From ce5bfca1526a9df8eb8034f846a6da93337af1ee Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sat, 7 Nov 2009 15:56:28 +0100 Subject: [PATCH] wma: Move computation of mdct coefficients into a separate funcion. This makes decode_block() almost readable.. --- wmadec_filter.c | 305 ++++++++++++++++++++++++------------------------ 1 file changed, 153 insertions(+), 152 deletions(-) diff --git a/wmadec_filter.c b/wmadec_filter.c index fccd8907..a404f35d 100644 --- a/wmadec_filter.c +++ b/wmadec_filter.c @@ -723,164 +723,17 @@ static int compute_high_band_values(struct private_wmadec_data *pwd, return 1; } -/** - * @return 0 if OK. 1 if last block of frame. return -1 if - * unrecorrable error. - */ -static int wma_decode_block(struct private_wmadec_data *pwd) +static void compute_mdct_coefficients(struct private_wmadec_data *pwd, + int bsize, int total_gain, int nb_coefs[MAX_CHANNELS]) { - int 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) { - n = wma_log2(pwd->nb_block_sizes - 1) + 1; - - if (pwd->reset_block_lengths) { - pwd->reset_block_lengths = 0; - v = get_bits(&pwd->gb, n); - if (v >= pwd->nb_block_sizes) - return -1; - pwd->prev_block_len_bits = pwd->frame_len_bits - v; - v = get_bits(&pwd->gb, n); - if (v >= pwd->nb_block_sizes) - return -1; - pwd->block_len_bits = pwd->frame_len_bits - v; - } else { - /* update block lengths */ - pwd->prev_block_len_bits = pwd->block_len_bits; - pwd->block_len_bits = pwd->next_block_len_bits; - } - v = get_bits(&pwd->gb, n); - if (v >= pwd->nb_block_sizes) - return -1; - pwd->next_block_len_bits = pwd->frame_len_bits - v; - } else { - /* fixed block len */ - pwd->next_block_len_bits = pwd->frame_len_bits; - pwd->prev_block_len_bits = pwd->frame_len_bits; - pwd->block_len_bits = pwd->frame_len_bits; - } - - /* now check if the block length is coherent with the frame length */ - pwd->block_len = 1 << pwd->block_len_bits; - if ((pwd->block_pos + pwd->block_len) > pwd->frame_len) - return -E_INCOHERENT_BLOCK_LEN; - - if (pwd->ahi.channels == 2) - pwd->ms_stereo = get_bit(&pwd->gb); - v = 0; - for (ch = 0; ch < pwd->ahi.channels; ch++) { - int a = get_bit(&pwd->gb); - pwd->channel_coded[ch] = a; - v |= a; - } - - bsize = pwd->frame_len_bits - pwd->block_len_bits; - - /* if no channel coded, no need to go further */ - /* XXX: fix potential framing problems */ - if (!v) - goto next; - - /* read total gain and extract corresponding number of bits for - coef escape coding */ - total_gain = 1; - for (;;) { - int a = get_bits(&pwd->gb, 7); - total_gain += a; - if (a != 127) - break; - } - - coef_nb_bits = wma_total_gain_to_bits(total_gain); - - /* compute number of coefficients */ - n = pwd->coefs_end[bsize] - pwd->coefs_start; - for (ch = 0; ch < pwd->ahi.channels; ch++) - nb_coefs[ch] = n; - - if (compute_high_band_values(pwd, bsize, nb_coefs) < 0) - return -1; - - /* 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 { - decode_exp_lsp(pwd, ch); - } - pwd->exponents_bsize[ch] = bsize; - } - } - } - - /* parse spectral coefficients : just RLE encoding */ - for (ch = 0; ch < pwd->ahi.channels; ch++) { - struct vlc *coef_vlc; - int level, run, tindex; - int16_t *ptr, *eptr; - const uint16_t *level_table, *run_table; - - if (!pwd->channel_coded[ch]) - continue; - /* - * special VLC tables are used for ms stereo because there is - * potentially less energy there - */ - tindex = (ch == 1 && pwd->ms_stereo); - coef_vlc = &pwd->coef_vlc[tindex]; - run_table = pwd->run_table[tindex]; - level_table = pwd->level_table[tindex]; - /* XXX: optimize */ - ptr = &pwd->coefs1[ch][0]; - eptr = ptr + nb_coefs[ch]; - memset(ptr, 0, pwd->block_len * sizeof(int16_t)); - for (;;) { - code = get_vlc(&pwd->gb, coef_vlc->table, - VLCBITS, VLCMAX); - if (code < 0) - return -1; - if (code == 1) /* EOB */ - break; - if (code == 0) { /* escape */ - level = get_bits(&pwd->gb, coef_nb_bits); - /* reading block_len_bits would be better */ - run = get_bits(&pwd->gb, pwd->frame_len_bits); - } else { /* normal code */ - run = run_table[code]; - level = level_table[code]; - } - if (!get_bit(&pwd->gb)) - level = -level; - ptr += run; - if (ptr >= eptr) { - PARA_ERROR_LOG("overflow in spectral RLE, ignoring\n"); - break; - } - *ptr++ = level; - if (ptr >= eptr) /* EOB can be omitted */ - break; - } - } - - /* normalize */ - { - int n4 = pwd->block_len / 2; - mdct_norm = 1.0 / (float) n4; - } + int ch; + float mdct_norm = 1.0 / (float)(pwd->block_len / 2); - /* 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; + int i, j, n, n1, last_high_band, esize; float exp_power[HIGH_BAND_MAX_SIZE]; coefs1 = pwd->coefs1[ch]; @@ -1029,6 +882,154 @@ static int wma_decode_block(struct private_wmadec_data *pwd) } } } +} + +/** + * @return 0 if OK. 1 if last block of frame. return -1 if + * unrecorrable error. + */ +static int wma_decode_block(struct private_wmadec_data *pwd) +{ + int n, v, ch, code, bsize; + int coef_nb_bits, total_gain; + int nb_coefs[MAX_CHANNELS]; + + /* compute current block length */ + if (pwd->use_variable_block_len) { + n = wma_log2(pwd->nb_block_sizes - 1) + 1; + + if (pwd->reset_block_lengths) { + pwd->reset_block_lengths = 0; + v = get_bits(&pwd->gb, n); + if (v >= pwd->nb_block_sizes) + return -1; + pwd->prev_block_len_bits = pwd->frame_len_bits - v; + v = get_bits(&pwd->gb, n); + if (v >= pwd->nb_block_sizes) + return -1; + pwd->block_len_bits = pwd->frame_len_bits - v; + } else { + /* update block lengths */ + pwd->prev_block_len_bits = pwd->block_len_bits; + pwd->block_len_bits = pwd->next_block_len_bits; + } + v = get_bits(&pwd->gb, n); + if (v >= pwd->nb_block_sizes) + return -1; + pwd->next_block_len_bits = pwd->frame_len_bits - v; + } else { + /* fixed block len */ + pwd->next_block_len_bits = pwd->frame_len_bits; + pwd->prev_block_len_bits = pwd->frame_len_bits; + pwd->block_len_bits = pwd->frame_len_bits; + } + + /* now check if the block length is coherent with the frame length */ + pwd->block_len = 1 << pwd->block_len_bits; + if ((pwd->block_pos + pwd->block_len) > pwd->frame_len) + return -E_INCOHERENT_BLOCK_LEN; + + if (pwd->ahi.channels == 2) + pwd->ms_stereo = get_bit(&pwd->gb); + v = 0; + for (ch = 0; ch < pwd->ahi.channels; ch++) { + int a = get_bit(&pwd->gb); + pwd->channel_coded[ch] = a; + v |= a; + } + + bsize = pwd->frame_len_bits - pwd->block_len_bits; + + /* if no channel coded, no need to go further */ + /* XXX: fix potential framing problems */ + if (!v) + goto next; + + /* read total gain and extract corresponding number of bits for + coef escape coding */ + total_gain = 1; + for (;;) { + int a = get_bits(&pwd->gb, 7); + total_gain += a; + if (a != 127) + break; + } + + coef_nb_bits = wma_total_gain_to_bits(total_gain); + + /* compute number of coefficients */ + n = pwd->coefs_end[bsize] - pwd->coefs_start; + for (ch = 0; ch < pwd->ahi.channels; ch++) + nb_coefs[ch] = n; + + if (compute_high_band_values(pwd, bsize, nb_coefs) < 0) + return -1; + + /* 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 { + decode_exp_lsp(pwd, ch); + } + pwd->exponents_bsize[ch] = bsize; + } + } + } + + /* parse spectral coefficients : just RLE encoding */ + for (ch = 0; ch < pwd->ahi.channels; ch++) { + struct vlc *coef_vlc; + int level, run, tindex; + int16_t *ptr, *eptr; + const uint16_t *level_table, *run_table; + + if (!pwd->channel_coded[ch]) + continue; + /* + * special VLC tables are used for ms stereo because there is + * potentially less energy there + */ + tindex = (ch == 1 && pwd->ms_stereo); + coef_vlc = &pwd->coef_vlc[tindex]; + run_table = pwd->run_table[tindex]; + level_table = pwd->level_table[tindex]; + /* XXX: optimize */ + ptr = &pwd->coefs1[ch][0]; + eptr = ptr + nb_coefs[ch]; + memset(ptr, 0, pwd->block_len * sizeof(int16_t)); + for (;;) { + code = get_vlc(&pwd->gb, coef_vlc->table, + VLCBITS, VLCMAX); + if (code < 0) + return -1; + if (code == 1) /* EOB */ + break; + if (code == 0) { /* escape */ + level = get_bits(&pwd->gb, coef_nb_bits); + /* reading block_len_bits would be better */ + run = get_bits(&pwd->gb, pwd->frame_len_bits); + } else { /* normal code */ + run = run_table[code]; + level = level_table[code]; + } + if (!get_bit(&pwd->gb)) + level = -level; + ptr += run; + if (ptr >= eptr) { + PARA_ERROR_LOG("overflow in spectral RLE, ignoring\n"); + break; + } + *ptr++ = level; + if (ptr >= eptr) /* EOB can be omitted */ + break; + } + } + + compute_mdct_coefficients(pwd, bsize, total_gain, nb_coefs); if (pwd->ms_stereo && pwd->channel_coded[1]) { float a, b; -- 2.39.2