Version 0.94.1 of the bladeenc mp3 encoder
[swftools.git] / lib / bladeenc / subs.c
diff --git a/lib/bladeenc/subs.c b/lib/bladeenc/subs.c
new file mode 100644 (file)
index 0000000..36b53ac
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+                       (c) Copyright 1998-2001 - Tord Jansson
+                       ======================================
+
+               This file is part of the BladeEnc MP3 Encoder, based on
+               ISO's reference code for MPEG Layer 3 compression, and might
+               contain smaller or larger sections that are directly taken
+               from ISO's reference code.
+
+               All changes to the ISO reference code herein are either
+               copyrighted by Tord Jansson (tord.jansson@swipnet.se)
+               or sublicensed to Tord Jansson by a third party.
+
+       BladeEnc is free software; you can redistribute this file
+       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.
+
+
+
+       ------------    Changes    ------------
+
+       2000-11-04  Andre Piotrowski
+
+       -       speed up: don«t calculate the unneeded phi values!
+
+       2000-11-22      ap
+
+       -       speed up: slightly improved way to handle the 'special case'
+
+       2000-12-05  ap
+
+       -       speed up: implemented prepacking
+
+       2000-12-11  ap
+
+       -       speed up: avoid data reordering
+
+       2000-12-12  ap
+
+       -       moved fft configuration switches to "l3psy.h"
+
+       2001-01-12  ap
+
+       -       use some explicit type casting to avoid compiler warnings
+*/
+
+/*****************************************************************************
+ * FFT computes fast fourier transform of BLKSIZE samples of data            *
+ *   based on the decimation-in-frequency algorithm described in "Digital    *
+ *   Signal Processing" by Oppenheim and Schafer, refer to pages 304         *
+ *   (flow graph) and 330-332 (Fortran program in problem 5).                *
+ *                                                                           *
+ *   required constants:                                                     *
+ *         PI          3.14159265358979                                      *
+ *         BLKSIZE     should be 2^^M for a positive integer M               *
+ *                                                                           *
+ *****************************************************************************/
+
+#include       "common.h"
+#include       "encoder.h"
+#include       "l3psy.h"
+
+
+
+
+
+/* The switches have been moved to "l3psy.h" */
+
+
+
+
+
+int                                            fInit_fft;
+
+
+
+
+
+void fft (FLOAT x_real[], FLOAT x_imag[], FLOAT energy[], FLOAT phi[], int N)
+{
+       int                                             i, j, k, off;
+#if USED_VALUES_ONLY
+       int                                             min_i, max_i;
+#endif
+       int                                             ip, le, le1;
+       static double                   w_real[BLKSIZE/2], w_imag[BLKSIZE/2];
+       double                                  t_real, t_imag, u_real, u_imag;
+       int                                             N_ORG;
+
+#if !REORDER_DATA
+       static  int                             swap_l[BLKSIZE/2+1];
+       static  int                             swap_s[BLKSIZE_s/2+1];
+       int                                             *pSwap, a, b;
+#endif
+
+       double  t1, t2, t3, t4, t5, t6;
+
+       if (fInit_fft == 0)
+       {
+               for (i = 0;  i < BLKSIZE/2;  i++)
+               {
+                       w_real[i] =  cos(PI*i/(BLKSIZE/2));
+#if NORMAL_FFT
+                       w_imag[i] = -sin(PI*i/(BLKSIZE/2));
+#else
+                       w_imag[i] =  sin(PI*i/(BLKSIZE/2));
+#endif
+               }
+
+#if !REORDER_DATA
+               j = 0;
+               for (i = 0;  i < BLKSIZE/2-1;  i++)
+               {
+                       swap_l[i] = j;  k = BLKSIZE/4;  while (k <= j) {j -= k;  k >>= 1;}  j += k;
+               }
+               swap_l[i] = i;  swap_l[i+1] = i+1;
+
+               j = 0;
+               for (i = 0;  i < BLKSIZE_s/2-1;  i++)
+               {
+                       swap_s[i] = j;  k = BLKSIZE_s/4;  while (k <= j) {j -= k;  k >>= 1;}  j += k;
+               }
+               swap_s[i] = i;  swap_s[i+1] = i+1;
+#endif
+
+               fInit_fft++;
+       }
+
+
+#if REAL_SEQUENCE
+       N_ORG = N;
+       N >>= 1;
+#if !PREPACKED
+       /* packing the sequence to the half length */
+       for (i = 0;  i < N;  i++)
+       {
+               x_real[i] = x_real[2*i];
+               x_imag[i] = x_real[2*i+1];
+       }
+#endif
+#endif
+
+
+       off = BLKSIZE/N;
+       for (le = N;  le > 1;  le = le1)
+       {
+               le1 = le >> 1;
+
+                       /* special case: k=0; u_real=1.0; u_imag=0.0; j=0 */
+                       for (i = 0;  i < N;  i += le)
+                       {
+                               ip = i + le1;
+                               t_real = x_real[i] - x_real[ip];
+                               t_imag = x_imag[i] - x_imag[ip];
+                               x_real[i] += x_real[ip];
+                               x_imag[i] += x_imag[ip];
+                               x_real[ip] = (FLOAT) t_real;
+                               x_imag[ip] = (FLOAT) t_imag;
+                       }
+
+               k = off;
+               for (j = 1;  j < le1;  j++)
+               {
+                       u_real = w_real[k];
+                       u_imag = w_imag[k];
+                       for (i = j;  i < N;  i += le)
+                       {
+                               ip = i + le1;
+                               t_real = x_real[i] - x_real[ip];
+                               t_imag = x_imag[i] - x_imag[ip];
+                               x_real[i] += x_real[ip];
+                               x_imag[i] += x_imag[ip];
+                               x_real[ip] = (FLOAT) (t_real*u_real - t_imag*u_imag);
+                               x_imag[ip] = (FLOAT) (t_imag*u_real + t_real*u_imag);
+                       }
+                       k += off;
+               }
+
+               off += off;
+       }
+
+
+#if REORDER_DATA
+       /* this section reorders the data to the correct ordering */
+       j = 0;
+       for (i = 0;  i < N-1;  i++)
+       {
+               if (i < j)
+               {
+                       t_real = x_real[j];
+                       t_imag = x_imag[j];
+                       x_real[j] = x_real[i];
+                       x_imag[j] = x_imag[i];
+                       x_real[i] = (FLOAT) t_real;
+                       x_imag[i] = (FLOAT) t_imag;
+               }
+               k=N/2;
+               while (k <= j)
+               {
+                       j -= k;
+                       k >>= 1;
+               }
+               j += k;
+       }
+#else
+       /*
+               We don«t reorder the data to the correct ordering,
+               but access the data by the bit reverse order index array.
+       */
+       pSwap = (N_ORG == BLKSIZE) ? swap_l : swap_s;
+#endif
+
+
+#if REAL_SEQUENCE
+       /* unpacking the sequence */
+       t_real = x_real[0];
+       t_imag = x_imag[0];
+       x_real[0] = (FLOAT) (t_real+t_imag);
+       x_imag[0] = 0.0;
+       x_real[N] = (FLOAT) (t_real-t_imag);
+       x_imag[N] = 0.0;
+
+       k = off = BLKSIZE/N_ORG;
+       for (i = 1;  i < N/2;  i++)
+       {
+#if REORDER_DATA
+#define                a       i
+#define                b       (N-i)
+#else
+               a = pSwap[i];
+               b = pSwap[N-i];
+#endif
+               t1 = x_real[a] + x_real[b];
+               t2 = x_real[a] - x_real[b];
+               t3 = x_imag[a] + x_imag[b];
+               t4 = x_imag[a] - x_imag[b];
+               t5 = t2*w_imag[k] + t3*w_real[k];
+               t6 = t3*w_imag[k] - t2*w_real[k];
+
+               x_real[a] = (FLOAT) (t1+t5) / 2.0;
+               x_imag[a] = (FLOAT) (t6+t4) / 2.0;
+               x_real[b] = (FLOAT) (t1-t5) / 2.0;
+               x_imag[b] = (FLOAT) (t6-t4) / 2.0;
+
+               k += off;
+       }
+       /* x_real[N/2] doesn«t change */
+       /* x_real[N/2] changes the sign in case of a normal fft */
+#if (NORMAL_FFT)
+#if REORDER_DATA
+       x_imag[i] = -x_imag[i];
+#else
+       x_imag[pSwap[i]] *= -1.0;
+#endif   /* REORDER_DATA */
+#endif   /* NORMAL_FFT */
+       N = N_ORG;
+#endif   /* REAL_SEQUENCE */
+
+
+       /* calculating the energy and phase, phi */
+#if USED_VALUES_ONLY
+       if (N == BLKSIZE)
+       {
+               min_i = LONG_FFT_MIN_IDX;
+               max_i = LONG_FFT_MAX_IDX;
+       }
+       else
+       {
+               min_i = SHORT_FFT_MIN_IDX;
+               max_i = SHORT_FFT_MAX_IDX;
+       }
+#endif
+#if REAL_SEQUENCE
+       for (i = 0;  i <= N/2;  i++)
+#else
+       for (i = 0;  i < N;  i++)
+#endif
+       {
+#if REORDER_DATA
+#define                a       i
+#else
+               a = pSwap[i];
+#endif
+               energy[i] = x_real[a]*x_real[a] + x_imag[a]*x_imag[a];
+               if(energy[i] <= 0.0005)
+               {
+                       energy[i] = (FLOAT) 0.0005;        /* keep the identity */
+                       x_real[a] = (FLOAT) sqrt(0.0005);  /* energy[i] * cos(phi[i]) == x_real[i] */
+                       x_imag[a] = 0.0;                   /* energy[i] * sin(phi[i]) == x_imag[i] */
+               }
+#if USED_VALUES_ONLY
+               if (i >= min_i  &&  i <= max_i)
+#endif
+               phi[i] = (FLOAT) atan2((double) x_imag[a], (double) x_real[a]);
+       }
+}
+
+
+