Version 0.94.1 of the bladeenc mp3 encoder
[swftools.git] / lib / bladeenc / encode.c
diff --git a/lib/bladeenc/encode.c b/lib/bladeenc/encode.c
new file mode 100644 (file)
index 0000000..30ed93a
--- /dev/null
@@ -0,0 +1,1106 @@
+/*
+                       (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-06  Andre Piotrowski
+
+       -       speed up: complete new, much faster functions 'create_ana_filter()', 'windowFilterSubband()'
+       -                 'WIND_SB_CHANGE_LEVEL' 3 requires a new 'enwindow[]' (see 'tables.c')
+
+       2000-11-22      ap
+
+       -       bug fix: initWindowFilterSubband() -- Dividing the enwindow-entries is allowed to be done once only!
+
+       2000-12-11  ap
+
+       -       speed up: WIND_SB_CHANGE_LEVEL 4
+
+       2001-01-12  ap
+
+       -       bug fix: fixed some typo relevant in case of ORG_BUFFERS == 1
+*/
+
+#include "common.h"
+#include "encoder.h"
+
+
+
+
+
+/*  ========================================================================================  */
+/*      rebuffer_audio                                                                        */
+/*  ========================================================================================  */
+
+#if ORG_BUFFERS
+
+void rebuffer_audio
+(
+       short                                   buffer[2][1152],
+       short                                   *insamp,
+       unsigned int                    samples_read,
+       int                                             stereo
+)
+{
+       unsigned int                    j;
+
+       if (stereo == 2)
+       { 
+               for (j = 0;  j < samples_read/2;  j++)
+               {
+                       buffer[0][j] = insamp[2*j];
+                       buffer[1][j] = insamp[2*j+1];
+               }
+       }
+       else
+       {               
+               for (j = 0;  j < samples_read;  j++)
+               {
+                       buffer[0][j] = insamp[j];
+                       buffer[1][j] = 0;
+               }
+       }
+
+       for( ;  j < 1152;  j++)
+       {
+               buffer[0][j] = 0;
+               buffer[1][j] = 0;
+       }
+
+       return;
+}
+
+#else
+
+#define                FLUSH                                   1152
+#define                DELAY                                    768
+
+void rebuffer_audio
+(
+       const short                             *insamp,
+       FLOAT                                   buffer[2][2048],
+       int                                             *buffer_idx,
+       unsigned int                    samples_read,
+       int                                             stereo
+)
+{
+       int                                             idx, med, fin;
+
+       /* flush the last two read granules */
+       *buffer_idx = (*buffer_idx + FLUSH) & 2047;
+       idx = (*buffer_idx + DELAY) & 2047;
+       fin = (idx + FLUSH) & 2047;
+
+       if (stereo == 2)
+       {
+               med = (idx + samples_read/2) & 2047;
+               if (idx >= med)
+               {
+                       while (idx < 2048)
+                       {
+                               buffer[0][idx] = *insamp++;
+                               buffer[1][idx] = *insamp++;
+                               idx++;
+                       }
+                       idx = 0;
+               }
+               while (idx < med)
+               {
+                       buffer[0][idx] = *insamp++;
+                       buffer[1][idx] = *insamp++;
+                       idx++;
+               }
+       }
+       else
+       {               
+               med = (idx + samples_read) & 2047;
+               if (idx >= med)
+               {
+                       while (idx < 2048)
+                       {
+                               buffer[0][idx] = *insamp++;
+                               buffer[1][idx] = 0;
+                               idx++;
+                       }
+                       idx = 0;
+               }
+               while (idx < med)
+               {
+                       buffer[0][idx] = *insamp++;
+                       buffer[1][idx] = 0;
+                       idx++;
+               }
+       }
+
+       if (idx != fin)
+       {
+               if (idx > fin)
+               {
+                       while (idx < 2048)
+                       {
+                               buffer[0][idx] = 0;
+                               buffer[1][idx] = 0;
+                               idx++;
+                       }
+                       idx = 0;
+               }
+               while (idx < fin)
+               {
+                       buffer[0][idx] = 0;
+                       buffer[1][idx] = 0;
+                       idx++;
+               }
+       }
+}
+
+#endif
+
+
+
+
+
+#if ORG_BUFFERS
+#define WIND_SB_CHANGE_LEVEL   3
+#else
+#define WIND_SB_CHANGE_LEVEL   4
+#endif
+
+
+
+#if WIND_SB_CHANGE_LEVEL==4
+
+       typedef double                  filter_matrix[SBLIMIT/4][32];
+
+       static  filter_matrix   m;
+
+       /*  ========================================================================================  */
+       /*      create_ana_filter                                                                     */
+       /*  ========================================================================================  */
+       /*
+               Calculates the analysis filterbank coefficients and rounds to the 9th decimal place
+               accuracy of the filterbank tables in the ISO document.
+               The coefficients are stored in #new_filter#
+
+
+               Originally was computed
+
+                       filter[i][j]  :=  cos (PI64 * ((2*i+1) * (16-j)))
+
+               for i = 0..SBLIMIT-1 and j = 0..63 .
+
+
+               But for j = 0..15 is 16-j = -(16-(32-j)) which implies
+
+               (1)             filter[i][j]  =  filter[i][32-j] .
+
+               (We know that filter[i][16] = cos(0) = 1 , but that is not so interesting.)
+
+               Furthermore, for j = 33..48 we get
+
+                                  filter[i][96-j]
+                               =  cos (PI64 * (2*i+1) * (j-80))
+                               =  cos (PI * (2*i+1) + PI64 * (2*i+1) * (16-j))
+               (2)             =  cos (PI * (2*i+1)) * cos (PI64 * (2*i+1) * (16-j))   // sin (PI * (2*i+1)) = 0
+                               =  -cos (PI64 * (2*i+1) * (16-j))
+                               =  -filter[i][j] ,
+
+               especially is filter[i][48] = 0 .
+
+
+               On the other hand there is
+
+                                  filter[31-i][j]
+                               =  cos (PI64 * (2*(31-i)+1) * (16-j))
+                               =  cos (PI64 * (64-(2*i+1)) * (16-j))
+                               =  cos (PI * (16-j) - PI64 * (2*i+1) * (16-j))
+                               =  cos (PI * (16-j)) * cos (PI64 * (2*i+1) * (16-j))   // sin (PI * (16-j)) = 0
+                               =  (-1)^^j * cos (PI64 * (2*i+1) * (16-j))
+                               =  (-1)^^j * filter[i][j] .
+
+
+               There is a third somewhat more complication "symmetry":
+
+                                  filter[15-i][j]
+                               =  cos (PI64 * (2*(15-i)+1) * (16-j))
+                               =  cos (PI64 * (32-(2*i+1)) * (16-j))
+                               =  cos (PI/2 * (16-j) - PI64 * (2*i+1) * (16-j))
+                               =  cos (PI/2 * (16-j)) * cos (PI64 * (2*i+1) * (16-j)) + sin (PI/2 * (16-j)) * sin (PI64 * (2*i+1) * (16-j))
+                               =  cos (PI/2 * (16-j)) * cos (PI64 * (2*i+1) * (16-j)) + sin (PI/2 * (16-j)) * cos (PI64 * (2*i+1) * (-1)^^i * (16-(j+32)))
+
+                               =  (-1)^^(  j  /2    ) * filter[i][j   ]   for even j
+                               =  (-1)^^((j+1)/2 + i) * filter[i][j+32]   for odd  j  with  j <  32
+                               =  (-1)^^((j-1)/2 + i) * filter[i][j-32]   for odd  j  with  j >= 32
+
+
+               For these reasons we create a filter of the eighth size only and set
+
+                       new_filter[i][j]  :=  filter[i][j]       for i = 0..SBLIMIT/4-1 and j =  0..16
+                       new_filter[i][j]  :=  filter[i][j+16]    for i = 0..SBLIMIT/4-1 and j = 17..31
+       */
+
+       static  void create_ana_filter (double new_filter[SBLIMIT/4][32])
+       {
+               register int                    i, j;
+               double                                  t;
+
+               for (i = 0;  i < SBLIMIT/4;  i++)
+               {
+                       for (j = 0;  j <= 16;  j++)
+                       {
+                               t = 1e9 * cos (PI64 * (double) ((2*i+1) * (16-j)));
+                               if (t >= 0)
+                                       modf (t + 0.5, &t);
+                               else
+                                       modf (t - 0.5, &t);
+                               new_filter[i][j] = t * 1e-9;
+                       }
+                       for (j = 17;  j < 32;  j++)
+                       {
+                               t = 1e9 * cos (PI64 * (double) ((2*i+1) * j));   /* (16-(j+16)) */
+                               if (t >= 0)
+                                       modf (t + 0.5, &t);
+                               else
+                                       modf (t - 0.5, &t);
+                               new_filter[i][j] = t * 1e-9;
+                       }
+               }
+       }
+
+       /*  ========================================================================================  */
+       /*      windowFilterSubband                                                                   */
+       /*  ========================================================================================  */
+       /*
+               Calculates the analysis filter bank coefficients
+
+               The windowed samples #z# is filtered by the digital filter matrix #m# to produce the
+               subband samples #s#. This done by first selectively picking out values from the windowed
+               samples, and then multiplying them by the filter matrix, producing 32 subband samples.
+       */
+
+       void  windowFilterSubband
+       (
+               const FLOAT                             *buffer,
+               int                                             buffer_idx,
+               double                                  s[SBLIMIT]
+       )
+       {
+               int                                             i, k;
+
+               double                                  t, u, v, w;
+
+               double                                  z[32];
+               double                                  *p;
+               double                                  *pEnw;
+
+               pEnw = enwindow;
+
+               for (k = 0;  k <= 16;  k++)
+               {
+                       t =  buffer[(buffer_idx+511) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+447) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+383) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+319) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+255) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+191) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+127) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+ 63) & 2047] * *pEnw++;
+                       z[k] = t;
+
+                       buffer_idx--;
+               }                       
+
+               for (k = 15;  k >= 0;  k--)
+               {
+                       t =  buffer[(buffer_idx+511) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+447) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+383) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+319) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+255) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+191) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+127) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+ 63) & 2047] * *pEnw++;
+                       z[k] += t;
+
+                       buffer_idx--;
+               }                       
+
+               for (k = 17;  k < 32;  k++)
+               {
+                       t =  buffer[(buffer_idx+511) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+447) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+383) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+319) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+255) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+191) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+127) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+ 63) & 2047] * *pEnw++;
+                       z[k] = t;
+
+                       buffer_idx--;
+               }                       
+
+               /* normally y[48] was computed like the other entries, */
+               /* but this entry is not needed because m[i][48] = 0.  */
+               buffer_idx--; /* But we have to increase the pointers. */
+               pEnw += 8;
+
+               for (k = 31;  k > 16;  k--)
+               {
+                       t =  buffer[(buffer_idx+511) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+447) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+383) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+319) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+255) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+191) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+127) & 2047] * *pEnw++;
+                       t += buffer[(buffer_idx+ 63) & 2047] * *pEnw++;
+                       z[k] -= t;
+
+                       buffer_idx--;
+               }                       
+
+               for (i = 0;  i < SBLIMIT/4;  i++)
+               {
+                       p = m[i];
+
+                       t = u = v = w = 0.0;
+                       for (k = 0;  k < 16;  k += 4)
+                       {
+                               t += p[k   ] * z[k  ];
+                               v += p[k+ 2] * z[k+2];
+                               u += p[k+ 1] * z[k+1] + p[k+ 3] * z[k+3];
+                               w -= p[k+17] * z[k+1] - p[k+19] * z[k+3];
+                       }
+                       for ( ;  k < 32;  k += 4)
+                       {
+                               t += p[k   ] * z[k  ];
+                               v += p[k+ 2] * z[k+2];
+                               u += p[k+ 1] * z[k+1] + p[k+ 3] * z[k+3];
+                               w += p[k-15] * z[k+1] - p[k-13] * z[k+3];
+                       }
+
+                       s[          i] = (t + v) + u;
+                       s[SBLIMIT-1-i] = (t + v) - u;
+                       if (i & 1)
+                       {
+                               s[SBLIMIT/2-1-i] = (t - v) - w;
+                               s[SBLIMIT/2  +i] = (t - v) + w;
+                       }
+                       else
+                       {
+                               s[SBLIMIT/2-1-i] = (t - v) + w;
+                               s[SBLIMIT/2  +i] = (t - v) - w;
+                       }
+               }        
+       }
+
+#elif WIND_SB_CHANGE_LEVEL==3
+
+       #define imax                    (SBLIMIT/4)
+       typedef double                  filter_matrix[imax][32];
+
+       static  int                             half[2];
+       static  int                             off[2];
+       static  double                  x[2][512];
+       static  filter_matrix   m;
+
+       /*  ========================================================================================  */
+       /*      create_ana_filter                                                                     */
+       /*  ========================================================================================  */
+       /*
+               Calculates the analysis filterbank coefficients and rounds to the 9th decimal place
+               accuracy of the filterbank tables in the ISO document.
+               The coefficients are stored in #new_filter#
+
+
+               Originally was computed
+
+                       filter[i][j]  :=  cos (PI64 * ((2*i+1) * (16-j)))
+
+               for i = 0..SBLIMIT-1 and j = 0..63 .
+
+
+               But for j = 0..15 is 16-j = -(16-(32-j)) which implies
+
+               (1)             filter[i][j]  =  filter[i][32-j] .
+
+               (We know that filter[i][16] = cos(0) = 1 , but that is not so interesting.)
+
+               Furthermore, for j = 33..48 we get
+
+                                  filter[i][96-j]
+                               =  cos (PI64 * (2*i+1) * (j-80))
+                               =  cos (PI * (2*i+1) + PI64 * (2*i+1) * (16-j))
+               (2)             =  cos (PI * (2*i+1)) * cos (PI64 * (2*i+1) * (16-j))   // sin (PI * (2*i+1)) = 0
+                               =  -cos (PI64 * (2*i+1) * (16-j))
+                               =  -filter[i][j] ,
+
+               especially is filter[i][48] = 0 .
+
+
+               On the other hand there is
+
+                                  filter[31-i][j]
+                               =  cos (PI64 * (2*(31-i)+1) * (16-j))
+                               =  cos (PI64 * (64-(2*i+1)) * (16-j))
+                               =  cos (PI * (16-j) - PI64 * (2*i+1) * (16-j))
+                               =  cos (PI * (16-j)) * cos (PI64 * (2*i+1) * (16-j))   // sin (PI * (16-j)) = 0
+                               =  (-1)^^j * cos (PI64 * (2*i+1) * (16-j))
+                               =  (-1)^^j * filter[i][j] .
+
+
+               There is a third somewhat more complication "symmetry":
+
+                                  filter[15-i][j]
+                               =  cos (PI64 * (2*(15-i)+1) * (16-j))
+                               =  cos (PI64 * (32-(2*i+1)) * (16-j))
+                               =  cos (PI/2 * (16-j) - PI64 * (2*i+1) * (16-j))
+                               =  cos (PI/2 * (16-j)) * cos (PI64 * (2*i+1) * (16-j)) + sin (PI/2 * (16-j)) * sin (PI64 * (2*i+1) * (16-j))
+                               =  cos (PI/2 * (16-j)) * cos (PI64 * (2*i+1) * (16-j)) + sin (PI/2 * (16-j)) * cos (PI64 * (2*i+1) * (-1)^^i * (16-(j+32)))
+
+                               =  (-1)^^(  j  /2    ) * filter[i][j   ]   for even j
+                               =  (-1)^^((j+1)/2 + i) * filter[i][j+32]   for odd  j  with  j <  32
+                               =  (-1)^^((j-1)/2 + i) * filter[i][j-32]   for odd  j  with  j >= 32
+
+
+               For these reasons we create a filter of the eighth size only and set
+
+                       new_filter[i][j]  :=  filter[i][j]       for i = 0..SBLIMIT/4-1 and j =  0..16
+                       new_filter[i][j]  :=  filter[i][j+16]    for i = 0..SBLIMIT/4-1 and j = 17..31
+       */
+
+       static  void create_ana_filter (double new_filter[imax][32])
+       {
+               register int                    i, j;
+               double                                  t;
+
+               for (i = 0;  i < imax;  i++)
+               {
+                       for (j = 0;  j <= 16;  j++)
+                       {
+                               t = 1e9 * cos (PI64 * (double) ((2*i+1) * (16-j)));
+                               if (t >= 0)
+                                       modf (t + 0.5, &t);
+                               else
+                                       modf (t - 0.5, &t);
+                               new_filter[i][j] = t * 1e-9;
+                       }
+                       for (j = 17;  j < 32;  j++)
+                       {
+                               t = 1e9 * cos (PI64 * (double) ((2*i+1) * j));   /* (16-(j+16)) */
+                               if (t >= 0)
+                                       modf (t + 0.5, &t);
+                               else
+                                       modf (t - 0.5, &t);
+                               new_filter[i][j] = t * 1e-9;
+                       }
+               }
+       }
+
+       /*  ========================================================================================  */
+       /*      windowFilterSubband                                                                   */
+       /*  ========================================================================================  */
+       /*
+               Calculates the analysis filter bank coefficients
+
+               The windowed samples #z# is filtered by the digital filter matrix #m# to produce the
+               subband samples #s#. This done by first selectively picking out values from the windowed
+               samples, and then multiplying them by the filter matrix, producing 32 subband samples.
+       */
+
+       void  windowFilterSubband
+       (
+               short                                   *pBuffer,
+               int                                             ch,
+               double                                  s[SBLIMIT]
+       )
+       {
+               int                                             i, k;
+               int                                             a;
+
+               double                                  t, u, v, w;
+
+               double                                  z[32];
+               double                                  *pm;
+               double                                  *px;
+               double                                  *pEnw;
+
+
+               px = x[ch] + half[ch];
+               a = off[ch];
+
+               /* replace 32 oldest samples with 32 new samples */
+
+               for (i = 0;  i < 32;  i++)
+                       px[a + (31-i)*8] = (double) pBuffer[i]/*/SCALE*/;
+
+
+               pEnw = enwindow;
+
+               for (k = 0;  k <= 16;  k++)
+               {
+                       t =  px[(a+0) & 7] * *pEnw++;
+                       t += px[(a+1) & 7] * *pEnw++;
+                       t += px[(a+2) & 7] * *pEnw++;
+                       t += px[(a+3) & 7] * *pEnw++;
+                       t += px[(a+4) & 7] * *pEnw++;
+                       t += px[(a+5) & 7] * *pEnw++;
+                       t += px[(a+6) & 7] * *pEnw++;
+                       t += px[(a+7) & 7] * *pEnw++;
+                       z[k] = t;
+
+                       px += 8;
+               }                       
+
+               for (k = 15;  k > 0;  k--)
+               {
+                       t =  px[(a+0) & 7] * *pEnw++;
+                       t += px[(a+1) & 7] * *pEnw++;
+                       t += px[(a+2) & 7] * *pEnw++;
+                       t += px[(a+3) & 7] * *pEnw++;
+                       t += px[(a+4) & 7] * *pEnw++;
+                       t += px[(a+5) & 7] * *pEnw++;
+                       t += px[(a+6) & 7] * *pEnw++;
+                       t += px[(a+7) & 7] * *pEnw++;
+                       z[k] += t;
+
+                       px += 8;
+               }                       
+
+               half[ch] ^= 256;   /* toggling 0 or 256 */
+               if (half[ch])
+               {
+                       off[ch] = (a + 7) & 7;
+               }
+               else
+               {
+                       px = x[ch];
+                       a = (a + 1) & 7;
+               }
+
+               /* k = 0; */
+               {
+                       t =  px[(a+0) & 7] * *pEnw++;
+                       t += px[(a+1) & 7] * *pEnw++;
+                       t += px[(a+2) & 7] * *pEnw++;
+                       t += px[(a+3) & 7] * *pEnw++;
+                       t += px[(a+4) & 7] * *pEnw++;
+                       t += px[(a+5) & 7] * *pEnw++;
+                       t += px[(a+6) & 7] * *pEnw++;
+                       t += px[(a+7) & 7] * *pEnw++;
+                       z[k] += t;
+
+                       px += 8;
+               }                       
+
+               for (k = 17;  k < 32;  k++)
+               {
+                       t =  px[(a+0) & 7] * *pEnw++;
+                       t += px[(a+1) & 7] * *pEnw++;
+                       t += px[(a+2) & 7] * *pEnw++;
+                       t += px[(a+3) & 7] * *pEnw++;
+                       t += px[(a+4) & 7] * *pEnw++;
+                       t += px[(a+5) & 7] * *pEnw++;
+                       t += px[(a+6) & 7] * *pEnw++;
+                       t += px[(a+7) & 7] * *pEnw++;
+                       z[k] = t;
+
+                       px += 8;
+               }                       
+
+               /* normally y[48] was computed like the other entries, */
+               /* but this entry is not needed because m[i][48] = 0.  */
+               px += 8;      /* But we have to increase the pointers. */
+               pEnw += 8;
+
+               for (k = 31;  k > 16;  k--)
+               {
+                       t =  px[(a+0) & 7] * *pEnw++;
+                       t += px[(a+1) & 7] * *pEnw++;
+                       t += px[(a+2) & 7] * *pEnw++;
+                       t += px[(a+3) & 7] * *pEnw++;
+                       t += px[(a+4) & 7] * *pEnw++;
+                       t += px[(a+5) & 7] * *pEnw++;
+                       t += px[(a+6) & 7] * *pEnw++;
+                       t += px[(a+7) & 7] * *pEnw++;
+                       z[k] -= t;
+
+                       px += 8;
+               }                       
+
+               for (i = 0;  i < imax;  i++)
+               {
+                       pm = m[i];
+
+                       t = u = v = w = 0.0;
+                       for (k = 0;  k < 16;  k += 4)
+                       {
+                               t += pm[k   ] * z[k  ];
+                               v += pm[k+ 2] * z[k+2];
+                               u += pm[k+ 1] * z[k+1] + pm[k+ 3] * z[k+3];
+                               w -= pm[k+17] * z[k+1] - pm[k+19] * z[k+3];
+                       }
+                       for (   ;  k < 32;  k += 4)
+                       {
+                               t += pm[k   ] * z[k  ];
+                               v += pm[k+ 2] * z[k+2];
+                               u += pm[k+ 1] * z[k+1] + pm[k+ 3] * z[k+3];
+                               w += pm[k-15] * z[k+1] - pm[k-13] * z[k+3];
+                       }
+
+                       s[          i] = (t + v) + u;
+                       s[SBLIMIT-1-i] = (t + v) - u;
+                       if (i & 1)
+                       {
+                               s[SBLIMIT/2-1-i] = (t - v) - w;
+                               s[SBLIMIT/2  +i] = (t - v) + w;
+                       }
+                       else
+                       {
+                               s[SBLIMIT/2-1-i] = (t - v) + w;
+                               s[SBLIMIT/2  +i] = (t - v) - w;
+                       }
+               }        
+       }
+
+#elif WIND_SB_CHANGE_LEVEL==2
+
+       typedef double                  filter_matrix[SBLIMIT/2][32];
+
+       static  int                             off[2];
+       static  int                             half[2];
+       static  double                  x[2][512];
+       static  filter_matrix   m;
+
+       /*  ========================================================================================  */
+       /*      create_ana_filter                                                                     */
+       /*  ========================================================================================  */
+       /*
+               Calculates the analysis filterbank coefficients and rounds to the 9th decimal place
+               accuracy of the filterbank tables in the ISO document.
+               The coefficients are stored in #new_filter#
+
+
+               Originally was computed
+
+                       filter[i][j]  :=  cos (PI64 * ((2*i+1) * (16-j)))
+
+               for i = 0..SBLIMIT-1 and j = 0..63 .
+
+
+               But for j = 0..15 is 16-j = -(16-(32-j)) which implies
+
+               (1)             filter[i][j]  =  filter[i][32-j] .
+
+               (We know that filter[i][16] = cos(0) = 1 , but that is not so interesting.)
+
+               Furthermore, for j = 33..48 we get
+
+                                  filter[i][96-j]
+                               =  cos (PI64 * (2*i+1) * (j-80))
+                               =  cos (PI * (2*i+1) + PI64 * (2*i+1) * (16-j))
+               (2)             =  cos (PI * (2*i+1)) * cos (PI64 * (2*i+1) * (16-j))   // sin (PI * (2*i+1)) = 0
+                               =  -cos (PI64 * (2*i+1) * (16-j))
+                               =  -filter[i][j] ,
+
+               especially is filter[i][48] = 0 .
+
+
+               On the other hand there is
+
+                                  filter[31-i][j]
+                               =  cos (PI64 * (2*(31-i)+1) * (16-j))
+                               =  cos (PI64 * (64-(2*i+1)) * (16-j))
+                               =  cos (PI * (16-j) - PI64 * (2*i+1) * (16-j))
+                               =  cos (PI * (16-j)) * cos (PI64 * (2*i+1) * (16-j))   // sin (PI * (16-j)) = 0
+                               =  (-1)^^j * cos (PI64 * (2*i+1) * (16-j))
+                               =  (-1)^^j * filter[i][j] .
+
+
+               For these reasons we create a filter of the quarter size only and set
+
+                       new_filter[i][j]  :=  filter[i][j]       for i = 0..SBLIMIT/2-1 and j =  0..16
+                       new_filter[i][j]  :=  filter[i][j+16]    for i = 0..SBLIMIT/2-1 and j = 17..31
+       */
+
+       static  void create_ana_filter (double new_filter[SBLIMIT/2][32])
+       {
+               register int                    i, j;
+               double                                  t;
+
+               for (i = 0;  i < SBLIMIT/2;  i++)
+               {
+                       for (j = 0;  j < =16;  j++)
+                       {
+                               t = 1e9 * cos (PI64 * (double) ((2*i+1) * (16-j)));
+                               if (t >= 0)
+                                       modf (t + 0.5, &t);
+                               else
+                                       modf (t - 0.5, &t);
+                               new_filter[i][j] = t * 1e-9;
+                       }
+                       for (j = 17;  j < 32;  j++)
+                       {
+                               t = 1e9 * cos (PI64 * (double) ((2*i+1) * j));   /* (16-(j+16)) */
+                               if (t >= 0)
+                                       modf (t + 0.5, &t);
+                               else
+                                       modf (t - 0.5, &t);
+                               new_filter[i][j] = t * 1e-9;
+                       }
+               }
+       }
+
+       /*  ========================================================================================  */
+       /*      windowFilterSubband                                                                   */
+       /*  ========================================================================================  */
+       /*
+               Calculates the analysis filter bank coefficients
+
+               The windowed samples #z# is filtered by the digital filter matrix #m# to produce the
+               subband samples #s#. This done by first selectively picking out values from the windowed
+               samples, and then multiplying them by the filter matrix, producing 32 subband samples.
+       */
+
+       void  windowFilterSubband
+       (
+               short                                   *pBuffer,
+               int                                             ch,
+               double                                  s[SBLIMIT]
+       )
+       {
+               int                                             i, k;
+               int                                             a;
+
+               double                                  t, u;
+
+               double                                  z[32];   /* y[64]; */
+               double                                  *pm;
+               double                                  *px;
+               double                                  *pEnw;
+
+
+               px = x[ch] + half[ch];
+               a = off[ch];
+
+               /* replace 32 oldest samples with 32 new samples */
+
+               for (i = 0;  i < 32;  i++)
+                       px[a + (31-i)*8] = (double) pBuffer[i] /*/SCALE*/;
+
+
+               /*
+                       for k = 0..15 we compute
+
+                               z[k]  :=  y[k] + y[32-k]
+
+                       and we set
+
+                               z[16|  :=  y[16] .
+               */
+
+               pEnw = enwindow;
+
+               for (k = 0;  k <= 16;  k++)   /* for (j = 0;  j < =16;  j++) */
+               {
+                       t =  px[(a+0) & 7] * pEnw[64*0];
+                       t += px[(a+1) & 7] * pEnw[64*1];
+                       t += px[(a+2) & 7] * pEnw[64*2];
+                       t += px[(a+3) & 7] * pEnw[64*3];
+                       t += px[(a+4) & 7] * pEnw[64*4];
+                       t += px[(a+5) & 7] * pEnw[64*5];
+                       t += px[(a+6) & 7] * pEnw[64*6];
+                       t += px[(a+7) & 7] * pEnw[64*7];
+                       z[k] = t;   /* y[j] = t; */
+
+                       px += 8;
+                       pEnw++;
+               }                       
+
+               for (k = 15;  k > 0;  k--)   /* for (j = 17;  j < 32;  j++) */
+               {
+                       t =  px[(a+0) & 7] * pEnw[64*0];
+                       t += px[(a+1) & 7] * pEnw[64*1];
+                       t += px[(a+2) & 7] * pEnw[64*2];
+                       t += px[(a+3) & 7] * pEnw[64*3];
+                       t += px[(a+4) & 7] * pEnw[64*4];
+                       t += px[(a+5) & 7] * pEnw[64*5];
+                       t += px[(a+6) & 7] * pEnw[64*6];
+                       t += px[(a+7) & 7] * pEnw[64*7];
+                       z[k] += t;   /* y[j] = t; */
+
+                       px += 8;
+                       pEnw++;
+               }                       
+
+               half[ch] ^= 256;   /* toggling 0 or 256 */
+               if (half[ch])
+               {
+                       off[ch] = (a + 7) & 7;   /*offset is modulo (HAN_SIZE-1)*/
+               }
+               else
+               {
+                       px = x[ch];
+                       a = (a + 1) & 7;
+               }
+
+               /* k = 0; not needed, actual value of k is 0 */   /* j = 32; */
+               {
+                       t =  px[(a+0) & 7] * pEnw[64*0];
+                       t += px[(a+1) & 7] * pEnw[64*1];
+                       t += px[(a+2) & 7] * pEnw[64*2];
+                       t += px[(a+3) & 7] * pEnw[64*3];
+                       t += px[(a+4) & 7] * pEnw[64*4];
+                       t += px[(a+5) & 7] * pEnw[64*5];
+                       t += px[(a+6) & 7] * pEnw[64*6];
+                       t += px[(a+7) & 7] * pEnw[64*7];
+                       z[k] += t;   /* y[j] = t; */
+
+                       px += 8;
+                       pEnw++;
+               }                       
+
+               /*
+                       for k = 17..31 we compute
+
+                               z[k]  :=  y[k+16] - y[80-k]
+               */
+
+               for (k = 17;  k < 32;  k++)   /* for (j = 33;  j < 47;  j++) */
+               {
+                       t =  px[(a+0) & 7] * pEnw[64*0];
+                       t += px[(a+1) & 7] * pEnw[64*1];
+                       t += px[(a+2) & 7] * pEnw[64*2];
+                       t += px[(a+3) & 7] * pEnw[64*3];
+                       t += px[(a+4) & 7] * pEnw[64*4];
+                       t += px[(a+5) & 7] * pEnw[64*5];
+                       t += px[(a+6) & 7] * pEnw[64*6];
+                       t += px[(a+7) & 7] * pEnw[64*7];
+                       z[k] = t;   /* y[j] = t; */
+
+                       px += 8;
+                       pEnw++;
+               }                       
+
+               /* normally y[48] was computed like the other entries, */
+               /* but this entry is not needed because m[i][48] = 0.  */
+               px += 8;      /* But we have to increase the pointers. */
+               pEnw++;
+
+               for (k = 31;  k > 16;  k--)   /* for (j = 49;  j < 64;  j++) */
+               {
+                       t =  px[(a+0) & 7] * pEnw[64*0];
+                       t += px[(a+1) & 7] * pEnw[64*1];
+                       t += px[(a+2) & 7] * pEnw[64*2];
+                       t += px[(a+3) & 7] * pEnw[64*3];
+                       t += px[(a+4) & 7] * pEnw[64*4];
+                       t += px[(a+5) & 7] * pEnw[64*5];
+                       t += px[(a+6) & 7] * pEnw[64*6];
+                       t += px[(a+7) & 7] * pEnw[64*7];
+                       z[k] -= t;   /* y[j] = t; */
+
+                       px += 8;
+                       pEnw++;
+               }                       
+
+               pm = m[0];                           /* pm = m[0];                      */
+               for (i = 0;  i < SBLIMIT/2;  i++)    /* for (i = 0;  i < SBLIMIT;  i++) */
+               {
+
+                       t = u = 0.0;                     /*    t = 0.0;                     */
+                       for (k = 0;  k < 32; )           /*    for (j = 0;  j < 64;  j++)   */
+                       {
+                               t += *pm++ * z[k++];         /*       t += *pm++ * y[j];        */
+                               u += *pm++ * z[k++];
+                       }
+
+                       s[          i] = t + u;          /*    s[i] = t;                    */
+                       s[SBLIMIT-1-i] = t - u;
+               }        
+       }
+
+#elif WIND_SB_CHANGE_LEVEL==1
+
+       typedef double                  filter_matrix[SBLIMIT][64];
+
+       static  int                             off[2];
+       static  int                             half[2];
+       static  double                  x[2][512];
+       static  filter_matrix   m;
+
+       /*  ========================================================================================  */
+       /*      create_ana_filter                                                                     */
+       /*  ========================================================================================  */
+       /*
+               Calculates the analysis filterbank coefficients and rounds to the 9th decimal place
+               accuracy of the filterbank tables in the ISO document.
+               The coefficients are stored in #filter#
+       */
+
+       static  void create_ana_filter (filter_matrix filter)
+       {
+               register int                    i, j;
+               double                                  t;
+
+               for (i = 0;  i < SBLIMIT;  i++)
+               {
+                       for (j = 0;  j < 64;  j++)
+                       {
+                               t = 1e9 * cos (PI64 * (double) ((2*i+1) * (16-j)));
+                               if (t >= 0)
+                                       modf (t + 0.5, &t);
+                               else
+                                       modf (t - 0.5, &t);
+                               filter[i][j] = t * 1e-9;
+                       }
+               }
+       }
+
+       /*  ========================================================================================  */
+       /*      windowFilterSubband                                                                   */
+       /*  ========================================================================================  */
+       /*
+               Calculates the analysis filter bank coefficients
+
+               The windowed samples #y# is filtered by the digital filter matrix #m# to produce the
+               subband samples #s#. This done by first selectively picking out values from the windowed
+               samples, and then multiplying them by the filter matrix, producing 32 subband samples.
+       */
+
+       void  windowFilterSubband
+       (
+               short                                   *pBuffer,
+               int                                             ch,
+               double                                  s[SBLIMIT]
+       )
+       {
+               int                                             i, j;
+               int                                             a;
+
+               double                                  t;
+
+               double                                  y[64];
+               double                                  *pm;
+               double                                  *px;
+               double                                  *pEnw;
+
+
+               px = x[ch] + half[ch];
+               a = off[ch];
+
+               /* replace 32 oldest samples with 32 new samples */
+
+               for (i = 0;  i < 32;  i++)
+                       px[a + (31-i)*8] = (double) pBuffer[i] /*/SCALE*/;
+
+
+               pEnw = enwindow;
+
+               for (j = 0;  j < 32;  j++)
+               {
+                       t =  px[(a+0) & 7] * pEnw[64*0];
+                       t += px[(a+1) & 7] * pEnw[64*1];
+                       t += px[(a+2) & 7] * pEnw[64*2];
+                       t += px[(a+3) & 7] * pEnw[64*3];
+                       t += px[(a+4) & 7] * pEnw[64*4];
+                       t += px[(a+5) & 7] * pEnw[64*5];
+                       t += px[(a+6) & 7] * pEnw[64*6];
+                       t += px[(a+7) & 7] * pEnw[64*7];
+                       y[j] = t;
+
+                       px += 8;
+                       pEnw++;
+               }                       
+
+               half[ch] ^= 256;   /* toggling 0 or 256 */
+               if (half[ch])
+               {
+                       off[ch] = (a + 7) & 7;   /*offset is modulo (HAN_SIZE-1)*/
+               }
+               else
+               {
+                       px = x[ch];
+                       a = (a + 1) & 7;
+               }
+
+               for (j = 32;  j < 64;  j++)
+               {
+                       t =  px[(a+0) & 7] * pEnw[64*0];
+                       t += px[(a+1) & 7] * pEnw[64*1];
+                       t += px[(a+2) & 7] * pEnw[64*2];
+                       t += px[(a+3) & 7] * pEnw[64*3];
+                       t += px[(a+4) & 7] * pEnw[64*4];
+                       t += px[(a+5) & 7] * pEnw[64*5];
+                       t += px[(a+6) & 7] * pEnw[64*6];
+                       t += px[(a+7) & 7] * pEnw[64*7];
+                       y[j] = t;
+
+                       px += 8;
+                       pEnw++;
+               }                       
+
+               pm = m[0];
+               for (i = 0;  i < SBLIMIT;  i++)
+               {
+                       t = 0.0;
+                       for (j = 0;  j < 64;  j++)
+                               t += *pm++ * y[j];
+
+                       s[i] = t;
+               }        
+       }
+
+#endif
+
+
+
+
+
+/*  ========================================================================================  */
+/*      initWindowFilterSubband                                                               */
+/*  ========================================================================================  */
+
+void initWindowFilterSubband (void)
+{
+       static  int                             initialized = 0;
+
+       int                                             i;
+
+       if (!initialized)
+       {
+               create_ana_filter (m);
+
+               for (i = 0;  i < 512;  i++)
+                       enwindow[i] /= SCALE;
+
+               initialized = 1;
+       }
+
+#if ORG_BUFFERS
+       half[0] = half[1] = 0;
+       off[0] = off[1] = 0;
+       memset (x, 0, sizeof(x));
+#endif
+}
+
+
+
+
+