00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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);
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);
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
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
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 }