X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=wmadec_filter.c;h=49f69b54d7601168ef195c938ae800a229f5ba19;hp=d574df35d3a9da3a75f25bf0069f6e887b8b547e;hb=3010ef96e10cb15d423eef8f9802fbed78744393;hpb=2d58aec6b7de7fdad67518568a79632b1944ee90 diff --git a/wmadec_filter.c b/wmadec_filter.c index d574df35..49f69b54 100644 --- a/wmadec_filter.c +++ b/wmadec_filter.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "para.h" #include "error.h" @@ -32,6 +33,7 @@ #include "ggo.h" #include "string.h" #include "sched.h" +#include "buffer_tree.h" #include "filter.h" #include "bitstream.h" #include "imdct.h" @@ -59,19 +61,25 @@ #define LSP_POW_BITS 7 struct private_wmadec_data { + /** Information contained in the audio file header. */ struct asf_header_info ahi; struct getbit_context gb; + /** Whether to use the bit reservoir. */ int use_bit_reservoir; + /** Whether to use variable block length. */ int use_variable_block_len; - int use_exp_vlc; ///< exponent coding: 0 = lsp, 1 = vlc + delta - int use_noise_coding; ///< true if perceptual noise is added + /** Whether to use exponent coding. */ + int use_exp_vlc; + /** Whether perceptual noise is added. */ + int use_noise_coding; int byte_offset_bits; struct vlc exp_vlc; int exponent_sizes[BLOCK_NB_SIZES]; uint16_t exponent_bands[BLOCK_NB_SIZES][25]; - int high_band_start[BLOCK_NB_SIZES]; ///< index of first coef in high band - int coefs_start; ///< first coded coef - int coefs_end[BLOCK_NB_SIZES]; ///< max number of coded coefficients + /** The index of the first coef in high band. */ + int high_band_start[BLOCK_NB_SIZES]; + /** Maximal number of coded coefficients. */ + int coefs_end[BLOCK_NB_SIZES]; int exponent_high_sizes[BLOCK_NB_SIZES]; int exponent_high_bands[BLOCK_NB_SIZES][HIGH_BAND_MAX_SIZE]; struct vlc hgain_vlc; @@ -85,20 +93,31 @@ struct private_wmadec_data { uint16_t *run_table[2]; uint16_t *level_table[2]; const struct coef_vlc_table *coef_vlcs[2]; - /* frame info */ - int frame_len; ///< frame length in samples - int frame_len_bits; ///< frame_len = 1 << frame_len_bits - int nb_block_sizes; ///< number of block sizes + /** Frame length in samples. */ + int frame_len; + /** log2 of frame_len. */ + int frame_len_bits; + /** Number of block sizes. */ + int nb_block_sizes; /* block info */ int reset_block_lengths; - int block_len_bits; ///< log2 of current block length - int next_block_len_bits; ///< log2 of next block length - int prev_block_len_bits; ///< log2 of prev block length - int block_len; ///< block length in samples - int block_pos; ///< current position in frame - uint8_t ms_stereo; ///< true if mid/side stereo mode - uint8_t channel_coded[MAX_CHANNELS]; ///< true if channel is coded - int exponents_bsize[MAX_CHANNELS]; ///< log2 ratio frame/exp. length + /** log2 of current block length. */ + int block_len_bits; + /** log2 of next block length. */ + int next_block_len_bits; + /** log2 of previous block length. */ + int prev_block_len_bits; + /** Block length in samples. */ + int block_len; + /** Current position in frame. */ + int block_pos; + /** True if mid/side stereo mode. */ + uint8_t ms_stereo; + /** True if channel is coded. */ + uint8_t channel_coded[MAX_CHANNELS]; + /** log2 ratio frame/exp. length. */ + int exponents_bsize[MAX_CHANNELS]; + float exponents[MAX_CHANNELS][BLOCK_MAX_SIZE]; float max_exponent[MAX_CHANNELS]; int16_t coefs1[MAX_CHANNELS][BLOCK_MAX_SIZE]; @@ -106,9 +125,9 @@ struct private_wmadec_data { float output[BLOCK_MAX_SIZE * 2]; struct mdct_context *mdct_ctx[BLOCK_NB_SIZES]; float *windows[BLOCK_NB_SIZES]; - /* output buffer for one frame and the last for IMDCT windowing */ + /** Output buffer for one frame and the last for IMDCT windowing. */ float frame_out[MAX_CHANNELS][BLOCK_MAX_SIZE * 2]; - /* last frame info */ + /** Last frame info. */ uint8_t last_superframe[MAX_CODED_SUPERFRAME_SIZE + 4]; /* padding added */ int last_bitoffset; int last_superframe_len; @@ -131,16 +150,17 @@ struct private_wmadec_data { #define VLCBITS 9 #define VLCMAX ((22 + VLCBITS - 1) / VLCBITS) -DECLARE_ALIGNED(16, float, ff_sine_128[128]); -DECLARE_ALIGNED(16, float, ff_sine_256[256]); -DECLARE_ALIGNED(16, float, ff_sine_512[512]); -DECLARE_ALIGNED(16, float, ff_sine_1024[1024]); -DECLARE_ALIGNED(16, float, ff_sine_2048[2048]); -DECLARE_ALIGNED(16, float, ff_sine_4096[4096]); +#define SINE_WINDOW(x) float sine_ ## x[x] __a_aligned(16) + +SINE_WINDOW(128); +SINE_WINDOW(256); +SINE_WINDOW(512); +SINE_WINDOW(1024); +SINE_WINDOW(2048); +SINE_WINDOW(4096); -static float *ff_sine_windows[6] = { - ff_sine_128, ff_sine_256, ff_sine_512, ff_sine_1024, - ff_sine_2048, ff_sine_4096 +static float *sine_windows[6] = { + sine_128, sine_256, sine_512, sine_1024, sine_2048, sine_4096 }; /* Generate a sine window. */ @@ -207,7 +227,6 @@ static void compute_scale_factor_band_sizes(struct private_wmadec_data *pwd, int a, b, pos, lpos, k, block_len, i, j, n; const uint8_t *table; - pwd->coefs_start = 0; for (k = 0; k < pwd->nb_block_sizes; k++) { block_len = pwd->frame_len >> k; @@ -285,13 +304,12 @@ static int wma_init(struct private_wmadec_data *pwd) return -E_WMA_BAD_PARAMS; /* compute MDCT block size */ - if (ahi->sample_rate <= 16000) { + if (ahi->sample_rate <= 16000) pwd->frame_len_bits = 9; - } else if (ahi->sample_rate <= 22050) { + else if (ahi->sample_rate <= 22050) pwd->frame_len_bits = 10; - } else { + else pwd->frame_len_bits = 11; - } pwd->frame_len = 1 << pwd->frame_len_bits; if (pwd->use_variable_block_len) { int nb_max, nb; @@ -348,24 +366,22 @@ static int wma_init(struct private_wmadec_data *pwd) high_freq = high_freq * 0.5; else high_freq = high_freq * 0.3; - } else if (sample_rate1 == 11025) { + } else if (sample_rate1 == 11025) high_freq = high_freq * 0.7; - } else if (sample_rate1 == 8000) { - if (bps <= 0.625) { + else if (sample_rate1 == 8000) { + if (bps <= 0.625) high_freq = high_freq * 0.5; - } else if (bps > 0.75) { + else if (bps > 0.75) pwd->use_noise_coding = 0; - } else { + else high_freq = high_freq * 0.65; - } } else { - if (bps >= 0.8) { + if (bps >= 0.8) high_freq = high_freq * 0.75; - } else if (bps >= 0.6) { + else if (bps >= 0.6) high_freq = high_freq * 0.6; - } else { + else high_freq = high_freq * 0.5; - } } PARA_INFO_LOG("channels=%d sample_rate=%d " "bitrate=%d block_align=%d\n", @@ -383,8 +399,8 @@ static int wma_init(struct private_wmadec_data *pwd) for (i = 0; i < pwd->nb_block_sizes; i++) { int n; n = 1 << (pwd->frame_len_bits - i); - sine_window_init(ff_sine_windows[pwd->frame_len_bits - i - 7], n); - pwd->windows[i] = ff_sine_windows[pwd->frame_len_bits - i - 7]; + sine_window_init(sine_windows[pwd->frame_len_bits - i - 7], n); + pwd->windows[i] = sine_windows[pwd->frame_len_bits - i - 7]; } pwd->reset_block_lengths = 1; @@ -481,15 +497,15 @@ static int wma_decode_init(char *initial_buf, int len, struct private_wmadec_dat if (pwd->use_noise_coding) { PARA_INFO_LOG("using noise coding\n"); init_vlc(&pwd->hgain_vlc, HGAINVLCBITS, - sizeof(ff_wma_hgain_huffbits), ff_wma_hgain_huffbits, - ff_wma_hgain_huffcodes, 2); + sizeof(wma_hgain_huffbits), wma_hgain_huffbits, + wma_hgain_huffcodes, 2); } if (pwd->use_exp_vlc) { PARA_INFO_LOG("using exp_vlc\n"); init_vlc(&pwd->exp_vlc, EXPVLCBITS, - sizeof(ff_wma_scale_huffbits), ff_wma_scale_huffbits, - ff_wma_scale_huffcodes, 4); + sizeof(wma_scale_huffbits), wma_scale_huffbits, + wma_scale_huffcodes, 4); } else { PARA_INFO_LOG("using curve\n"); wma_lsp_to_curve_init(pwd, pwd->frame_len); @@ -560,7 +576,7 @@ static void decode_exp_lsp(struct private_wmadec_data *pwd, int ch) val = get_bits(&pwd->gb, 3); else val = get_bits(&pwd->gb, 4); - lsp_coefs[i] = ff_wma_lsp_codebook[i][val]; + lsp_coefs[i] = wma_lsp_codebook[i][val]; } wma_lsp_to_curve(pwd, pwd->exponents[ch], &pwd->max_exponent[ch], @@ -584,7 +600,7 @@ static int decode_exp_vlc(struct private_wmadec_data *pwd, int ch) while (q < q_end) { code = get_vlc(&pwd->gb, pwd->exp_vlc.table, EXPVLCBITS, EXPMAX); if (code < 0) - return -1; + return code; /* NOTE: this offset is the same as MPEG4 AAC ! */ last_exp += code - 60; /* XXX: use a table */ @@ -677,16 +693,161 @@ static int wma_total_gain_to_bits(int total_gain) return 9; } +static int compute_high_band_values(struct private_wmadec_data *pwd, + int bsize, int nb_coefs[MAX_CHANNELS]) +{ + int ch; + + if (!pwd->use_noise_coding) + return 0; + for (ch = 0; ch < pwd->ahi.channels; ch++) { + int i, m, a; + if (!pwd->channel_coded[ch]) + continue; + m = pwd->exponent_high_sizes[bsize]; + for (i = 0; i < m; i++) { + a = get_bit(&pwd->gb); + pwd->high_band_coded[ch][i] = a; + if (!a) + continue; + nb_coefs[ch] -= pwd->exponent_high_bands[bsize][i]; + } + } + for (ch = 0; ch < pwd->ahi.channels; ch++) { + int i, n, val; + if (!pwd->channel_coded[ch]) + continue; + n = pwd->exponent_high_sizes[bsize]; + val = (int)0x80000000; + for (i = 0; i < n; i++) { + if (!pwd->high_band_coded[ch][i]) + continue; + if (val == (int)0x80000000) + val = get_bits(&pwd->gb, 7) - 19; + else { + int code = get_vlc(&pwd->gb, + pwd->hgain_vlc.table, HGAINVLCBITS, + HGAINMAX); + if (code < 0) + return code; + val += code - 18; + } + pwd->high_band_values[ch][i] = val; + } + } + return 1; +} + +static void compute_mdct_coefficients(struct private_wmadec_data *pwd, + int bsize, int total_gain, int nb_coefs[MAX_CHANNELS]) +{ + int ch; + float mdct_norm = 1.0 / (pwd->block_len / 2); + + for (ch = 0; ch < pwd->ahi.channels; ch++) { + int16_t *coefs1; + float *coefs, *exponents, mult, mult1, noise; + int i, j, n, n1, last_high_band, esize; + float exp_power[HIGH_BAND_MAX_SIZE]; + + if (!pwd->channel_coded[ch]) + continue; + coefs1 = pwd->coefs1[ch]; + exponents = pwd->exponents[ch]; + esize = pwd->exponents_bsize[ch]; + mult = pow(10, total_gain * 0.05) / pwd->max_exponent[ch]; + mult *= mdct_norm; + coefs = pwd->coefs[ch]; + if (!pwd->use_noise_coding) { + /* XXX: optimize more */ + n = nb_coefs[ch]; + for (i = 0; i < n; i++) + *coefs++ = coefs1[i] * + exponents[i << bsize >> esize] * mult; + n = pwd->block_len - pwd->coefs_end[bsize]; + for (i = 0; i < n; i++) + *coefs++ = 0.0; + continue; + } + mult1 = mult; + n1 = pwd->exponent_high_sizes[bsize]; + /* compute power of high bands */ + exponents = pwd->exponents[ch] + + (pwd->high_band_start[bsize] << bsize); + last_high_band = 0; /* avoid warning */ + for (j = 0; j < n1; j++) { + n = pwd->exponent_high_bands[ + pwd->frame_len_bits - pwd->block_len_bits][j]; + if (pwd->high_band_coded[ch][j]) { + float e2, val; + e2 = 0; + for (i = 0; i < n; i++) { + val = exponents[i << bsize >> esize]; + e2 += val * val; + } + exp_power[j] = e2 / n; + last_high_band = j; + } + exponents += n << bsize; + } + /* main freqs and high freqs */ + exponents = pwd->exponents[ch]; + for (j = -1; j < n1; j++) { + if (j < 0) + n = pwd->high_band_start[bsize]; + else + n = pwd->exponent_high_bands[pwd->frame_len_bits + - pwd->block_len_bits][j]; + if (j >= 0 && pwd->high_band_coded[ch][j]) { + /* use noise with specified power */ + mult1 = sqrt(exp_power[j] + / exp_power[last_high_band]); + /* XXX: use a table */ + mult1 = mult1 * pow(10, + pwd->high_band_values[ch][j] * 0.05); + mult1 /= (pwd->max_exponent[ch] * pwd->noise_mult); + mult1 *= mdct_norm; + for (i = 0; i < n; i++) { + noise = pwd->noise_table[pwd->noise_index]; + pwd->noise_index = (pwd->noise_index + 1) + & (NOISE_TAB_SIZE - 1); + *coefs++ = noise * exponents[ + i << bsize >> esize] * mult1; + } + exponents += n << bsize; + } else { + /* coded values + small noise */ + for (i = 0; i < n; i++) { + noise = pwd->noise_table[pwd->noise_index]; + pwd->noise_index = (pwd->noise_index + 1) + & (NOISE_TAB_SIZE - 1); + *coefs++ = ((*coefs1++) + noise) * + exponents[i << bsize >> esize] + * mult; + } + exponents += n << bsize; + } + } + /* very high freqs: noise */ + n = pwd->block_len - pwd->coefs_end[bsize]; + mult1 = mult * exponents[((-1 << bsize)) >> esize]; + for (i = 0; i < n; i++) { + *coefs++ = pwd->noise_table[pwd->noise_index] * mult1; + pwd->noise_index = (pwd->noise_index + 1) + & (NOISE_TAB_SIZE - 1); + } + } +} + /** - * @return 0 if OK. 1 if last block of frame. return -1 if - * unrecorrable error. + * Returns 0 if OK, 1 if last block of frame, negative on uncorrectable + * errors. */ static int wma_decode_block(struct private_wmadec_data *pwd) { - int n, v, ch, code, bsize; + int ret, n, v, ch, code, bsize; int coef_nb_bits, total_gain; int nb_coefs[MAX_CHANNELS]; - float mdct_norm; /* compute current block length */ if (pwd->use_variable_block_len) { @@ -696,11 +857,11 @@ static int wma_decode_block(struct private_wmadec_data *pwd) pwd->reset_block_lengths = 0; v = get_bits(&pwd->gb, n); if (v >= pwd->nb_block_sizes) - return -1; + return -E_WMA_BLOCK_SIZE; pwd->prev_block_len_bits = pwd->frame_len_bits - v; v = get_bits(&pwd->gb, n); if (v >= pwd->nb_block_sizes) - return -1; + return -E_WMA_BLOCK_SIZE; pwd->block_len_bits = pwd->frame_len_bits - v; } else { /* update block lengths */ @@ -709,7 +870,7 @@ static int wma_decode_block(struct private_wmadec_data *pwd) } v = get_bits(&pwd->gb, n); if (v >= pwd->nb_block_sizes) - return -1; + return -E_WMA_BLOCK_SIZE; pwd->next_block_len_bits = pwd->frame_len_bits - v; } else { /* fixed block len */ @@ -739,8 +900,10 @@ static int wma_decode_block(struct private_wmadec_data *pwd) if (!v) goto next; - /* read total gain and extract corresponding number of bits for - coef escape coding */ + /* + * Read total gain and extract corresponding number of bits for coef + * escape coding. + */ total_gain = 1; for (;;) { int a = get_bits(&pwd->gb, 7); @@ -752,70 +915,24 @@ static int wma_decode_block(struct private_wmadec_data *pwd) coef_nb_bits = wma_total_gain_to_bits(total_gain); /* compute number of coefficients */ - n = pwd->coefs_end[bsize] - pwd->coefs_start; + n = pwd->coefs_end[bsize]; for (ch = 0; ch < pwd->ahi.channels; ch++) nb_coefs[ch] = n; - /* complex coding */ - if (pwd->use_noise_coding) { - for (ch = 0; ch < pwd->ahi.channels; ch++) { - if (pwd->channel_coded[ch]) { - int i, m, a; - m = pwd->exponent_high_sizes[bsize]; - for (i = 0; i < m; i++) { - a = get_bit(&pwd->gb); - pwd->high_band_coded[ch][i] = a; - /* if noise coding, the coefficients are not transmitted */ - if (a) - nb_coefs[ch] -= - pwd-> - exponent_high_bands[bsize] - [i]; - } - } - } - for (ch = 0; ch < pwd->ahi.channels; ch++) { - if (pwd->channel_coded[ch]) { - int i, val; - - n = pwd->exponent_high_sizes[bsize]; - val = (int) 0x80000000; - for (i = 0; i < n; i++) { - if (pwd->high_band_coded[ch][i]) { - if (val == (int) 0x80000000) { - val = - get_bits(&pwd->gb, - 7) - 19; - } else { - code = - get_vlc(&pwd->gb, - pwd-> - hgain_vlc. - table, - HGAINVLCBITS, - HGAINMAX); - if (code < 0) - return -1; - val += code - 18; - } - pwd->high_band_values[ch][i] = - val; - } - } - } - } - } + ret = compute_high_band_values(pwd, bsize, nb_coefs); + if (ret < 0) + return ret; /* exponents can be reused in short blocks. */ if ((pwd->block_len_bits == pwd->frame_len_bits) || get_bit(&pwd->gb)) { for (ch = 0; ch < pwd->ahi.channels; ch++) { if (pwd->channel_coded[ch]) { if (pwd->use_exp_vlc) { - if (decode_exp_vlc(pwd, ch) < 0) - return -1; - } else { + ret = decode_exp_vlc(pwd, ch); + if (ret < 0) + return ret; + } else decode_exp_lsp(pwd, ch); - } pwd->exponents_bsize[ch] = bsize; } } @@ -846,7 +963,7 @@ static int wma_decode_block(struct private_wmadec_data *pwd) code = get_vlc(&pwd->gb, coef_vlc->table, VLCBITS, VLCMAX); if (code < 0) - return -1; + return code; if (code == 1) /* EOB */ break; if (code == 0) { /* escape */ @@ -869,172 +986,10 @@ static int wma_decode_block(struct private_wmadec_data *pwd) break; } } - - /* normalize */ - { - int n4 = pwd->block_len / 2; - mdct_norm = 1.0 / (float) n4; - } - - /* finally compute the MDCT coefficients */ - for (ch = 0; ch < pwd->ahi.channels; ch++) { - if (pwd->channel_coded[ch]) { - int16_t *coefs1; - float *coefs, *exponents, mult, mult1, noise; - int i, j, n1, last_high_band, esize; - float exp_power[HIGH_BAND_MAX_SIZE]; - - coefs1 = pwd->coefs1[ch]; - exponents = pwd->exponents[ch]; - esize = pwd->exponents_bsize[ch]; - mult = pow(10, total_gain * 0.05) / pwd->max_exponent[ch]; - mult *= mdct_norm; - coefs = pwd->coefs[ch]; - if (pwd->use_noise_coding) { - mult1 = mult; - /* very low freqs : noise */ - for (i = 0; i < pwd->coefs_start; i++) { - *coefs++ = - pwd->noise_table[pwd->noise_index] * - exponents[i << bsize >> esize] * - mult1; - pwd->noise_index = - (pwd->noise_index + - 1) & (NOISE_TAB_SIZE - 1); - } - - n1 = pwd->exponent_high_sizes[bsize]; - - /* compute power of high bands */ - exponents = pwd->exponents[ch] + - (pwd->high_band_start[bsize] << bsize); - last_high_band = 0; /* avoid warning */ - for (j = 0; j < n1; j++) { - n = pwd->exponent_high_bands[pwd-> - frame_len_bits - - - pwd-> - block_len_bits] - [j]; - if (pwd->high_band_coded[ch][j]) { - float e2, val; - e2 = 0; - for (i = 0; i < n; i++) { - val = exponents[i << bsize - >> esize]; - e2 += val * val; - } - exp_power[j] = e2 / n; - last_high_band = j; - } - exponents += n << bsize; - } - - /* main freqs and high freqs */ - exponents = - pwd->exponents[ch] + - (pwd->coefs_start << bsize); - for (j = -1; j < n1; j++) { - if (j < 0) { - n = pwd->high_band_start[bsize] - - pwd->coefs_start; - } else { - n = pwd->exponent_high_bands[pwd-> - frame_len_bits - - - pwd-> - block_len_bits] - [j]; - } - if (j >= 0 && pwd->high_band_coded[ch][j]) { - /* use noise with specified power */ - mult1 = - sqrt(exp_power[j] / - exp_power - [last_high_band]); - /* XXX: use a table */ - mult1 = - mult1 * pow(10, - pwd-> - high_band_values - [ch][j] * 0.05); - mult1 = - mult1 / - (pwd->max_exponent[ch] * - pwd->noise_mult); - mult1 *= mdct_norm; - for (i = 0; i < n; i++) { - noise = - pwd->noise_table[pwd-> - noise_index]; - pwd->noise_index = - (pwd->noise_index + - 1) & - (NOISE_TAB_SIZE - - 1); - *coefs++ = - noise * - exponents[i << bsize - >> esize] - * mult1; - } - exponents += n << bsize; - } else { - /* coded values + small noise */ - for (i = 0; i < n; i++) { - noise = - pwd->noise_table[pwd-> - noise_index]; - pwd->noise_index = - (pwd->noise_index + - 1) & - (NOISE_TAB_SIZE - - 1); - *coefs++ = - ((*coefs1++) + - noise) * - exponents[i << bsize - >> esize] - * mult; - } - exponents += n << bsize; - } - } - - /* very high freqs : noise */ - n = pwd->block_len - pwd->coefs_end[bsize]; - mult1 = - mult * exponents[((-1 << bsize)) >> esize]; - for (i = 0; i < n; i++) { - *coefs++ = - pwd->noise_table[pwd->noise_index] * - mult1; - pwd->noise_index = - (pwd->noise_index + - 1) & (NOISE_TAB_SIZE - 1); - } - } else { - /* XXX: optimize more */ - for (i = 0; i < pwd->coefs_start; i++) - *coefs++ = 0.0; - n = nb_coefs[ch]; - for (i = 0; i < n; i++) { - *coefs++ = - coefs1[i] * - exponents[i << bsize >> esize] * - mult; - } - n = pwd->block_len - pwd->coefs_end[bsize]; - for (i = 0; i < n; i++) - *coefs++ = 0.0; - } - } - } - + compute_mdct_coefficients(pwd, bsize, total_gain, nb_coefs); if (pwd->ms_stereo && pwd->channel_coded[1]) { float a, b; int i; - /* * Nominal case for ms stereo: we do it before mdct. * @@ -1053,7 +1008,6 @@ static int wma_decode_block(struct private_wmadec_data *pwd) pwd->coefs[1][i] = a - b; } } - next: for (ch = 0; ch < pwd->ahi.channels; ch++) { int n4, index; @@ -1105,7 +1059,7 @@ static int wma_decode_frame(struct private_wmadec_data *pwd, int16_t *samples) for (;;) { ret = wma_decode_block(pwd); if (ret < 0) - return -1; + return ret; if (ret) break; } @@ -1133,7 +1087,6 @@ static int wma_decode_superframe(struct private_wmadec_data *pwd, void *data, { int ret; int16_t *samples; - static int frame_count; if (buf_size == 0) { pwd->last_superframe_len = 0; @@ -1184,10 +1137,9 @@ static int wma_decode_superframe(struct private_wmadec_data *pwd, void *data, * This frame is stored in the last superframe and in * the current one. */ - ret = -E_WMA_DECODE; - if (wma_decode_frame(pwd, samples) < 0) + ret = wma_decode_frame(pwd, samples); + if (ret < 0) goto fail; - frame_count++; samples += pwd->ahi.channels * pwd->frame_len; } @@ -1201,10 +1153,9 @@ static int wma_decode_superframe(struct private_wmadec_data *pwd, void *data, pwd->reset_block_lengths = 1; for (i = 0; i < nb_frames; i++) { - ret = -E_WMA_DECODE; - if (wma_decode_frame(pwd, samples) < 0) + ret = wma_decode_frame(pwd, samples); + if (ret < 0) goto fail; - frame_count++; samples += pwd->ahi.channels * pwd->frame_len; } @@ -1225,16 +1176,14 @@ static int wma_decode_superframe(struct private_wmadec_data *pwd, void *data, if (pwd->ahi.channels * pwd->frame_len * sizeof(int16_t) > *data_size) goto fail; /* single frame decode */ - ret = -E_WMA_DECODE; - if (wma_decode_frame(pwd, samples) < 0) + ret = wma_decode_frame(pwd, samples); + if (ret < 0) goto fail; - frame_count++; samples += pwd->ahi.channels * pwd->frame_len; } - PARA_DEBUG_LOG("frame_count: %d frame_len: %d, block_len: %d, " - "outbytes: %d, eaten: %d\n", - frame_count, pwd->frame_len, pwd->block_len, - (int8_t *) samples - (int8_t *) data, pwd->ahi.block_align); + PARA_DEBUG_LOG("frame_len: %d, block_len: %d, outbytes: %d, eaten: %d\n", + pwd->frame_len, pwd->block_len, + (int)((int8_t *)samples - (int8_t *)data), pwd->ahi.block_align); *data_size = (int8_t *)samples - (int8_t *)data; return pwd->ahi.block_align; fail: @@ -1243,14 +1192,107 @@ fail: return ret; } +static void wmadec_close(struct filter_node *fn) +{ + struct private_wmadec_data *pwd = fn->private_data; + + if (!pwd) + return; + wmadec_cleanup(pwd); + free(fn->buf); + fn->buf = NULL; + free(fn->private_data); + fn->private_data = NULL; +} + +static int wmadec_execute(struct btr_node *btrn, const char *cmd, char **result) +{ + struct filter_node *fn = btr_context(btrn); + struct private_wmadec_data *pwd = fn->private_data; + + if (!strcmp(cmd, "samplerate")) { + if (pwd->ahi.sample_rate == 0) + return -ERRNO_TO_PARA_ERROR(ENAVAIL); + *result = make_message("%u", pwd->ahi.sample_rate); + return 1; + } + if (!strcmp(cmd, "channels")) { + if (pwd->ahi.channels == 0) + return -ERRNO_TO_PARA_ERROR(ENAVAIL); + *result = make_message("%u", pwd->ahi.channels); + return 1; + } + return -ERRNO_TO_PARA_ERROR(ENOTSUP); +} + +#define WMA_OUTPUT_BUFFER_SIZE (128 * 1024) + +static void wmadec_post_select(__a_unused struct sched *s, struct task *t) +{ + struct filter_node *fn = container_of(t, struct filter_node, task); + int ret, converted; + struct private_wmadec_data *pwd = fn->private_data; + struct btr_node *btrn = fn->btrn; + size_t len; + char *in; + +next_buffer: + converted = 0; + t->error = 0; + ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL); + if (ret < 0) + goto err; + if (ret == 0) + return; + btr_merge(btrn, fn->min_iqs); + len = btr_next_buffer(btrn, (char **)&in); + ret = -E_WMADEC_EOF; + if (len < fn->min_iqs) + goto err; + if (!pwd) { + ret = wma_decode_init(in, len, &pwd); + if (ret < 0) + goto err; + if (ret == 0) { + fn->min_iqs += 4096; + goto next_buffer; + } + fn->min_iqs = WMA_FRAME_SKIP + pwd->ahi.block_align; + fn->private_data = pwd; + converted = pwd->ahi.header_len; + goto success; + } + for (;;) { + char *out; + int out_size = WMA_OUTPUT_BUFFER_SIZE; + if (converted + fn->min_iqs > len) + break; + out = para_malloc(WMA_OUTPUT_BUFFER_SIZE); + ret = wma_decode_superframe(pwd, out, + &out_size, (uint8_t *)in + converted + WMA_FRAME_SKIP, + len - WMA_FRAME_SKIP); + if (ret < 0) { + free(out); + goto err; + } + btr_add_output(out, out_size, btrn); + converted += ret + WMA_FRAME_SKIP; + } +success: + btr_consume(btrn, converted); + goto next_buffer; +err: + assert(ret < 0); + t->error = ret; + btr_remove_node(btrn); +} + static ssize_t wmadec_convert(char *inbuffer, size_t len, struct filter_node *fn) { - int ret, out_size = fn->bufsize - fn->loaded; + int ret, converted = 0; struct private_wmadec_data *pwd = fn->private_data; - if (out_size < 128 * 1024) - return 0; if (len <= WMA_FRAME_SKIP) return 0; if (!pwd) { @@ -1262,29 +1304,22 @@ static ssize_t wmadec_convert(char *inbuffer, size_t len, fn->fc->samplerate = pwd->ahi.sample_rate; return pwd->ahi.header_len; } - /* skip 31 bytes */ - if (len <= WMA_FRAME_SKIP + pwd->ahi.block_align) - return 0; - ret = wma_decode_superframe(pwd, fn->buf + fn->loaded, - &out_size, (uint8_t *)inbuffer + WMA_FRAME_SKIP, - len - WMA_FRAME_SKIP); - if (ret < 0) - return ret; - fn->loaded += out_size; - return ret + WMA_FRAME_SKIP; -} - -static void wmadec_close(struct filter_node *fn) -{ - struct private_wmadec_data *pwd = fn->private_data; - - if (!pwd) - return; - wmadec_cleanup(pwd); - free(fn->buf); - fn->buf = NULL; - free(fn->private_data); - fn->private_data = NULL; + for (;;) { + int out_size; + if (converted + WMA_FRAME_SKIP + pwd->ahi.block_align > len) + break; + out_size = fn->bufsize - fn->loaded; + if (out_size < 128 * 1024) + break; + ret = wma_decode_superframe(pwd, fn->buf + fn->loaded, + &out_size, (uint8_t *)inbuffer + converted + WMA_FRAME_SKIP, + len - WMA_FRAME_SKIP); + if (ret < 0) + return ret; + fn->loaded += out_size; + converted += ret + WMA_FRAME_SKIP; + } + return converted; } static void wmadec_open(struct filter_node *fn) @@ -1293,6 +1328,7 @@ static void wmadec_open(struct filter_node *fn) fn->buf = para_malloc(fn->bufsize); fn->private_data = NULL; fn->loaded = 0; + fn->min_iqs = 4096; } /** @@ -1305,4 +1341,7 @@ void wmadec_filter_init(struct filter *f) f->open = wmadec_open; f->close = wmadec_close; f->convert = wmadec_convert; + f->execute = wmadec_execute; + f->pre_select = generic_filter_pre_select; + f->post_select = wmadec_post_select; }