MythTV  0.26-pre
sound_parse.c
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends