X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fatrac.c;h=f36db9e8c5f8fe62019d716a2bf669f1083448d5;hb=8dfba25ce89b62c80ba83e2116d549176c376144;hp=b34bff3489a4ca71ab9de6cc1ebb05f73669d7b6;hpb=4be292dac7e7f0586053fcced8d530ccf4ebef29;p=ffmpeg diff --git a/libavcodec/atrac.c b/libavcodec/atrac.c index b34bff3489a..f36db9e8c5f 100644 --- a/libavcodec/atrac.c +++ b/libavcodec/atrac.c @@ -45,7 +45,7 @@ static const float qmf_48tap_half[24] = { -0.043596379, -0.099384367, 0.13207909, 0.46424159 }; -void ff_atrac_generate_tables(void) +av_cold void ff_atrac_generate_tables(void) { int i; float s; @@ -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;