📄 wmadeci.c
字号:
{ scale[i] = scale[j]; j += jincr; } }}/* compute x^-0.25 with an exponent and mantissa table. We use linear interpolation to reduce the mantissa table size at a small speed expense (linear interpolation approximately doubles the number of bits of precision). */static inline fixed32 pow_m1_4(WMADecodeContext *s, fixed32 x){ union { fixed64 f; unsigned int v; } u, t; unsigned int e, m; fixed64 a, b; u.f = x; e = u.v >> 23; m = (u.v >> (23 - LSP_POW_BITS)) & ((1 << LSP_POW_BITS) - 1); /* build interpolation scale: 1 <= t < 2. */ t.v = ((u.v << LSP_POW_BITS) & ((1 << 23) - 1)) | (127 << 23); a = s->lsp_pow_m_table1[m]; b = s->lsp_pow_m_table2[m]; return lsp_pow_e_table[e] * (a + b * t.f);}static void wma_lsp_to_curve_init(WMADecodeContext *s, int frame_len){ fixed32 wdel, a, b; int i, m; wdel = fixdiv32(M_PI_F, itofix32(frame_len)); for (i=0; i<frame_len; ++i) { s->lsp_cos_table[i] = 0x20000 * fixcos32(wdel * i); } /* NOTE: these two tables are needed to avoid two operations in pow_m1_4 */ b = itofix32(1); int ix = 0; for(i=(1 << LSP_POW_BITS) - 1;i>=0;i--) { m = (1 << LSP_POW_BITS) + i; a = m * (0x8000 / (1 << LSP_POW_BITS)); /* PJJ */ a = pow_a_table[++ix]; /* PJJ : further refinement */ s->lsp_pow_m_table1[i] = 2 * a - b; s->lsp_pow_m_table2[i] = b - a; b = a; }}/* NOTE: We use the same code as Vorbis here */static void wma_lsp_to_curve(WMADecodeContext *s, fixed32 *out, fixed32 *val_max_ptr, int n, fixed32 *lsp){ int i, j; fixed32 p, q, w, v, val_max; val_max = 0; for(i=0;i<n;++i) { p = 0x8000; q = 0x8000; w = s->lsp_cos_table[i]; for (j=1;j<NB_LSP_COEFS;j+=2) { q *= w - lsp[j - 1]; p *= w - lsp[j]; } p *= p * (0x20000 - w); q *= q * (0x20000 + w); v = p + q; v = pow_m1_4(s, v); /* PJJ */ if (v > val_max) { val_max = v; } out[i] = v; } *val_max_ptr = val_max;}void free_vlc(VLC *vlc){ av_free(vlc->table);}/* decode exponents coded with LSP coefficients (same idea as Vorbis) */static void decode_exp_lsp(WMADecodeContext *s, int ch){ fixed32 lsp_coefs[NB_LSP_COEFS]; int val, i; for (i = 0; i < NB_LSP_COEFS; ++i) { if (i == 0 || i >= 8) { val = get_bits(&s->gb, 3); } else { val = get_bits(&s->gb, 4); } lsp_coefs[i] = lsp_codebook[i][val]; } wma_lsp_to_curve(s, s->exponents[ch], &s->max_exponent[ch], s->block_len, lsp_coefs);}/* decode exponents coded with VLC codes */static int decode_exp_vlc(WMADecodeContext *s, int ch){ int last_exp, n, code; const uint16_t *ptr, *band_ptr; fixed32 v, max_scale; fixed32 *q,*q_end; band_ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits]; ptr = band_ptr; q = s->exponents[ch]; q_end = q + s->block_len; max_scale = 0; if (s->version == 1) { last_exp = get_bits(&s->gb, 5) + 10; /* XXX: use a table */ v = pow_10_to_yover16[last_exp]; max_scale = v; n = *ptr++; do { *q++ = v; } while (--n); } last_exp = 36; while (q < q_end) { code = get_vlc(&s->gb, &s->exp_vlc); if (code < 0) { return -1; } /* NOTE: this offset is the same as MPEG4 AAC ! */ last_exp += code - 60; /* XXX: use a table */ v = pow_10_to_yover16[last_exp]; if (v > max_scale) { max_scale = v; } n = *ptr++; do { *q++ = v; } while (--n); } s->max_exponent[ch] = max_scale; return 0;}/* return 0 if OK. return 1 if last block of frame. return -1 if unrecorrable error. */static int wma_decode_block(WMADecodeContext *s){ int n, v, a, ch, code, bsize; int coef_nb_bits, total_gain, parse_exponents; fixed32 window[BLOCK_MAX_SIZE * 2]; int nb_coefs[MAX_CHANNELS]; fixed32 mdct_norm; /* compute current block length */ if (s->use_variable_block_len) { n = av_log2(s->nb_block_sizes - 1) + 1; if (s->reset_block_lengths) { s->reset_block_lengths = 0; v = get_bits(&s->gb, n); if (v >= s->nb_block_sizes) { return -1; } s->prev_block_len_bits = s->frame_len_bits - v; v = get_bits(&s->gb, n); if (v >= s->nb_block_sizes) { return -1; } s->block_len_bits = s->frame_len_bits - v; } else { /* update block lengths */ s->prev_block_len_bits = s->block_len_bits; s->block_len_bits = s->next_block_len_bits; } v = get_bits(&s->gb, n); if (v >= s->nb_block_sizes) { return -1; } s->next_block_len_bits = s->frame_len_bits - v; } else { /* fixed block len */ s->next_block_len_bits = s->frame_len_bits; s->prev_block_len_bits = s->frame_len_bits; s->block_len_bits = s->frame_len_bits; } /* now check if the block length is coherent with the frame length */ s->block_len = 1 << s->block_len_bits; if ((s->block_pos + s->block_len) > s->frame_len) { return -1; } if (s->nb_channels == 2) { s->ms_stereo = get_bits(&s->gb, 1); } v = 0; for (ch = 0; ch < s->nb_channels; ++ch) { a = get_bits(&s->gb, 1); s->channel_coded[ch] = a; v |= a; } /* if no channel coded, no need to go further */ /* XXX: fix potential framing problems */ if (!v) { goto next; } bsize = s->frame_len_bits - s->block_len_bits; /* read total gain and extract corresponding number of bits for coef escape coding */ total_gain = 1; for(;;) { a = get_bits(&s->gb, 7); total_gain += a; if (a != 127) { break; } } if (total_gain < 15) coef_nb_bits = 13; else if (total_gain < 32) coef_nb_bits = 12; else if (total_gain < 40) coef_nb_bits = 11; else if (total_gain < 45) coef_nb_bits = 10; else coef_nb_bits = 9; /* compute number of coefficients */ n = s->coefs_end[bsize] - s->coefs_start; for(ch = 0; ch < s->nb_channels; ++ch) { nb_coefs[ch] = n; } /* complex coding */ if (s->use_noise_coding) { for(ch = 0; ch < s->nb_channels; ++ch) { if (s->channel_coded[ch]) { int i, n, a; n = s->exponent_high_sizes[bsize]; for(i=0;i<n;++i) { a = get_bits(&s->gb, 1); s->high_band_coded[ch][i] = a; /* if noise coding, the coefficients are not transmitted */ if (a) nb_coefs[ch] -= s->exponent_high_bands[bsize][i]; } } } for(ch = 0; ch < s->nb_channels; ++ch) { if (s->channel_coded[ch]) { int i, n, val, code; n = s->exponent_high_sizes[bsize]; val = (int)0x80000000; for(i=0;i<n;++i) { if (s->high_band_coded[ch][i]) { if (val == (int)0x80000000) { val = get_bits(&s->gb, 7) - 19; } else { code = get_vlc(&s->gb, &s->hgain_vlc); if (code < 0) { return -1; } val += code - 18; } s->high_band_values[ch][i] = val; } } } } } /* exposant can be interpolated in short blocks. */ parse_exponents = 1; if (s->block_len_bits != s->frame_len_bits) { parse_exponents = get_bits(&s->gb, 1); } if (parse_exponents) { for(ch = 0; ch < s->nb_channels; ++ch) { if (s->channel_coded[ch]) { if (s->use_exp_vlc) { if (decode_exp_vlc(s, ch) < 0) { return -1; } } else { decode_exp_lsp(s, ch); } } } } else { for(ch = 0; ch < s->nb_channels; ++ch) { if (s->channel_coded[ch]) { interpolate_array(s->exponents[ch], 1 << s->prev_block_len_bits, s->block_len); } } } /* parse spectral coefficients : just RLE encoding */ for(ch = 0; ch < s->nb_channels; ++ch) { if (s->channel_coded[ch]) { VLC *coef_vlc; int level, run, sign, tindex; int16_t *ptr, *eptr; const int16_t *level_table, *run_table; /* special VLC tables are used for ms stereo because there is potentially less energy there */ tindex = (ch == 1 && s->ms_stereo); coef_vlc = &s->coef_vlc[tindex]; run_table = s->run_table[tindex]; level_table = s->level_table[tindex]; /* XXX: optimize */ ptr = &s->coefs1[ch][0]; eptr = ptr + nb_coefs[ch]; memset(ptr, 0, s->block_len * sizeof(int16_t)); for(;;) { code = get_vlc(&s->gb, coef_vlc); if (code < 0) { return -1; } if (code == 1) { /* EOB */ break; } else if (code == 0) { /* escape */ level = get_bits(&s->gb, coef_nb_bits); /* NOTE: this is rather suboptimal. reading block_len_bits would be better */ run = get_bits(&s->gb, s->frame_len_bits); } else { /* normal code */ run = run_table[code]; level = level_table[code]; } sign = get_bits(&s->gb, 1); if (!sign) level = -level; ptr += run; if (ptr >= eptr) { return -1; } *ptr++ = level; /* NOTE: EOB can be omitted */ if (ptr >= eptr) break; } } if (s->version == 1 && s->nb_channels >= 2) { align_get_bits(&s->gb); } } /* normalize */ { int n4 = s->block_len >> 1; mdct_norm = 0x10000; mdct_norm = fixdiv32(mdct_norm,itofix32(n4)); if (s->version == 1) { fixed32 tmp = fixsqrt32(itofix32(n4)); mdct_norm *= tmp; /* PJJ : exercise this path */ } } /* finally compute the MDCT coefficients */ for(ch = 0; ch < s->nb_channels; ++ch) { if (s->channel_coded[ch]) { int16_t *coefs1; fixed32 *exponents, *exp_ptr; fixed32 *coefs; fixed64 mult; fixed64 mult1; fixed32 noise; int i, j, n, n1, last_high_band; fixed32 exp_power[HIGH_BAND_MAX_SIZE]; coefs1 = s->coefs1[ch]; exponents = s->exponents[ch]; mult = fixdiv64(pow_table[total_gain],Fixed32To64(s->max_exponent[ch])); mult = fixmul64byfixed(mult, mdct_norm); coefs = s->coefs[ch]; if (s->use_noise_coding) { mult1 = mult; /* very low freqs : noise */ for(i = 0;i < s->coefs_start; ++i) { *coefs++ = fixmul32(fixmul32(s->noise_table[s->noise_index],(*exponents++)),Fixed32From64(mult1)); s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1); } n1 = s->exponent_high_sizes[bsize]; /* compute power of high bands */ exp_ptr = exponents + s->high_band_start[bsize] - s->coefs_start; last_high_band = 0; /* avoid warning */ for (j=0;j<n1;++j) { n = s->exponent_high_bands[s->frame_len_bits - s->block_len_bits][j]; if (s->high_band_coded[ch][j]) { fixed32 e2, v; e2 = 0; for(i = 0;i < n; ++i) { v = exp_ptr[i]; e2 += v * v; } exp_power[j] = fixdiv32(e2,n); last_high_band = j; } exp_ptr += n; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -