1 /********************************************************************
3 * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5 * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *
6 * PLEASE READ THESE TERMS DISTRIBUTING. *
8 * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000 *
9 * by Monty <monty@xiph.org> and The XIPHOPHORUS Company *
10 * http://www.xiph.org/ *
12 ********************************************************************
14 function: modified discrete cosine transform
15 power of two length transform only [16 <= n ]
16 last mod: $Id: mdct.c,v 1.13 1999/12/30 07:26:44 xiphmont Exp $
18 Algorithm adapted from _The use of multirate filter banks for coding
19 of high quality digital audio_, by T. Sporer, K. Brandenburg and
20 B. Edler, collection of the European Signal Processing Conference
21 (EUSIPCO), Amsterdam, June 1992, Vol.1, pp 211-214
23 Note that the below code won't make much sense without the paper;
24 The presented algorithm was already fairly polished, and the code
25 once followed it closely. The current code both corrects several
26 typos in the paper and goes beyond the presented optimizations
27 (steps 4 through 6 are, for example, entirely eliminated).
29 This module DOES NOT INCLUDE code to generate the window function.
30 Everybody has their own weird favorite including me... I happen to
31 like the properties of y=sin(2PI*sin^2(x)), but others may vehemently
34 ********************************************************************/
43 /* build lookups for trig functions; also pre-figure scaling and
44 some window function algebra. */
46 void mdct_init(mdct_lookup *lookup,int n){
47 int *bitrev=malloc(sizeof(int)*(n/4));
48 double *trig=malloc(sizeof(double)*(n+n/4));
57 int log2n=lookup->log2n=rint(log(n)/log(2));
60 lookup->bitrev=bitrev;
65 AE[i*2]=cos((M_PI/n)*(4*i));
66 AO[i*2]=-sin((M_PI/n)*(4*i));
67 BE[i*2]=cos((M_PI/(2*n))*(2*i+1));
68 BO[i*2]=sin((M_PI/(2*n))*(2*i+1));
71 CE[i*2]=cos((M_PI/n)*(4*i+2));
72 CO[i*2]=-sin((M_PI/n)*(4*i+2));
75 /* bitreverse lookup... */
78 int mask=(1<<(log2n-1))-1,i,j;
83 if((msb>>j)&i)acc|=1<<j;
84 bitrev[i*2]=((~acc)&mask);
90 void mdct_clear(mdct_lookup *l){
92 if(l->trig)free(l->trig);
93 if(l->bitrev)free(l->bitrev);
94 memset(l,0,sizeof(mdct_lookup));
98 static double *_mdct_kernel(double *x, double *w,
99 int n, int n2, int n4, int n8,
108 double *A=init->trig+n2;
113 w2[i]= *xA++ + *xB++;
119 w[i++]= x0 * A[0] + x1 * A[1];
120 w[i]= x1 * A[0] - x0 * A[1];
122 w2[i++]= *xA++ + *xB++;
131 for(i=0;i<init->log2n-3;i++){
135 double *A=init->trig;
138 for(r=0;r<(k0>>2);r++){
146 for(s=0;s<(2<<i);s++){
150 wA =w[++w1] -w[++w2];
153 x[w2] =wA*AEv - wB*AOv;
154 x[w2-1]=wB*AEv + wA*AOv;
170 /* step 4, 5, 6, 7 */
172 double *C=init->trig+n;
173 int *bit=init->bitrev;
180 double wA=w[t1]-w[t2+1];
181 double wB=w[t1-1]+w[t2];
182 double wC=w[t1]+w[t2+1];
183 double wD=w[t1-1]-w[t2];
186 double wBCE=wB* *C++;
188 double wBCO=wB* *C++;
190 *x1++=( wC+wACO+wBCE)*.5;
191 *x2--=(-wD+wBCO-wACE)*.5;
192 *x1++=( wD+wBCO-wACE)*.5;
193 *x2--=( wC-wACO-wBCE)*.5;
199 void mdct_forward(mdct_lookup *init, double *in, double *out, double *window){
201 double *x=alloca(sizeof(double)*(n/2));
202 double *w=alloca(sizeof(double)*(n/2));
209 /* window + rotate + step 1 */
214 double *A=init->trig+n2;
220 tempA= in[in1+2]*window[in1+2] + in[in2]*window[in2];
221 tempB= in[in1]*window[in1] + in[in2+2]*window[in2+2];
223 x[i]= tempB*A[1] + tempA*A[0];
224 x[i+1]= tempB*A[0] - tempA*A[1];
231 tempA= in[in1+2]*window[in1+2] - in[in2]*window[in2];
232 tempB= in[in1]*window[in1] - in[in2+2]*window[in2+2];
234 x[i]= tempB*A[1] + tempA*A[0];
235 x[i+1]= tempB*A[0] - tempA*A[1];
242 tempA= -in[in1+2]*window[in1+2] - in[in2]*window[in2];
243 tempB= -in[in1]*window[in1] - in[in2+2]*window[in2+2];
245 x[i]= tempB*A[1] + tempA*A[0];
246 x[i+1]= tempB*A[0] - tempA*A[1];
250 xx=_mdct_kernel(x,w,n,n2,n4,n8,init);
255 double *B=init->trig+n2;
259 out[i] =(xx[0]*B[0]+xx[1]*B[1])*scale;
260 *(--out2)=(xx[0]*B[1]-xx[1]*B[0])*scale;
268 void mdct_backward(mdct_lookup *init, double *in, double *out, double *window){
270 double *x=alloca(sizeof(double)*(n/2));
271 double *w=alloca(sizeof(double)*(n/2));
278 /* window + rotate + step 1 */
282 double *A=init->trig+n2;
286 *xO++=-*(inO+2)*A[1] - *inO*A[0];
287 *xO++= *inO*A[1] - *(inO+2)*A[0];
295 *xO++=*inO*A[1] + *(inO+2)*A[0];
296 *xO++=*inO*A[0] - *(inO+2)*A[1];
302 xx=_mdct_kernel(x,w,n,n2,n4,n8,init);
307 double *B=init->trig+n2;
309 int o3=n4+n2,o4=o3-1;
312 double temp1= (*xx * B[1] - *(xx+1) * B[0]);
313 double temp2=-(*xx * B[0] + *(xx+1) * B[1]);
315 out[o1]=-temp1*window[o1];
316 out[o2]= temp1*window[o2];
317 out[o3]= temp2*window[o3];
318 out[o4]= temp2*window[o4];