]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/atrac.c
pthread_frame: ensure the threads don't run simultaneously with hwaccel
[ffmpeg] / libavcodec / atrac.c
index a772e7db48d22f799db5a34c8991f0fef4ef4bc0..f36db9e8c5f8fe62019d716a2bf669f1083448d5 100644 (file)
@@ -1,6 +1,7 @@
 /*
- * 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.
@@ -30,7 +31,6 @@
 #include <string.h>
 
 #include "avcodec.h"
-#include "dsputil.h"
 #include "atrac.h"
 
 float ff_atrac_sf_table[64];
@@ -45,11 +45,7 @@ static const float qmf_48tap_half[24] = {
    -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;
@@ -67,18 +63,66 @@ void ff_atrac_generate_tables(void)
         }
 }
 
+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)
 {