/*
- * Atrac common functions
- * Copyright (c) 2006-2008 Maxim Poliakovski
+ * common functions for the ATRAC family of decoders
+ *
+ * Copyright (c) 2006-2013 Maxim Poliakovski
* Copyright (c) 2006-2008 Benjamin Larsson
*
* This file is part of Libav.
-0.043596379, -0.099384367, 0.13207909, 0.46424159
};
-/**
- * Generate common tables
- */
-
-void ff_atrac_generate_tables(void)
+av_cold void ff_atrac_generate_tables(void)
{
int i;
float s;
}
}
+av_cold void ff_atrac_init_gain_compensation(AtracGCContext *gctx, int id2exp_offset,
+ int loc_scale)
+{
+ int i;
-/**
- * Quadrature mirror synthesis filter.
- *
- * @param inlo lower part of spectrum
- * @param inhi higher part of spectrum
- * @param nIn size of spectrum buffer
- * @param pOut out buffer
- * @param delayBuf delayBuf buffer
- * @param temp temp buffer
- */
+ 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)
{