Mercurial > libavcodec.hg
changeset 8136:3085502c4f33 libavcodec
add support for spectral extension
author | jbr |
---|---|
date | Thu, 13 Nov 2008 03:18:13 +0000 |
parents | c82f8f5657ff |
children | c6993d9ed77c |
files | ac3dec.c ac3dec.h ac3dec_data.c ac3dec_data.h eac3dec.c |
diffstat | 5 files changed, 272 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/ac3dec.c Thu Nov 13 03:18:07 2008 +0000 +++ b/ac3dec.c Thu Nov 13 03:18:13 2008 +0000 @@ -818,14 +818,86 @@ /* spectral extension strategy */ if (s->eac3 && (!blk || get_bits1(gbc))) { - if (get_bits1(gbc)) { - av_log_missing_feature(s->avctx, "Spectral extension", 1); - return -1; + s->spx_in_use[blk] = get_bits1(gbc); + if (s->spx_in_use[blk]) { + int begf, endf; + int spx_end_subband; + + /* determine which channels use spx */ + if (s->channel_mode == AC3_CHMODE_MONO) { + s->channel_in_spx[1] = 1; + s->spx_coords_exist[1] = 0; + } else { + for (ch = 1; ch <= fbw_channels; ch++) { + s->channel_in_spx[ch] = get_bits1(gbc); + s->spx_coords_exist[ch] = 0; + } + } + + s->spx_copy_start_freq = get_bits(gbc, 2) * 12 + 25; + begf = get_bits(gbc, 3); + endf = get_bits(gbc, 3); + s->spx_start_subband = begf < 6 ? begf+2 : 2*begf-3; + spx_end_subband = endf < 4 ? endf+5 : 2*endf+3; + s->num_spx_subbands = spx_end_subband - s->spx_start_subband; + s->spx_start_freq = s->spx_start_subband * 12 + 25; + s->spx_end_freq = spx_end_subband * 12 + 25; + + decode_band_structure(gbc, blk, s->eac3, 0, + s->spx_start_subband, spx_end_subband, + ff_eac3_default_spx_band_struct, + s->spx_band_struct, NULL, &s->num_spx_bands, + s->spx_band_sizes); + } else { + for (ch = 1; ch <= fbw_channels; ch++) { + s->channel_in_spx[ch] = 0; + s->first_spx_coords[ch] = 1; + } } - /* TODO: parse spectral extension strategy info */ + } else { + s->spx_in_use[blk] = blk ? s->spx_in_use[blk-1] : 0; } - /* TODO: spectral extension coordinates */ + /* spectral extension coordinates */ + if (s->spx_in_use[blk]) { + for (ch = 1; ch <= fbw_channels; ch++) { + if (s->channel_in_spx[ch]) { + if (s->first_spx_coords[ch] || get_bits1(gbc)) { + int bin, spx_blend; + int master_spx_coord; + s->first_spx_coords[ch] = 0; + s->spx_coords_exist[ch] = 1; + spx_blend = get_bits(gbc, 5) << 18; + master_spx_coord = get_bits(gbc, 2) * 3; + bin = s->spx_start_freq; + for (bnd = 0; bnd < s->num_spx_bands; bnd++) { + int spx_coord_exp, spx_coord_mant; + + /* calculate blending factors */ + int bandsize = s->spx_band_sizes[bnd]; + int nratio = (((bin + (bandsize >> 1)) << 23) / s->spx_end_freq) - spx_blend; + nratio = av_clip(nratio, 0, INT24_MAX); + s->spx_noise_blend [ch][bnd] = ff_sqrt(( nratio) << 8) * M_SQRT_POW2_15; + s->spx_signal_blend[ch][bnd] = ff_sqrt((INT24_MAX - nratio) << 8) * M_SQRT_POW2_15; + bin += bandsize; + + /* decode spx coordinates */ + spx_coord_exp = get_bits(gbc, 4); + spx_coord_mant = get_bits(gbc, 2); + if (spx_coord_exp == 15) + s->spx_coords[ch][bnd] = spx_coord_mant << 26; + else + s->spx_coords[ch][bnd] = (spx_coord_mant + 4) << 25; + s->spx_coords[ch][bnd] >>= (spx_coord_exp + master_spx_coord); + } + } else { + s->spx_coords_exist[ch] = 0; + } + } else { + s->first_spx_coords[ch] = 1; + } + } + } /* coupling strategy */ if (s->eac3 ? s->cpl_strategy_exists[blk] : get_bits1(gbc)) { @@ -862,9 +934,12 @@ s->phase_flags_in_use = get_bits1(gbc); /* coupling frequency range */ - /* TODO: modify coupling end freq if spectral extension is used */ cpl_start_subband = get_bits(gbc, 4); + if (s->spx_in_use[blk]) { + cpl_end_subband = s->spx_start_subband - 1; + } else { cpl_end_subband = get_bits(gbc, 4) + 3; + } s->num_cpl_subbands = cpl_end_subband - cpl_start_subband; if (s->num_cpl_subbands < 0) { av_log(s->avctx, AV_LOG_ERROR, "invalid coupling range (%d > %d)\n", @@ -939,8 +1014,14 @@ if (channel_mode == AC3_CHMODE_STEREO) { if ((s->eac3 && !blk) || get_bits1(gbc)) { s->num_rematrixing_bands = 4; - if(cpl_in_use && s->start_freq[CPL_CH] <= 61) + if (cpl_in_use) { + if (s->start_freq[CPL_CH] <= 61) s->num_rematrixing_bands -= 1 + (s->start_freq[CPL_CH] == 37); + } else if (s->spx_in_use[blk]) { + if (s->spx_start_freq <= 61) + s->num_rematrixing_bands -= 1 + (s->spx_start_freq <= 37) + + (s->spx_start_freq <= 25); + } for(bnd=0; bnd<s->num_rematrixing_bands; bnd++) s->rematrixing_flags[bnd] = get_bits1(gbc); } else if (!blk) { @@ -965,6 +1046,8 @@ int prev = s->end_freq[ch]; if (s->channel_in_cpl[ch]) s->end_freq[ch] = s->start_freq[CPL_CH]; + else if (s->channel_in_spx[ch]) + s->end_freq[ch] = s->spx_start_freq; else { int bandwidth_code = get_bits(gbc, 6); if (bandwidth_code > 60) { @@ -1155,12 +1238,12 @@ /* TODO: generate enhanced coupling coordinates and uncouple */ - /* TODO: apply spectral extension */ - /* recover coefficients if rematrixing is in use */ if(s->channel_mode == AC3_CHMODE_STEREO) do_rematrixing(s); + ff_eac3_apply_spectral_extension(s); + /* apply scaling to coefficients (headroom, dynrng) */ for(ch=1; ch<=s->channels; ch++) { float gain = s->mul_bias / 4194304.0f;
--- a/ac3dec.h Thu Nov 13 03:18:07 2008 +0000 +++ b/ac3dec.h Thu Nov 13 03:18:13 2008 +0000 @@ -42,6 +42,11 @@ #define AC3_MAX_COEFS 256 #define AC3_BLOCK_SIZE 256 #define MAX_BLOCKS 6 +#define SPX_MAX_BANDS 17 + +#define INT24_MIN -8388608 +#define INT24_MAX 8388607 +#define M_SQRT_POW2_15 181 typedef struct { AVCodecContext *avctx; ///< parent context @@ -88,6 +93,26 @@ int cpl_coords[AC3_MAX_CHANNELS][18]; ///< coupling coordinates (cplco) ///@} +///@defgroup spx spectral extension +///@{ + int spx_in_use[MAX_BLOCKS]; ///< spectral extension in use (spxinu) + int channel_in_spx[AC3_MAX_CHANNELS]; ///< channel in spectral extension (chinspx) + int spx_atten_code[AC3_MAX_CHANNELS]; ///< spx attenuation code (spxattencod) + int spx_coords_exist[AC3_MAX_CHANNELS]; ///< indicates if a channel has spx coords (spxcoe) + int spx_start_subband; ///< spx beginning frequency band (spxbegf) + int spx_start_freq; ///< spx start frequency bin + int spx_end_freq; ///< spx end frequency bin + int spx_copy_start_freq; ///< spx starting frequency for copying (copystartmant) + int num_spx_subbands; ///< number of spectral extension subbands + int num_spx_bands; ///< number of spectral extension bands (nspxbnds) + uint8_t spx_band_struct[SPX_MAX_BANDS]; ///< spectral extension band structure (spxbndstrc) + int spx_band_sizes[SPX_MAX_BANDS]; ///< number of bins in each band (spxbndsztab) + int first_spx_coords[AC3_MAX_CHANNELS]; ///< first spx coordinates states (firstspxcos) + int spx_noise_blend[AC3_MAX_CHANNELS][SPX_MAX_BANDS]; ///< spx noise blending factor (nblendfact) + int spx_signal_blend[AC3_MAX_CHANNELS][SPX_MAX_BANDS]; ///< spx signal blending factor (sblendfact) + int spx_coords[AC3_MAX_CHANNELS][SPX_MAX_BANDS]; ///< spectral extension coordinates (spxco) +///@} + ///@defgroup aht adaptive hybrid transform int channel_uses_aht[AC3_MAX_CHANNELS]; ///< channel AHT in use (chahtinu) int pre_mantissa[AC3_MAX_CHANNELS][AC3_MAX_COEFS][MAX_BLOCKS]; ///< pre-IDCT mantissas @@ -179,4 +204,6 @@ */ void ff_eac3_decode_transform_coeffs_aht_ch(AC3DecodeContext *s, int ch); +void ff_eac3_apply_spectral_extension(AC3DecodeContext *s); + #endif /* AVCODEC_AC3DEC_H */
--- a/ac3dec_data.c Thu Nov 13 03:18:07 2008 +0000 +++ b/ac3dec_data.c Thu Nov 13 03:18:13 2008 +0000 @@ -1127,6 +1127,52 @@ const uint8_t ff_eac3_default_cpl_band_struct[18] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1 }; + /** + * Table E2.15 Default Spectral Extension Banding Structure + */ +const uint8_t ff_eac3_default_spx_band_struct[17] = +{ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 }; + +/** + * Table E.25: Spectral Extension Attenuation Table + * 24-bit fixed-point version of the floating-point table in the specification. + * ff_eac3_spx_atten_tab[code][bin]=lrint(pow(1<<(bin+1),(code+1)/-15.0)*(1<<23)); + */ +const int32_t ff_eac3_spx_atten_tab[32][3] = { + { 8009792, 7648083, 7302707 }, + { 7648083, 6972929, 6357376 }, + { 7302707, 6357376, 5534417 }, + { 6972929, 5796163, 4817990 }, + { 6658043, 5284492, 4194304 }, + { 6357376, 4817990, 3651354 }, + { 6070287, 4392670, 3178688 }, + { 5796163, 4004896, 2767209 }, + { 5534417, 3651354, 2408995 }, + { 5284492, 3329021, 2097152 }, + { 5045853, 3035144, 1825677 }, + { 4817990, 2767209, 1589344 }, + { 4600417, 2522926, 1383604 }, + { 4392670, 2300209, 1204498 }, + { 4194304, 2097152, 1048576 }, + { 4004896, 1912021, 912838 }, + { 3824041, 1743232, 794672 }, + { 3651354, 1589344, 691802 }, + { 3486464, 1449041, 602249 }, + { 3329021, 1321123, 524288 }, + { 3178688, 1204498, 456419 }, + { 3035144, 1098167, 397336 }, + { 2898081, 1001224, 345901 }, + { 2767209, 912838, 301124 }, + { 2642246, 832255, 262144 }, + { 2522926, 758786, 228210 }, + { 2408995, 691802, 198668 }, + { 2300209, 630732, 172951 }, + { 2196335, 575052, 150562 }, + { 2097152, 524288, 131072 }, + { 2002448, 478005, 114105 }, + { 1912021, 435808, 99334 } +}; + /** * Table of bin locations for rematrixing bands * reference: Section 7.5.2 Rematrixing : Frequency Band Definitions
--- a/ac3dec_data.h Thu Nov 13 03:18:07 2008 +0000 +++ b/ac3dec_data.h Thu Nov 13 03:18:13 2008 +0000 @@ -34,6 +34,8 @@ extern const int16_t (* const ff_eac3_mantissa_vq[8])[6]; extern const uint8_t ff_eac3_frm_expstr[32][6]; extern const uint8_t ff_eac3_default_cpl_band_struct[18]; +extern const uint8_t ff_eac3_default_spx_band_struct[17]; +extern const int32_t ff_eac3_spx_atten_tab[32][3]; extern const uint8_t ff_ac3_rematrix_band_tab[5];
--- a/eac3dec.c Thu Nov 13 03:18:07 2008 +0000 +++ b/eac3dec.c Thu Nov 13 03:18:13 2008 +0000 @@ -36,6 +36,104 @@ #define EAC3_SR_CODE_REDUCED 3 + +void ff_eac3_apply_spectral_extension(AC3DecodeContext *s) +{ + int bin, bnd, ch, i; + int wrapflag[SPX_MAX_BANDS]={0,}, num_copy_sections, copy_sizes[SPX_MAX_BANDS]; + int rms_energy[SPX_MAX_BANDS]; + + /* Set copy index mapping table. Set wrap flags to apply a notch filter at + wrap points later on. */ + bin = s->spx_copy_start_freq; + num_copy_sections = 0; + for (bnd = 0; bnd < s->num_spx_bands; bnd++) { + int bandsize = s->spx_band_sizes[bnd]; + if ((bin + bandsize) > s->spx_start_freq) { + copy_sizes[num_copy_sections++] = bin - s->spx_copy_start_freq; + bin = s->spx_copy_start_freq; + wrapflag[bnd] = 1; + } + for (i = 0; i < bandsize; i++) { + if (bin == s->spx_start_freq) { + copy_sizes[num_copy_sections++] = bin - s->spx_copy_start_freq; + bin = s->spx_copy_start_freq; + } + bin++; + } + } + copy_sizes[num_copy_sections++] = bin - s->spx_copy_start_freq; + + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (!s->channel_in_spx[ch]) + continue; + + /* Copy coeffs from normal bands to extension bands */ + bin = s->spx_start_freq; + for (bnd = 0; bnd < num_copy_sections; bnd++) { + memcpy(&s->fixed_coeffs[ch][bin], + &s->fixed_coeffs[ch][s->spx_copy_start_freq], + copy_sizes[bnd]*sizeof(int)); + bin += copy_sizes[bnd]; + } + + /* Calculate RMS energy for each SPX band. */ + bin = s->spx_start_freq; + for (bnd = 0; bnd < s->num_spx_bands; bnd++) { + int bandsize = s->spx_band_sizes[bnd]; + int64_t accum = 0; + for (i = 0; i < bandsize; i++) { + int64_t coeff = s->fixed_coeffs[ch][bin++]; + accum += coeff * coeff; + } + rms_energy[bnd] = ff_sqrt((accum >> 15) / bandsize) * M_SQRT_POW2_15; + } + + /* Apply a notch filter at transitions between normal and extension + bands and at all wrap points. */ + if (s->spx_atten_code[ch] >= 0) { + const int32_t *atten_tab = ff_eac3_spx_atten_tab[s->spx_atten_code[ch]]; + /* apply notch filter at baseband / extension region border */ + bin = s->spx_start_freq - 2; + for (i = 0; i < 5; i++) { + s->fixed_coeffs[ch][bin] = ((int64_t)atten_tab[2-abs(i-2)] * + (int64_t)s->fixed_coeffs[ch][bin]) >> 23; + bin++; + } + /* apply notch at all other wrap points */ + bin += s->spx_band_sizes[0]; + for (bnd = 1; bnd < s->num_spx_bands; bnd++) { + if (wrapflag[bnd]) { + bin -= 5; + for (i = 0; i < 5; i++) { + s->fixed_coeffs[ch][bin] = (atten_tab[2-abs(i-2)] * + (int64_t)s->fixed_coeffs[ch][bin]) >> 23; + bin++; + } + } + bin += s->spx_band_sizes[bnd]; + } + } + + /* Apply noise-blended coefficient scaling based on previously + calculated RMS energy, blending factors, and SPX coordinates for + each band. */ + bin = s->spx_start_freq; + for (bnd = 0; bnd < s->num_spx_bands; bnd++) { + int64_t nscale, sscale, spxco; + nscale = (s->spx_noise_blend [ch][bnd] * rms_energy[bnd]) >> 23; + nscale = (nscale * 14529495) >> 23; + sscale = s->spx_signal_blend[ch][bnd]; + spxco = s->spx_coords[ch][bnd]; + for (i = 0; i < s->spx_band_sizes[bnd]; i++) { + int64_t noise = (nscale * (((int)av_lfg_get(&s->dith_state))>>8)) >> 23; + int64_t signal = (sscale * s->fixed_coeffs[ch][bin]) >> 23; + s->fixed_coeffs[ch][bin++] = ((noise + signal) * spxco) >> 23; + } + } + } +} + /** lrint(M_SQRT2*cos(2*M_PI/12)*(1<<23)) */ #define COEFF_0 10273905LL @@ -459,14 +557,12 @@ } /* spectral extension attenuation data */ - if (parse_spx_atten_data) { - av_log_missing_feature(s->avctx, "Spectral extension attenuation", 1); - for (ch = 1; ch <= s->fbw_channels; ch++) { - if (get_bits1(gbc)) { // channel has spx attenuation - skip_bits(gbc, 5); // skip spx attenuation code - } - } - } + for (ch = 1; ch <= s->fbw_channels; ch++) { + if (parse_spx_atten_data && get_bits1(gbc)) + s->spx_atten_code[ch] = get_bits(gbc, 5); + else + s->spx_atten_code[ch] = -1; + } /* block start information */ if (s->num_blocks > 1 && get_bits1(gbc)) { @@ -480,6 +576,7 @@ /* syntax state initialization */ for (ch = 1; ch <= s->fbw_channels; ch++) { + s->first_spx_coords[ch] = 1; s->first_cpl_coords[ch] = 1; } s->first_cpl_leak = 1;