1 /********************************************************************
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5 * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH *
6 * THIS SOURCE. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * THE OggVorbis 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: normalized modified discrete cosine transform
15 power of two length transform only [64 <= n ]
16 last mod: $Id: mdct.c,v 1.22 2000/12/17 08:50:27 xiphmont Exp $
18 Original algorithm adapted long ago from _The use of multirate filter
19 banks for coding of high quality digital audio_, by T. Sporer,
20 K. Brandenburg and B. Edler, collection of the European Signal
21 Processing Conference (EUSIPCO), Amsterdam, June 1992, Vol.1, pp
24 The below code implements an algorithm that no longer looks much like
25 that presented in the paper, but the basic structure remains if you
26 dig deep enough to see it.
28 This module DOES NOT INCLUDE code to generate/apply the window
29 function. Everybody has their own weird favorite including me... I
30 happen to like the properties of y=sin(2PI*sin^2(x)), but others may
33 ********************************************************************/
35 /* this can also be run as an integer transform by uncommenting a
36 define in mdct.h; the integerization is a first pass and although
37 it's likely stable for Vorbis, the dynamic range is constrained and
38 roundoff isn't done (so it's noisy). Consider it functional, but
39 only a starting point. There's no point on a machine with an FPU */
45 #include "vorbis/codec.h"
49 /* build lookups for trig functions; also pre-figure scaling and
50 some window function algebra. */
52 void mdct_init(mdct_lookup *lookup,int n){
53 int *bitrev=_ogg_malloc(sizeof(int)*(n/4));
54 DATA_TYPE *T=_ogg_malloc(sizeof(DATA_TYPE)*(n+n/4));
58 int log2n=lookup->log2n=rint(log(n)/log(2));
61 lookup->bitrev=bitrev;
66 T[i*2]=FLOAT_CONV(cos((M_PI/n)*(4*i)));
67 T[i*2+1]=FLOAT_CONV(-sin((M_PI/n)*(4*i)));
68 T[n2+i*2]=FLOAT_CONV(cos((M_PI/(2*n))*(2*i+1)));
69 T[n2+i*2+1]=FLOAT_CONV(sin((M_PI/(2*n))*(2*i+1)));
72 T[n+i*2]=FLOAT_CONV(cos((M_PI/n)*(4*i+2))*.5);
73 T[n+i*2+1]=FLOAT_CONV(-sin((M_PI/n)*(4*i+2))*.5);
76 /* bitreverse lookup... */
79 int mask=(1<<(log2n-1))-1,i,j;
84 if((msb>>j)&i)acc|=1<<j;
85 bitrev[i*2]=((~acc)&mask)-1;
90 lookup->scale=FLOAT_CONV(4./n);
93 /* 8 point butterfly (in place, 4 register) */
94 STIN void mdct_butterfly_8(DATA_TYPE *x){
95 REG_TYPE r0 = x[6] + x[2];
96 REG_TYPE r1 = x[6] - x[2];
97 REG_TYPE r2 = x[4] + x[0];
98 REG_TYPE r3 = x[4] - x[0];
122 /* 16 point butterfly (in place, 4 register) */
123 STIN void mdct_butterfly_16(DATA_TYPE *x){
124 REG_TYPE r0 = x[1] - x[9];
125 REG_TYPE r1 = x[0] - x[8];
129 x[0] = MULT_NORM((r0 + r1) * cPI2_8);
130 x[1] = MULT_NORM((r0 - r1) * cPI2_8);
143 x[4] = MULT_NORM((r0 - r1) * cPI2_8);
144 x[5] = MULT_NORM((r0 + r1) * cPI2_8);
154 mdct_butterfly_8(x+8);
157 /* 32 point butterfly (in place, 4 register) */
158 STIN void mdct_butterfly_32(DATA_TYPE *x){
159 REG_TYPE r0 = x[30] - x[14];
160 REG_TYPE r1 = x[31] - x[15];
171 x[12] = MULT_NORM( r0 * cPI1_8 - r1 * cPI3_8 );
172 x[13] = MULT_NORM( r0 * cPI3_8 + r1 * cPI1_8 );
178 x[10] = MULT_NORM(( r0 - r1 ) * cPI2_8);
179 x[11] = MULT_NORM(( r0 + r1 ) * cPI2_8);
185 x[8] = MULT_NORM( r0 * cPI3_8 - r1 * cPI1_8 );
186 x[9] = MULT_NORM( r1 * cPI3_8 + r0 * cPI1_8 );
199 x[4] = MULT_NORM( r1 * cPI1_8 + r0 * cPI3_8 );
200 x[5] = MULT_NORM( r1 * cPI3_8 - r0 * cPI1_8 );
206 x[2] = MULT_NORM(( r1 + r0 ) * cPI2_8);
207 x[3] = MULT_NORM(( r1 - r0 ) * cPI2_8);
213 x[0] = MULT_NORM( r1 * cPI3_8 + r0 * cPI1_8 );
214 x[1] = MULT_NORM( r1 * cPI1_8 - r0 * cPI3_8 );
216 mdct_butterfly_16(x);
217 mdct_butterfly_16(x+16);
221 /* N point first stage butterfly (in place, 2 register) */
222 STIN void mdct_butterfly_first(DATA_TYPE *T,
226 DATA_TYPE *x1 = x + points - 8;
227 DATA_TYPE *x2 = x + (points>>1) - 8;
237 x2[6] = MULT_NORM(r1 * T[1] + r0 * T[0]);
238 x2[7] = MULT_NORM(r1 * T[0] - r0 * T[1]);
244 x2[4] = MULT_NORM(r1 * T[5] + r0 * T[4]);
245 x2[5] = MULT_NORM(r1 * T[4] - r0 * T[5]);
251 x2[2] = MULT_NORM(r1 * T[9] + r0 * T[8]);
252 x2[3] = MULT_NORM(r1 * T[8] - r0 * T[9]);
258 x2[0] = MULT_NORM(r1 * T[13] + r0 * T[12]);
259 x2[1] = MULT_NORM(r1 * T[12] - r0 * T[13]);
268 /* N/stage point generic N stage butterfly (in place, 2 register) */
269 STIN void mdct_butterfly_generic(DATA_TYPE *T,
274 DATA_TYPE *x1 = x + points - 8;
275 DATA_TYPE *x2 = x + (points>>1) - 8;
285 x2[6] = MULT_NORM(r1 * T[1] + r0 * T[0]);
286 x2[7] = MULT_NORM(r1 * T[0] - r0 * T[1]);
294 x2[4] = MULT_NORM(r1 * T[1] + r0 * T[0]);
295 x2[5] = MULT_NORM(r1 * T[0] - r0 * T[1]);
303 x2[2] = MULT_NORM(r1 * T[1] + r0 * T[0]);
304 x2[3] = MULT_NORM(r1 * T[0] - r0 * T[1]);
312 x2[0] = MULT_NORM(r1 * T[1] + r0 * T[0]);
313 x2[1] = MULT_NORM(r1 * T[0] - r0 * T[1]);
322 STIN void mdct_butterflies(mdct_lookup *init,
326 DATA_TYPE *T=init->trig;
327 int stages=init->log2n-5;
331 mdct_butterfly_first(T,x,points);
334 for(i=1;--stages>0;i++){
335 for(j=0;j<(1<<i);j++)
336 mdct_butterfly_generic(T,x+(points>>i)*j,points>>i,4<<i);
339 for(j=0;j<points;j+=32)
340 mdct_butterfly_32(x+j);
344 void mdct_clear(mdct_lookup *l){
346 if(l->trig)_ogg_free(l->trig);
347 if(l->bitrev)_ogg_free(l->bitrev);
348 memset(l,0,sizeof(mdct_lookup));
352 STIN void mdct_bitreverse(mdct_lookup *init,
355 int *bit = init->bitrev;
357 DATA_TYPE *w1 = x = w0+(n>>1);
358 DATA_TYPE *T = init->trig+n;
361 DATA_TYPE *x0 = x+bit[0];
362 DATA_TYPE *x1 = x+bit[1];
364 REG_TYPE r0 = x0[1] - x1[1];
365 REG_TYPE r1 = x0[0] + x1[0];
366 REG_TYPE r2 = MULT_NORM(r1 * T[0] + r0 * T[1]);
367 REG_TYPE r3 = MULT_NORM(r1 * T[1] - r0 * T[0]);
371 r0 = HALVE(x0[1] + x1[1]);
372 r1 = HALVE(x0[0] - x1[0]);
384 r2 = MULT_NORM(r1 * T[2] + r0 * T[3]);
385 r3 = MULT_NORM(r1 * T[3] - r0 * T[2]);
387 r0 = HALVE(x0[1] + x1[1]);
388 r1 = HALVE(x0[0] - x1[0]);
402 void mdct_backward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out){
409 DATA_TYPE *iX = in+n2-7;
410 DATA_TYPE *oX = out+n2+n4;
411 DATA_TYPE *T = init->trig+n4;
415 oX[0] = MULT_NORM(-iX[2] * T[3] - iX[0] * T[2]);
416 oX[1] = MULT_NORM (iX[0] * T[3] - iX[2] * T[2]);
417 oX[2] = MULT_NORM(-iX[6] * T[1] - iX[4] * T[0]);
418 oX[3] = MULT_NORM (iX[4] * T[1] - iX[6] * T[0]);
429 oX[0] = MULT_NORM (iX[4] * T[3] + iX[6] * T[2]);
430 oX[1] = MULT_NORM (iX[4] * T[2] - iX[6] * T[3]);
431 oX[2] = MULT_NORM (iX[0] * T[1] + iX[2] * T[0]);
432 oX[3] = MULT_NORM (iX[0] * T[0] - iX[2] * T[1]);
437 mdct_butterflies(init,out+n2,n2);
438 mdct_bitreverse(init,out);
440 /* roatate + window */
443 DATA_TYPE *oX1=out+n2+n4;
444 DATA_TYPE *oX2=out+n2+n4;
451 oX1[3] = MULT_NORM (iX[0] * T[1] - iX[1] * T[0]);
452 oX2[0] = -MULT_NORM (iX[0] * T[0] + iX[1] * T[1]);
454 oX1[2] = MULT_NORM (iX[2] * T[3] - iX[3] * T[2]);
455 oX2[1] = -MULT_NORM (iX[2] * T[2] + iX[3] * T[3]);
457 oX1[1] = MULT_NORM (iX[4] * T[5] - iX[5] * T[4]);
458 oX2[2] = -MULT_NORM (iX[4] * T[4] + iX[5] * T[5]);
460 oX1[0] = MULT_NORM (iX[6] * T[7] - iX[7] * T[6]);
461 oX2[3] = -MULT_NORM (iX[6] * T[6] + iX[7] * T[7]);
476 oX2[0] = -(oX1[3] = iX[3]);
477 oX2[1] = -(oX1[2] = iX[2]);
478 oX2[2] = -(oX1[1] = iX[1]);
479 oX2[3] = -(oX1[0] = iX[0]);
498 void mdct_forward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out){
503 DATA_TYPE *w=alloca(n*sizeof(DATA_TYPE)); /* forward needs working space */
508 /* window + rotate + step 1 */
512 DATA_TYPE *x0=in+n2+n4;
514 DATA_TYPE *T=init->trig+n2;
523 w2[i]= MULT_NORM(r1*T[1] + r0*T[0]);
524 w2[i+1]= MULT_NORM(r1*T[0] - r0*T[1]);
535 w2[i]= MULT_NORM(r1*T[1] + r0*T[0]);
536 w2[i+1]= MULT_NORM(r1*T[0] - r0*T[1]);
547 w2[i]= MULT_NORM(r1*T[1] + r0*T[0]);
548 w2[i+1]= MULT_NORM(r1*T[0] - r0*T[1]);
553 mdct_butterflies(init,w+n2,n2);
554 mdct_bitreverse(init,w);
556 /* roatate + window */
563 out[i] =MULT_NORM((w[0]*T[0]+w[1]*T[1])*init->scale);
564 x0[0] =MULT_NORM((w[0]*T[1]-w[1]*T[0])*init->scale);