18e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/********************************************************************
28e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels *                                                                  *
38e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
48e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
58e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
68e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
78e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels *                                                                  *
88e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009             *
98e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels * by the Xiph.Org Foundation http://www.xiph.org/                  *
108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels *                                                                  *
118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels ********************************************************************
128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels function: normalized modified discrete cosine transform
148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           power of two length transform only [64 <= n ]
158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels last mod: $Id: mdct.c 16227 2009-07-08 06:58:46Z xiphmont $
168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels Original algorithm adapted long ago from _The use of multirate filter
188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels banks for coding of high quality digital audio_, by T. Sporer,
198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels K. Brandenburg and B. Edler, collection of the European Signal
208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels Processing Conference (EUSIPCO), Amsterdam, June 1992, Vol.1, pp
218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels 211-214
228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels The below code implements an algorithm that no longer looks much like
248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels that presented in the paper, but the basic structure remains if you
258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels dig deep enough to see it.
268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels This module DOES NOT INCLUDE code to generate/apply the window
288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels function.  Everybody has their own weird favorite including me... I
298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels happen to like the properties of y=sin(.5PI*sin^2(x)), but others may
308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels vehemently disagree.
318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels ********************************************************************/
338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* this can also be run as an integer transform by uncommenting a
358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels   define in mdct.h; the integerization is a first pass and although
368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels   it's likely stable for Vorbis, the dynamic range is constrained and
378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels   roundoff isn't done (so it's noisy).  Consider it functional, but
388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels   only a starting point.  There's no point on a machine with an FPU */
398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <stdio.h>
418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <stdlib.h>
428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <string.h>
438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include <math.h>
448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include "vorbis/codec.h"
458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include "mdct.h"
468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include "os.h"
478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels#include "misc.h"
488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* build lookups for trig functions; also pre-figure scaling and
508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels   some window function algebra. */
518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid mdct_init(mdct_lookup *lookup,int n){
538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int   *bitrev=_ogg_malloc(sizeof(*bitrev)*(n/4));
548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  DATA_TYPE *T=_ogg_malloc(sizeof(*T)*(n+n/4));
558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i;
578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int n2=n>>1;
588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int log2n=lookup->log2n=rint(log((float)n)/log(2.f));
598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  lookup->n=n;
608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  lookup->trig=T;
618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  lookup->bitrev=bitrev;
628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* trig lookups... */
648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<n/4;i++){
668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    T[i*2]=FLOAT_CONV(cos((M_PI/n)*(4*i)));
678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    T[i*2+1]=FLOAT_CONV(-sin((M_PI/n)*(4*i)));
688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    T[n2+i*2]=FLOAT_CONV(cos((M_PI/(2*n))*(2*i+1)));
698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    T[n2+i*2+1]=FLOAT_CONV(sin((M_PI/(2*n))*(2*i+1)));
708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<n/8;i++){
728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    T[n+i*2]=FLOAT_CONV(cos((M_PI/n)*(4*i+2))*.5);
738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    T[n+i*2+1]=FLOAT_CONV(-sin((M_PI/n)*(4*i+2))*.5);
748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* bitreverse lookup... */
778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  {
798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    int mask=(1<<(log2n-1))-1,i,j;
808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    int msb=1<<(log2n-2);
818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(i=0;i<n/8;i++){
828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      int acc=0;
838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      for(j=0;msb>>j;j++)
848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels        if((msb>>j)&i)acc|=1<<j;
858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      bitrev[i*2]=((~acc)&mask)-1;
868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      bitrev[i*2+1]=acc;
878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }
898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  lookup->scale=FLOAT_CONV(4.f/n);
918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* 8 point butterfly (in place, 4 register) */
948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas EckelsSTIN void mdct_butterfly_8(DATA_TYPE *x){
958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  REG_TYPE r0   = x[6] + x[2];
968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  REG_TYPE r1   = x[6] - x[2];
978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  REG_TYPE r2   = x[4] + x[0];
988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  REG_TYPE r3   = x[4] - x[0];
998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[6] = r0   + r2;
1018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[4] = r0   - r2;
1028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r0   = x[5] - x[1];
1048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r2   = x[7] - x[3];
1058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[0] = r1   + r0;
1068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[2] = r1   - r0;
1078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r0   = x[5] + x[1];
1098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r1   = x[7] + x[3];
1108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[3] = r2   + r3;
1118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[1] = r2   - r3;
1128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[7] = r1   + r0;
1138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[5] = r1   - r0;
1148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
1168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* 16 point butterfly (in place, 4 register) */
1188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas EckelsSTIN void mdct_butterfly_16(DATA_TYPE *x){
1198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  REG_TYPE r0     = x[1]  - x[9];
1208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  REG_TYPE r1     = x[0]  - x[8];
1218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[8]  += x[0];
1238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[9]  += x[1];
1248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[0]   = MULT_NORM((r0   + r1) * cPI2_8);
1258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[1]   = MULT_NORM((r0   - r1) * cPI2_8);
1268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r0     = x[3]  - x[11];
1288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r1     = x[10] - x[2];
1298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[10] += x[2];
1308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[11] += x[3];
1318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[2]   = r0;
1328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[3]   = r1;
1338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r0     = x[12] - x[4];
1358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r1     = x[13] - x[5];
1368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[12] += x[4];
1378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[13] += x[5];
1388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[4]   = MULT_NORM((r0   - r1) * cPI2_8);
1398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[5]   = MULT_NORM((r0   + r1) * cPI2_8);
1408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r0     = x[14] - x[6];
1428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r1     = x[15] - x[7];
1438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[14] += x[6];
1448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[15] += x[7];
1458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[6]  = r0;
1468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[7]  = r1;
1478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           mdct_butterfly_8(x);
1498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           mdct_butterfly_8(x+8);
1508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
1518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* 32 point butterfly (in place, 4 register) */
1538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas EckelsSTIN void mdct_butterfly_32(DATA_TYPE *x){
1548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  REG_TYPE r0     = x[30] - x[14];
1558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  REG_TYPE r1     = x[31] - x[15];
1568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[30] +=         x[14];
1588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[31] +=         x[15];
1598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[14]  =         r0;
1608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[15]  =         r1;
1618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r0     = x[28] - x[12];
1638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r1     = x[29] - x[13];
1648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[28] +=         x[12];
1658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[29] +=         x[13];
1668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[12]  = MULT_NORM( r0 * cPI1_8  -  r1 * cPI3_8 );
1678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[13]  = MULT_NORM( r0 * cPI3_8  +  r1 * cPI1_8 );
1688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r0     = x[26] - x[10];
1708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r1     = x[27] - x[11];
1718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[26] +=         x[10];
1728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[27] +=         x[11];
1738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[10]  = MULT_NORM(( r0  - r1 ) * cPI2_8);
1748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[11]  = MULT_NORM(( r0  + r1 ) * cPI2_8);
1758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r0     = x[24] - x[8];
1778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r1     = x[25] - x[9];
1788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[24] += x[8];
1798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[25] += x[9];
1808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[8]   = MULT_NORM( r0 * cPI3_8  -  r1 * cPI1_8 );
1818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[9]   = MULT_NORM( r1 * cPI3_8  +  r0 * cPI1_8 );
1828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r0     = x[22] - x[6];
1848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r1     = x[7]  - x[23];
1858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[22] += x[6];
1868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[23] += x[7];
1878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[6]   = r1;
1888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[7]   = r0;
1898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r0     = x[4]  - x[20];
1918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r1     = x[5]  - x[21];
1928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[20] += x[4];
1938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[21] += x[5];
1948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[4]   = MULT_NORM( r1 * cPI1_8  +  r0 * cPI3_8 );
1958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[5]   = MULT_NORM( r1 * cPI3_8  -  r0 * cPI1_8 );
1968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
1978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r0     = x[2]  - x[18];
1988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r1     = x[3]  - x[19];
1998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[18] += x[2];
2008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[19] += x[3];
2018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[2]   = MULT_NORM(( r1  + r0 ) * cPI2_8);
2028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[3]   = MULT_NORM(( r1  - r0 ) * cPI2_8);
2038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r0     = x[0]  - x[16];
2058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           r1     = x[1]  - x[17];
2068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[16] += x[0];
2078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[17] += x[1];
2088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[0]   = MULT_NORM( r1 * cPI3_8  +  r0 * cPI1_8 );
2098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           x[1]   = MULT_NORM( r1 * cPI1_8  -  r0 * cPI3_8 );
2108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           mdct_butterfly_16(x);
2128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels           mdct_butterfly_16(x+16);
2138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
2158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* N point first stage butterfly (in place, 2 register) */
2178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas EckelsSTIN void mdct_butterfly_first(DATA_TYPE *T,
2188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                        DATA_TYPE *x,
2198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                        int points){
2208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  DATA_TYPE *x1        = x          + points      - 8;
2228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  DATA_TYPE *x2        = x          + (points>>1) - 8;
2238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  REG_TYPE   r0;
2248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  REG_TYPE   r1;
2258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  do{
2278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               r0      = x1[6]      -  x2[6];
2298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               r1      = x1[7]      -  x2[7];
2308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x1[6]  += x2[6];
2318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x1[7]  += x2[7];
2328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x2[6]   = MULT_NORM(r1 * T[1]  +  r0 * T[0]);
2338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x2[7]   = MULT_NORM(r1 * T[0]  -  r0 * T[1]);
2348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               r0      = x1[4]      -  x2[4];
2368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               r1      = x1[5]      -  x2[5];
2378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x1[4]  += x2[4];
2388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x1[5]  += x2[5];
2398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x2[4]   = MULT_NORM(r1 * T[5]  +  r0 * T[4]);
2408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x2[5]   = MULT_NORM(r1 * T[4]  -  r0 * T[5]);
2418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               r0      = x1[2]      -  x2[2];
2438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               r1      = x1[3]      -  x2[3];
2448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x1[2]  += x2[2];
2458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x1[3]  += x2[3];
2468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x2[2]   = MULT_NORM(r1 * T[9]  +  r0 * T[8]);
2478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x2[3]   = MULT_NORM(r1 * T[8]  -  r0 * T[9]);
2488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               r0      = x1[0]      -  x2[0];
2508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               r1      = x1[1]      -  x2[1];
2518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x1[0]  += x2[0];
2528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x1[1]  += x2[1];
2538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x2[0]   = MULT_NORM(r1 * T[13] +  r0 * T[12]);
2548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x2[1]   = MULT_NORM(r1 * T[12] -  r0 * T[13]);
2558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    x1-=8;
2578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    x2-=8;
2588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    T+=16;
2598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }while(x2>=x);
2618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
2628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels/* N/stage point generic N stage butterfly (in place, 2 register) */
2648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas EckelsSTIN void mdct_butterfly_generic(DATA_TYPE *T,
2658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                          DATA_TYPE *x,
2668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                          int points,
2678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                                          int trigint){
2688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  DATA_TYPE *x1        = x          + points      - 8;
2708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  DATA_TYPE *x2        = x          + (points>>1) - 8;
2718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  REG_TYPE   r0;
2728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  REG_TYPE   r1;
2738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  do{
2758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               r0      = x1[6]      -  x2[6];
2778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               r1      = x1[7]      -  x2[7];
2788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x1[6]  += x2[6];
2798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x1[7]  += x2[7];
2808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x2[6]   = MULT_NORM(r1 * T[1]  +  r0 * T[0]);
2818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x2[7]   = MULT_NORM(r1 * T[0]  -  r0 * T[1]);
2828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               T+=trigint;
2848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               r0      = x1[4]      -  x2[4];
2868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               r1      = x1[5]      -  x2[5];
2878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x1[4]  += x2[4];
2888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x1[5]  += x2[5];
2898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x2[4]   = MULT_NORM(r1 * T[1]  +  r0 * T[0]);
2908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x2[5]   = MULT_NORM(r1 * T[0]  -  r0 * T[1]);
2918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               T+=trigint;
2938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
2948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               r0      = x1[2]      -  x2[2];
2958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               r1      = x1[3]      -  x2[3];
2968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x1[2]  += x2[2];
2978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x1[3]  += x2[3];
2988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x2[2]   = MULT_NORM(r1 * T[1]  +  r0 * T[0]);
2998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x2[3]   = MULT_NORM(r1 * T[0]  -  r0 * T[1]);
3008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               T+=trigint;
3028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               r0      = x1[0]      -  x2[0];
3048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               r1      = x1[1]      -  x2[1];
3058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x1[0]  += x2[0];
3068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x1[1]  += x2[1];
3078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x2[0]   = MULT_NORM(r1 * T[1]  +  r0 * T[0]);
3088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               x2[1]   = MULT_NORM(r1 * T[0]  -  r0 * T[1]);
3098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels               T+=trigint;
3118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    x1-=8;
3128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    x2-=8;
3138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }while(x2>=x);
3158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
3168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas EckelsSTIN void mdct_butterflies(mdct_lookup *init,
3188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                             DATA_TYPE *x,
3198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                             int points){
3208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  DATA_TYPE *T=init->trig;
3228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int stages=init->log2n-5;
3238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i,j;
3248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(--stages>0){
3268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    mdct_butterfly_first(T,x,points);
3278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
3288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=1;--stages>0;i++){
3308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    for(j=0;j<(1<<i);j++)
3318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      mdct_butterfly_generic(T,x+(points>>i)*j,points>>i,4<<i);
3328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
3338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(j=0;j<points;j+=32)
3358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    mdct_butterfly_32(x+j);
3368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
3388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid mdct_clear(mdct_lookup *l){
3408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  if(l){
3418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(l->trig)_ogg_free(l->trig);
3428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    if(l->bitrev)_ogg_free(l->bitrev);
3438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    memset(l,0,sizeof(*l));
3448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
3458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
3468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas EckelsSTIN void mdct_bitreverse(mdct_lookup *init,
3488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels                            DATA_TYPE *x){
3498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int        n       = init->n;
3508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int       *bit     = init->bitrev;
3518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  DATA_TYPE *w0      = x;
3528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  DATA_TYPE *w1      = x = w0+(n>>1);
3538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  DATA_TYPE *T       = init->trig+n;
3548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  do{
3568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    DATA_TYPE *x0    = x+bit[0];
3578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    DATA_TYPE *x1    = x+bit[1];
3588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    REG_TYPE  r0     = x0[1]  - x1[1];
3608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    REG_TYPE  r1     = x0[0]  + x1[0];
3618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    REG_TYPE  r2     = MULT_NORM(r1     * T[0]   + r0 * T[1]);
3628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    REG_TYPE  r3     = MULT_NORM(r1     * T[1]   - r0 * T[0]);
3638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              w1    -= 4;
3658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              r0     = HALVE(x0[1] + x1[1]);
3678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              r1     = HALVE(x0[0] - x1[0]);
3688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              w0[0]  = r0     + r2;
3708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              w1[2]  = r0     - r2;
3718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              w0[1]  = r1     + r3;
3728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              w1[3]  = r3     - r1;
3738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              x0     = x+bit[2];
3758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              x1     = x+bit[3];
3768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              r0     = x0[1]  - x1[1];
3788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              r1     = x0[0]  + x1[0];
3798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              r2     = MULT_NORM(r1     * T[2]   + r0 * T[3]);
3808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              r3     = MULT_NORM(r1     * T[3]   - r0 * T[2]);
3818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              r0     = HALVE(x0[1] + x1[1]);
3838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              r1     = HALVE(x0[0] - x1[0]);
3848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              w0[2]  = r0     + r2;
3868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              w1[0]  = r0     - r2;
3878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              w0[3]  = r1     + r3;
3888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              w1[1]  = r3     - r1;
3898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              T     += 4;
3918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              bit   += 4;
3928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels              w0    += 4;
3938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }while(w0<w1);
3958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
3968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
3978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid mdct_backward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out){
3988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int n=init->n;
3998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int n2=n>>1;
4008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int n4=n>>2;
4018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* rotate */
4038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  DATA_TYPE *iX = in+n2-7;
4058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  DATA_TYPE *oX = out+n2+n4;
4068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  DATA_TYPE *T  = init->trig+n4;
4078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  do{
4098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    oX         -= 4;
4108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    oX[0]       = MULT_NORM(-iX[2] * T[3] - iX[0]  * T[2]);
4118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    oX[1]       = MULT_NORM (iX[0] * T[3] - iX[2]  * T[2]);
4128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    oX[2]       = MULT_NORM(-iX[6] * T[1] - iX[4]  * T[0]);
4138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    oX[3]       = MULT_NORM (iX[4] * T[1] - iX[6]  * T[0]);
4148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    iX         -= 8;
4158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    T          += 4;
4168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }while(iX>=in);
4178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  iX            = in+n2-8;
4198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  oX            = out+n2+n4;
4208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  T             = init->trig+n4;
4218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  do{
4238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    T          -= 4;
4248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    oX[0]       =  MULT_NORM (iX[4] * T[3] + iX[6] * T[2]);
4258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    oX[1]       =  MULT_NORM (iX[4] * T[2] - iX[6] * T[3]);
4268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    oX[2]       =  MULT_NORM (iX[0] * T[1] + iX[2] * T[0]);
4278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    oX[3]       =  MULT_NORM (iX[0] * T[0] - iX[2] * T[1]);
4288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    iX         -= 8;
4298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    oX         += 4;
4308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }while(iX>=in);
4318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  mdct_butterflies(init,out+n2,n2);
4338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  mdct_bitreverse(init,out);
4348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* roatate + window */
4368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  {
4388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    DATA_TYPE *oX1=out+n2+n4;
4398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    DATA_TYPE *oX2=out+n2+n4;
4408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    DATA_TYPE *iX =out;
4418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    T             =init->trig+n2;
4428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    do{
4448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX1-=4;
4458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX1[3]  =  MULT_NORM (iX[0] * T[1] - iX[1] * T[0]);
4478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX2[0]  = -MULT_NORM (iX[0] * T[0] + iX[1] * T[1]);
4488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX1[2]  =  MULT_NORM (iX[2] * T[3] - iX[3] * T[2]);
4508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX2[1]  = -MULT_NORM (iX[2] * T[2] + iX[3] * T[3]);
4518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX1[1]  =  MULT_NORM (iX[4] * T[5] - iX[5] * T[4]);
4538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX2[2]  = -MULT_NORM (iX[4] * T[4] + iX[5] * T[5]);
4548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX1[0]  =  MULT_NORM (iX[6] * T[7] - iX[7] * T[6]);
4568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX2[3]  = -MULT_NORM (iX[6] * T[6] + iX[7] * T[7]);
4578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX2+=4;
4598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      iX    +=   8;
4608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      T     +=   8;
4618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }while(iX<oX1);
4628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    iX=out+n2+n4;
4648e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    oX1=out+n4;
4658e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    oX2=oX1;
4668e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4678e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    do{
4688e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX1-=4;
4698e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      iX-=4;
4708e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4718e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX2[0] = -(oX1[3] = iX[3]);
4728e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX2[1] = -(oX1[2] = iX[2]);
4738e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX2[2] = -(oX1[1] = iX[1]);
4748e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX2[3] = -(oX1[0] = iX[0]);
4758e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4768e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX2+=4;
4778e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }while(oX2<iX);
4788e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4798e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    iX=out+n2+n4;
4808e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    oX1=out+n2+n4;
4818e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    oX2=out+n2;
4828e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    do{
4838e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX1-=4;
4848e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX1[0]= iX[3];
4858e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX1[1]= iX[2];
4868e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX1[2]= iX[1];
4878e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      oX1[3]= iX[0];
4888e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels      iX+=4;
4898e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    }while(oX1>oX2);
4908e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
4918e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
4928e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
4938e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckelsvoid mdct_forward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out){
4948e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int n=init->n;
4958e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int n2=n>>1;
4968e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int n4=n>>2;
4978e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int n8=n>>3;
4988e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  DATA_TYPE *w=alloca(n*sizeof(*w)); /* forward needs working space */
4998e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  DATA_TYPE *w2=w+n2;
5008e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5018e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* rotate */
5028e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5038e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* window + rotate + step 1 */
5048e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5058e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  REG_TYPE r0;
5068e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  REG_TYPE r1;
5078e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  DATA_TYPE *x0=in+n2+n4;
5088e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  DATA_TYPE *x1=x0+1;
5098e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  DATA_TYPE *T=init->trig+n2;
5108e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5118e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  int i=0;
5128e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5138e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<n8;i+=2){
5148e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    x0 -=4;
5158e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    T-=2;
5168e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    r0= x0[2] + x1[0];
5178e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    r1= x0[0] + x1[2];
5188e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    w2[i]=   MULT_NORM(r1*T[1] + r0*T[0]);
5198e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    w2[i+1]= MULT_NORM(r1*T[0] - r0*T[1]);
5208e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    x1 +=4;
5218e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
5228e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5238e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  x1=in+1;
5248e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5258e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(;i<n2-n8;i+=2){
5268e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    T-=2;
5278e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    x0 -=4;
5288e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    r0= x0[2] - x1[0];
5298e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    r1= x0[0] - x1[2];
5308e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    w2[i]=   MULT_NORM(r1*T[1] + r0*T[0]);
5318e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    w2[i+1]= MULT_NORM(r1*T[0] - r0*T[1]);
5328e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    x1 +=4;
5338e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
5348e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5358e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  x0=in+n;
5368e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5378e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(;i<n2;i+=2){
5388e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    T-=2;
5398e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    x0 -=4;
5408e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    r0= -x0[2] - x1[0];
5418e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    r1= -x0[0] - x1[2];
5428e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    w2[i]=   MULT_NORM(r1*T[1] + r0*T[0]);
5438e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    w2[i+1]= MULT_NORM(r1*T[0] - r0*T[1]);
5448e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    x1 +=4;
5458e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
5468e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5478e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5488e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  mdct_butterflies(init,w+n2,n2);
5498e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  mdct_bitreverse(init,w);
5508e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5518e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  /* roatate + window */
5528e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5538e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  T=init->trig+n2;
5548e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  x0=out+n2;
5558e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels
5568e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  for(i=0;i<n4;i++){
5578e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    x0--;
5588e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    out[i] =MULT_NORM((w[0]*T[0]+w[1]*T[1])*init->scale);
5598e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    x0[0]  =MULT_NORM((w[0]*T[1]-w[1]*T[0])*init->scale);
5608e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    w+=2;
5618e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels    T+=2;
5628e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels  }
5638e01cdce135d5d816f92d7bb83f9a930aa1b45aeLucas Eckels}
564