|
MythTV
0.26-pre
|
00001 /* 00002 * This file is part of libbluray 00003 * Copyright (C) 2010 hpi1 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Lesser General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2.1 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public 00016 * License along with this library. If not, see 00017 * <http://www.gnu.org/licenses/>. 00018 */ 00019 00020 #include "file/file.h" 00021 #include "util/bits.h" 00022 #include "util/logging.h" 00023 #include "util/macro.h" 00024 #include "sound_parse.h" 00025 00026 #include <stdlib.h> 00027 00028 #define BCLK_SIG1 ('B' << 24 | 'C' << 16 | 'L' << 8 | 'K') 00029 #define BCLK_SIG2A ('0' << 24 | '2' << 16 | '0' << 8 | '0') 00030 #define BCLK_SIG2B ('0' << 24 | '1' << 16 | '0' << 8 | '0') 00031 00032 00033 static int _bclk_parse_header(BITSTREAM *bs, uint32_t *data_start, uint32_t *extension_data_start) 00034 { 00035 uint32_t sig1, sig2; 00036 00037 bs_seek_byte(bs, 0); 00038 00039 sig1 = bs_read(bs, 32); 00040 sig2 = bs_read(bs, 32); 00041 00042 if (sig1 != BCLK_SIG1 || 00043 (sig2 != BCLK_SIG2A && 00044 sig2 != BCLK_SIG2B)) { 00045 BD_DEBUG(DBG_NAV, "sound.bdmv failed signature match: expected BCLK0100 got %8.8s\n", bs->buf); 00046 return 0; 00047 } 00048 00049 *data_start = bs_read(bs, 32); 00050 *extension_data_start = bs_read(bs, 32); 00051 00052 return 1; 00053 } 00054 00055 static int _sound_parse_attributes(BITSTREAM *bs, SOUND_OBJECT *obj) 00056 { 00057 int i; 00058 00059 switch (i = bs_read(bs, 4)) { 00060 default: BD_DEBUG(DBG_NAV, "unknown channel configuration code %d\n", i); 00061 case 1: obj->num_channels = 1; 00062 break; 00063 case 3: obj->num_channels = 2; 00064 break; 00065 }; 00066 switch (i = bs_read(bs, 4)) { 00067 default: BD_DEBUG(DBG_NAV, "unknown sample rate code %d\n", i); 00068 case 1: obj->sample_rate = 48000; 00069 break; 00070 }; 00071 switch (i = bs_read(bs, 2)) { 00072 default: BD_DEBUG(DBG_NAV, "unknown bits per sample code %d\n", i); 00073 case 1: obj->bits_per_sample = 16; 00074 break; 00075 }; 00076 00077 bs_skip(bs, 6); /* padding */ 00078 00079 return 1; 00080 } 00081 00082 static int _sound_parse_index(BITSTREAM *bs, uint32_t *sound_data_index, SOUND_OBJECT *obj) 00083 { 00084 if (!_sound_parse_attributes(bs, obj)) 00085 return 0; 00086 00087 *sound_data_index = bs_read(bs, 32); 00088 obj->num_frames = bs_read(bs, 32); 00089 obj->num_frames /= (obj->bits_per_sample / 8) * obj->num_channels; 00090 00091 return 1; 00092 } 00093 00094 static int _sound_read_samples(BITSTREAM *bs, SOUND_OBJECT *obj) 00095 { 00096 uint32_t n; 00097 uint32_t num_samples = obj->num_frames * obj->num_channels; 00098 00099 obj->samples = calloc(num_samples, sizeof(uint16_t)); 00100 00101 for (n = 0; n < num_samples; n++) { 00102 obj->samples[n] = bs_read(bs, 16); 00103 } 00104 00105 return 1; 00106 } 00107 00108 void sound_free(SOUND_DATA **p) 00109 { 00110 if (p && *p) { 00111 00112 unsigned i; 00113 for (i = 0 ; i < (*p)->num_sounds; i++) { 00114 X_FREE((*p)->sounds[i].samples); 00115 } 00116 00117 X_FREE(*p); 00118 } 00119 } 00120 00121 SOUND_DATA *sound_parse(const char *file_name) 00122 { 00123 BITSTREAM bs; 00124 BD_FILE_H *fp; 00125 SOUND_DATA *data = NULL; 00126 uint16_t num_sounds; 00127 uint32_t data_len; 00128 int i; 00129 uint32_t data_start, extension_data_start; 00130 uint32_t *data_offsets = NULL; 00131 00132 fp = file_open(file_name, "rb"); 00133 if (!fp) { 00134 BD_DEBUG(DBG_NAV | DBG_CRIT, "error opening %s\n", file_name); 00135 return NULL; 00136 } 00137 00138 bs_init(&bs, fp); 00139 00140 if (!_bclk_parse_header(&bs, &data_start, &extension_data_start)) { 00141 BD_DEBUG(DBG_NAV | DBG_CRIT, "%s: invalid header\n", file_name); 00142 goto error; 00143 } 00144 00145 bs_seek_byte(&bs, 40); 00146 00147 data_len = bs_read(&bs, 32); 00148 bs_skip(&bs, 8); /* reserved */ 00149 num_sounds = bs_read(&bs, 8); 00150 00151 if (data_len < 1) { 00152 BD_DEBUG(DBG_NAV | DBG_CRIT, "%s: empty database\n", file_name); 00153 goto error; 00154 } 00155 00156 data_offsets = calloc(num_sounds, sizeof(uint32_t)); 00157 data = calloc(1, sizeof(SOUND_DATA) + num_sounds * sizeof(SOUND_OBJECT)); 00158 data->num_sounds = num_sounds; 00159 00160 /* parse headers */ 00161 00162 for (i = 0; i < data->num_sounds; i++) { 00163 if (!_sound_parse_index(&bs, data_offsets + i, &data->sounds[i])) { 00164 BD_DEBUG(DBG_NAV | DBG_CRIT, "%s: error parsing sound %d attribues\n", file_name, i); 00165 goto error; 00166 } 00167 } 00168 00169 /* read samples */ 00170 00171 for (i = 0; i < data->num_sounds; i++) { 00172 00173 bs_seek_byte(&bs, data_start + data_offsets[i]); 00174 00175 if (!_sound_read_samples(&bs, &data->sounds[i])) { 00176 BD_DEBUG(DBG_NAV | DBG_CRIT, "%s: error reading samples for sound %d\n", file_name, i); 00177 goto error; 00178 } 00179 } 00180 00181 X_FREE(data_offsets); 00182 file_close(fp); 00183 00184 return data; 00185 00186 error: 00187 sound_free(&data); 00188 X_FREE(data_offsets); 00189 file_close(fp); 00190 return NULL; 00191 }
1.7.6.1