summaryrefslogtreecommitdiff
path: root/libavcodec/atrac.c
diff options
context:
space:
mode:
authorMaxim Poliakovski <max_pole@gmx.de>2013-10-02 02:23:16 +0200
committerMichael Niedermayer <michaelni@gmx.at>2013-10-02 10:44:02 +0200
commitd49f3fa5794c9f17e058a6bce3ce6eac870ef85c (patch)
tree361fdfad4a493c195371c6e36832a35fc5a95b8a /libavcodec/atrac.c
parent4fa2484067d19a69dfe6f6e6b67a58fcba380a27 (diff)
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.c61
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)
{