Move it to the ATRAC common code, to reuse in the upcoming ATRAC3+ decoder. Signed-off-by: Diego Biurrun <diego@biurrun.de>tags/n2.1
| @@ -63,6 +63,67 @@ void ff_atrac_generate_tables(void) | |||
| } | |||
| } | |||
| av_cold void ff_atrac_init_gain_compensation(AtracGCContext *gctx, int id2exp_offset, | |||
| int loc_scale) | |||
| { | |||
| int i; | |||
| gctx->loc_scale = loc_scale; | |||
| gctx->loc_size = 1 << loc_scale; | |||
| gctx->id2exp_offset = id2exp_offset; | |||
| /* Generate gain level table. */ | |||
| for (i = 0; i < 16; i++) | |||
| gctx->gain_tab1[i] = powf(2.0, id2exp_offset - i); | |||
| /* Generate gain interpolation table. */ | |||
| for (i = -15; i < 16; i++) | |||
| gctx->gain_tab2[i + 15] = powf(2.0, -1.0f / gctx->loc_size * i); | |||
| } | |||
| void ff_atrac_gain_compensation(AtracGCContext *gctx, float *in, float *prev, | |||
| AtracGainInfo *gc_now, AtracGainInfo *gc_next, | |||
| int num_samples, float *out) | |||
| { | |||
| float lev, gc_scale, gain_inc; | |||
| int i, pos, lastpos; | |||
| gc_scale = gc_next->num_points ? gctx->gain_tab1[gc_next->lev_code[0]] | |||
| : 1.0f; | |||
| if (!gc_now->num_points) { | |||
| for (pos = 0; pos < num_samples; pos++) | |||
| out[pos] = in[pos] * gc_scale + prev[pos]; | |||
| } else { | |||
| pos = 0; | |||
| for (i = 0; i < gc_now->num_points; i++) { | |||
| lastpos = gc_now->loc_code[i] << gctx->loc_scale; | |||
| lev = gctx->gain_tab1[gc_now->lev_code[i]]; | |||
| gain_inc = gctx->gain_tab2[(i + 1 < gc_now->num_points ? gc_now->lev_code[i + 1] | |||
| : gctx->id2exp_offset) - | |||
| gc_now->lev_code[i] + 15]; | |||
| /* apply constant gain level and overlap */ | |||
| for (; pos < lastpos; pos++) | |||
| out[pos] = (in[pos] * gc_scale + prev[pos]) * lev; | |||
| /* interpolate between two different gain levels */ | |||
| for (; pos < lastpos + gctx->loc_size; pos++) { | |||
| out[pos] = (in[pos] * gc_scale + prev[pos]) * lev; | |||
| lev *= gain_inc; | |||
| } | |||
| } | |||
| for (; pos < num_samples; pos++) | |||
| out[pos] = in[pos] * gc_scale + prev[pos]; | |||
| } | |||
| /* copy the overlapping part into the delay buffer */ | |||
| memcpy(prev, &in[num_samples], num_samples * sizeof(float)); | |||
| } | |||
| void ff_atrac_iqmf (float *inlo, float *inhi, unsigned int nIn, float *pOut, float *delayBuf, float *temp) | |||
| { | |||
| int i, j; | |||
| @@ -29,6 +29,26 @@ | |||
| #ifndef AVCODEC_ATRAC_H | |||
| #define AVCODEC_ATRAC_H | |||
| /** | |||
| * Gain control parameters for one subband. | |||
| */ | |||
| typedef struct AtracGainInfo { | |||
| int num_points; ///< number of gain control points | |||
| int lev_code[7]; ///< level at corresponding control point | |||
| int loc_code[7]; ///< location of gain control points | |||
| } AtracGainInfo; | |||
| /** | |||
| * Gain compensation context structure. | |||
| */ | |||
| typedef struct AtracGCContext { | |||
| float gain_tab1[16]; ///< gain compensation level table | |||
| float gain_tab2[31]; ///< gain compensation interpolation table | |||
| int id2exp_offset; ///< offset for converting level index into level exponent | |||
| int loc_scale; ///< scale of location code = 2^loc_scale samples | |||
| int loc_size; ///< size of location code in samples | |||
| } AtracGCContext; | |||
| extern float ff_atrac_sf_table[64]; | |||
| /** | |||
| @@ -36,6 +56,31 @@ extern float ff_atrac_sf_table[64]; | |||
| */ | |||
| void ff_atrac_generate_tables(void); | |||
| /** | |||
| * Initialize gain compensation context. | |||
| * | |||
| * @param gctx pointer to gain compensation context to initialize | |||
| * @param id2exp_offset offset for converting level index into level exponent | |||
| * @param loc_scale location size factor | |||
| */ | |||
| void ff_atrac_init_gain_compensation(AtracGCContext *gctx, int id2exp_offset, | |||
| int loc_scale); | |||
| /** | |||
| * Apply gain compensation and perform the MDCT overlapping part. | |||
| * | |||
| * @param gctx pointer to gain compensation context | |||
| * @param in input buffer | |||
| * @param prev previous buffer to perform overlap against | |||
| * @param gc_now gain control information for current frame | |||
| * @param gc_next gain control information for next frame | |||
| * @param num_samples number of samples to process | |||
| * @param out output data goes here | |||
| */ | |||
| void ff_atrac_gain_compensation(AtracGCContext *gctx, float *in, float *prev, | |||
| AtracGainInfo *gc_now, AtracGainInfo *gc_next, | |||
| int num_samples, float *out); | |||
| /** | |||
| * Quadrature mirror synthesis filter. | |||
| * | |||
| @@ -54,14 +54,8 @@ | |||
| #define SAMPLES_PER_FRAME 1024 | |||
| #define MDCT_SIZE 512 | |||
| typedef struct GainInfo { | |||
| int num_gain_data; | |||
| int lev_code[8]; | |||
| int loc_code[8]; | |||
| } GainInfo; | |||
| typedef struct GainBlock { | |||
| GainInfo g_block[4]; | |||
| AtracGainInfo g_block[4]; | |||
| } GainBlock; | |||
| typedef struct TonalComponent { | |||
| @@ -111,6 +105,7 @@ typedef struct ATRAC3Context { | |||
| int scrambled_stream; | |||
| //@} | |||
| AtracGCContext gainc_ctx; | |||
| FFTContext mdct_ctx; | |||
| FmtConvertContext fmt_conv; | |||
| AVFloatDSPContext fdsp; | |||
| @@ -417,18 +412,17 @@ static int decode_tonal_components(GetBitContext *gb, | |||
| static int decode_gain_control(GetBitContext *gb, GainBlock *block, | |||
| int num_bands) | |||
| { | |||
| int i, j, num_data; | |||
| int i, j; | |||
| int *level, *loc; | |||
| GainInfo *gain = block->g_block; | |||
| AtracGainInfo *gain = block->g_block; | |||
| for (i = 0; i <= num_bands; i++) { | |||
| num_data = get_bits(gb, 3); | |||
| gain[i].num_gain_data = num_data; | |||
| gain[i].num_points = get_bits(gb, 3); | |||
| level = gain[i].lev_code; | |||
| loc = gain[i].loc_code; | |||
| for (j = 0; j < gain[i].num_gain_data; j++) { | |||
| for (j = 0; j < gain[i].num_points; j++) { | |||
| level[j] = get_bits(gb, 4); | |||
| loc[j] = get_bits(gb, 5); | |||
| if (j && loc[j] <= loc[j - 1]) | |||
| @@ -438,68 +432,11 @@ static int decode_gain_control(GetBitContext *gb, GainBlock *block, | |||
| /* Clear the unused blocks. */ | |||
| for (; i < 4 ; i++) | |||
| gain[i].num_gain_data = 0; | |||
| gain[i].num_points = 0; | |||
| return 0; | |||
| } | |||
| /** | |||
| * Apply gain parameters and perform the MDCT overlapping part | |||
| * | |||
| * @param input input buffer | |||
| * @param prev previous buffer to perform overlap against | |||
| * @param output output buffer | |||
| * @param gain1 current band gain info | |||
| * @param gain2 next band gain info | |||
| */ | |||
| static void gain_compensate_and_overlap(float *input, float *prev, | |||
| float *output, GainInfo *gain1, | |||
| GainInfo *gain2) | |||
| { | |||
| float g1, g2, gain_inc; | |||
| int i, j, num_data, start_loc, end_loc; | |||
| if (gain2->num_gain_data == 0) | |||
| g1 = 1.0; | |||
| else | |||
| g1 = gain_tab1[gain2->lev_code[0]]; | |||
| if (gain1->num_gain_data == 0) { | |||
| for (i = 0; i < 256; i++) | |||
| output[i] = input[i] * g1 + prev[i]; | |||
| } else { | |||
| num_data = gain1->num_gain_data; | |||
| gain1->loc_code[num_data] = 32; | |||
| gain1->lev_code[num_data] = 4; | |||
| for (i = 0, j = 0; i < num_data; i++) { | |||
| start_loc = gain1->loc_code[i] * 8; | |||
| end_loc = start_loc + 8; | |||
| g2 = gain_tab1[gain1->lev_code[i]]; | |||
| gain_inc = gain_tab2[gain1->lev_code[i + 1] - | |||
| gain1->lev_code[i ] + 15]; | |||
| /* interpolate */ | |||
| for (; j < start_loc; j++) | |||
| output[j] = (input[j] * g1 + prev[j]) * g2; | |||
| /* interpolation is done over eight samples */ | |||
| for (; j < end_loc; j++) { | |||
| output[j] = (input[j] * g1 + prev[j]) * g2; | |||
| g2 *= gain_inc; | |||
| } | |||
| } | |||
| for (; j < 256; j++) | |||
| output[j] = input[j] * g1 + prev[j]; | |||
| } | |||
| /* Delay for the overlapping part. */ | |||
| memcpy(prev, &input[256], 256 * sizeof(*prev)); | |||
| } | |||
| /** | |||
| * Combine the tonal band spectrum and regular band spectrum | |||
| * | |||
| @@ -690,11 +627,10 @@ static int decode_channel_sound_unit(ATRAC3Context *q, GetBitContext *gb, | |||
| memset(snd->imdct_buf, 0, 512 * sizeof(*snd->imdct_buf)); | |||
| /* gain compensation and overlapping */ | |||
| gain_compensate_and_overlap(snd->imdct_buf, | |||
| &snd->prev_frame[band * 256], | |||
| &output[band * 256], | |||
| &gain1->g_block[band], | |||
| &gain2->g_block[band]); | |||
| ff_atrac_gain_compensation(&q->gainc_ctx, snd->imdct_buf, | |||
| &snd->prev_frame[band * 256], | |||
| &gain1->g_block[band], &gain2->g_block[band], | |||
| 256, &output[band * 256]); | |||
| } | |||
| /* Swap the gain control buffers for the next frame. */ | |||
| @@ -982,6 +918,7 @@ static av_cold int atrac3_decode_init(AVCodecContext *avctx) | |||
| q->matrix_coeff_index_next[i] = 3; | |||
| } | |||
| ff_atrac_init_gain_compensation(&q->gainc_ctx, 4, 3); | |||
| avpriv_float_dsp_init(&q->fdsp, avctx->flags & CODEC_FLAG_BITEXACT); | |||
| ff_fmt_convert_init(&q->fmt_conv, avctx); | |||