/******************************************************************** * * * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. * * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY * * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. * * PLEASE READ THESE TERMS DISTRIBUTING. * * * * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000 * * by Monty and The XIPHOPHORUS Company * * http://www.xiph.org/ * * * ******************************************************************** function: normalized modified discrete cosine transform power of two length transform only [16 <= n ] last mod: $Id: mdct.c,v 1.2 2001/08/01 16:26:54 jmvalin Exp $ Algorithm adapted from _The use of multirate filter banks for coding of high quality digital audio_, by T. Sporer, K. Brandenburg and B. Edler, collection of the European Signal Processing Conference (EUSIPCO), Amsterdam, June 1992, Vol.1, pp 211-214 Note that the below code won't make much sense without the paper; The presented algorithm was already fairly polished, and the code once followed it closely. The current code both corrects several typos in the paper and goes beyond the presented optimizations (steps 4 through 6 are, for example, entirely eliminated). This module DOES NOT INCLUDE code to generate the window function. Everybody has their own weird favorite including me... I happen to like the properties of y=sin(2PI*sin^2(x)), but others may vehemently disagree. ********************************************************************/ #include #include #include #include #include "mdct.h" //#include "misc.h" //@implements MDCT /* build lookups for trig functions; also pre-figure scaling and some window function algebra. */ void mdct_init(mdct_lookup *lookup,int n){ int *bitrev=malloc(sizeof(int)*(n/4)); double *trig=malloc(sizeof(double)*(n+n/4)); double *AE=trig; double *AO=trig+1; double *BE=AE+n/2; double *BO=BE+1; double *CE=BE+n/2; double *CO=CE+1; int i; int log2n=lookup->log2n=rint(log(n)/log(2)); lookup->n=n; lookup->trig=trig; lookup->bitrev=bitrev; /* trig lookups... */ for(i=0;i>j;j++) if((msb>>j)&i)acc|=1<trig)free(l->trig); if(l->bitrev)free(l->bitrev); memset(l,0,sizeof(mdct_lookup)); } } static double *_mdct_kernel(double *x, double *w, int n, int n2, int n4, int n8, mdct_lookup *init){ int i; /* step 2 */ { double *xA=x+n4; double *xB=x; double *w2=w+n4; double *A=init->trig+n2; for(i=0;ilog2n-3;i++){ int k0=n>>(i+2); int k1=1<<(i+3); int wbase=n2-2; double *A=init->trig; double *temp; for(r=0;r<(k0>>2);r++){ int w1=wbase; int w2=w1-(k0>>1); double AEv= A[0],wA; double AOv= A[1],wB; wbase-=2; k0++; for(s=0;s<(2<trig+n; int *bit=init->bitrev; double *x1=x; double *x2=x+n2-1; for(i=0;in; double *x=alloca(sizeof(double)*(n/2)); double *w=alloca(sizeof(double)*(n/2)); double *xx; int n2=n>>1; int n4=n>>2; int n8=n>>3; int i; /* window + rotate + step 1 */ { double tempA,tempB; int in1=n2+n4-4; int in2=in1+5; double *A=init->trig+n2; i=0; for(i=0;itrig+n2; double *out2=out+n2; double scale=4./n; for(i=0;in; double *x=alloca(sizeof(double)*(n/2)); double *w=alloca(sizeof(double)*(n/2)); double *xx; int n2=n>>1; int n4=n>>2; int n8=n>>3; int i; /* rotate + step 1 */ { double *inO=in+1; double *xO= x; double *A=init->trig+n2; for(i=0;itrig+n2; int o1=n4,o2=o1-1; int o3=n4+n2,o4=o3-1; for(i=0;i