]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/atrac.c
avcodec: Mark argument in av_{parser|hwaccel|bitstream_filter}_next as const
[ffmpeg] / libavcodec / atrac.c
index 6c1b1f19ce86caad833424688e1916500926c953..f36db9e8c5f8fe62019d716a2bf669f1083448d5 100644 (file)
@@ -1,22 +1,23 @@
 /*
- * 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 FFmpeg.
+ * This file is part of Libav.
  *
- * FFmpeg is free software; you can redistribute it and/or
+ * Libav is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * FFmpeg is distributed in the hope that it will be useful,
+ * Libav is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with Libav; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
@@ -27,9 +28,9 @@
 #include <math.h>
 #include <stddef.h>
 #include <stdio.h>
+#include <string.h>
 
 #include "avcodec.h"
-#include "dsputil.h"
 #include "atrac.h"
 
 float ff_atrac_sf_table[64];
@@ -44,11 +45,7 @@ static const float qmf_48tap_half[24] = {
    -0.043596379,   -0.099384367,   0.13207909,    0.46424159
 };
 
-/**
- * Generate common tables
- */
-
-void atrac_generate_tables(void)
+av_cold void ff_atrac_generate_tables(void)
 {
     int i;
     float s;
@@ -66,20 +63,68 @@ void 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);
 
-void atrac_iqmf (float *inlo, float *inhi, unsigned int nIn, float *pOut, float *delayBuf, float *temp)
+    /* 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;
     float   *p1, *p3;
@@ -117,4 +162,3 @@ void atrac_iqmf (float *inlo, float *inhi, unsigned int nIn, float *pOut, float
     /* Update the delay buffer. */
     memcpy(delayBuf, temp + nIn*2, 46*sizeof(float));
 }
-