summaryrefslogtreecommitdiff
path: root/libavcodec/atrac.c
diff options
context:
space:
mode:
authorMaxim Poliakovski <max_pole@gmx.de>2013-09-30 23:14:51 +0200
committerDiego Biurrun <diego@biurrun.de>2013-10-03 18:20:01 +0200
commit79cbac8cd456c3f1c914bd1e7262b55e48de13a7 (patch)
treea06c45e77b9f0e19acc69360084aa8227c2f3ebc /libavcodec/atrac.c
parent5ce04c14dd3dd3670cbdba82275a3a72c716ec6f (diff)
atrac3: Generalize gain compensation code
Move it to the ATRAC common code, to reuse in the upcoming ATRAC3+ decoder. Signed-off-by: Diego Biurrun <diego@biurrun.de>
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 b34bff3489..0f5721500e 100644
--- a/libavcodec/atrac.c
+++ b/libavcodec/atrac.c
@@ -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;