diff options
author | Maxim Poliakovski <max_pole@gmx.de> | 2013-10-02 02:23:16 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-10-02 10:44:02 +0200 |
commit | d49f3fa5794c9f17e058a6bce3ce6eac870ef85c (patch) | |
tree | 361fdfad4a493c195371c6e36832a35fc5a95b8a /libavcodec/atrac.c | |
parent | 4fa2484067d19a69dfe6f6e6b67a58fcba380a27 (diff) | |
download | ffmpeg-d49f3fa5794c9f17e058a6bce3ce6eac870ef85c.tar.gz |
atrac3: Generalize gain compensation code
Move it to the ATRAC common code, so it can be reused
in the umpcoming ATRAC3+ decoder.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/atrac.c')
-rw-r--r-- | libavcodec/atrac.c | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/libavcodec/atrac.c b/libavcodec/atrac.c index 258523b4ac..141248f54d 100644 --- a/libavcodec/atrac.c +++ b/libavcodec/atrac.c @@ -63,6 +63,67 @@ av_cold 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->levcode[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->loccode[i] << gctx->loc_scale; + + lev = gctx->gain_tab1[gc_now->levcode[i]]; + gain_inc = gctx->gain_tab2[(i + 1 < gc_now->num_points + ? gc_now->levcode[i + 1] + : gctx->id2exp_offset) + - gc_now->levcode[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) { |