hommage-0.0.6: Sound/Hommage/dft.c
#include <stdio.h>
// #include <io.h>
#include <fcntl.h>
#include <stdlib.h>
#include <math.h>
double sinus [1024];
double cosin [1024];
double kurve [1024];
int cinit ()
{
int i;
double f = 3.1415926 / 512.0;
double k = 1.0 / 512.0;
for (i=0; i<1024; i++)
{ double x = f * (double) i;
sinus [i] = sin (x);
cosin [i] = cos (x);
}
/*
for (i=0; i<512; i++)
{ double x = k * (double) i;
kurve [i] = x;
kurve [i+512] = 1.0-x;
}
*/
for (i=0; i<1024; i++)
{ kurve [i] = 0.5 - (cosin [i] * 0.5);
}
return 0;
}
double getsinus (int x)
{ return sinus [x & 1023];
}
double getcosin (int x)
{ return cosin [x & 1023];
}
void xcanalyse (double * wv, double * cf)
{ int k, x;
for (k=1; k<512; k++)
{ int kc = k << 1;
int ks = kc - 1;
cf [kc] = 0.0;
cf [ks] = 0.0;
for (x=0; x<1024; x++)
{ int i = (x * k) & 1023;
cf [kc] += cosin [i] * wv [x];
cf [ks] += sinus [i] * wv [x];
}
cf [kc] /= 512.0;
cf [ks] /= 512.0;
}
cf [1023] = 0.0;
cf [0] = 0.0;
for (x=0; x<1024; x++)
{ if (x % 2 == 0)
cf [1023] += wv [x];
else
cf [1023] -= wv [x];
cf [0] += wv [x];
}
cf [0] /= 512.0;
cf [1023] /= 512.0;
}
void xcsynthese (double * cf, double * wv)
{ int x,k;
double d;
for (x=0; x<1024; x++)
{ d = cf [0] * 0.5;
if (x % 2 == 0)
d += cf [1023];
else
d -= cf [1023];
for (k=1; k<512; k++)
{ int kc = k << 1;
int ks = kc - 1;
int i = (x * k) & 1023;
d += cosin [i] * cf [kc];
d += sinus [i] * cf [ks];
}
wv [x] = d; // * st->kurve [x];
}
}
void ckurve (double * arr)
{ int i;
for (i=0; i<1024; i++)
arr [i] *= kurve [i];
}
// Now with FFT ...
void canalyse (double * wv, double * cf)
{ int group_length;
int i,j,d,nr_of_groups,group;
int a_ix, b_ix, w_ix;
int a_r_ix, a_i_ix, b_r_ix, b_i_ix;
double a_r, a_i, b_r, b_i, w_r, w_i, wb_r, wb_i;
group_length = 1;
for (i=0; i<512; i++)
{ j = 0; //bitreverse (i);
int ii = i;
for (d=0;d<9;d++)
{ j<<=1;
if (ii % 2)
{ j++;
}
ii >>=1;
}
cf [i*2] = wv [j*2];
cf [i*2+1] = wv [j*2+1];
}
for (nr_of_groups=512; nr_of_groups>1; nr_of_groups>>=1)
{
for (group=0; group<nr_of_groups; group+=2)
{
for (i=0; i<group_length; i++) // zipWith3 butterfly ws xs ys
{ a_ix = group * group_length + i;
b_ix = a_ix + group_length;
w_ix = (i * 512 / group_length);
//butterfly (w_ix, a_ix, b_ix);
w_r = cosin [w_ix];
w_i = sinus [w_ix];
a_r_ix = a_ix * 2;
a_i_ix = a_r_ix + 1;
b_r_ix = b_ix * 2;
b_i_ix = b_r_ix + 1;
a_r = cf [a_r_ix];
a_i = cf [a_i_ix];
b_r = cf [b_r_ix];
b_i = cf [b_i_ix];
wb_r = (w_r * b_r) + (w_i * b_i);
wb_i = (w_r * b_i) - (w_i * b_r);
cf [a_r_ix] = a_r + wb_r;
cf [a_i_ix] = a_i + wb_i;
cf [b_r_ix] = a_r - wb_r;
cf [b_i_ix] = a_i - wb_i;
}
}
group_length *= 2;
}
}
void csynthese (double * wv, double * cf)
{ int group_length;
int i,j,d,nr_of_groups,group;
int a_ix, b_ix, w_ix;
int a_r_ix, a_i_ix, b_r_ix, b_i_ix;
double a_r, a_i, b_r, b_i, w_r, w_i, wb_r, wb_i;
group_length = 1;
for (i=0; i<512; i++)
{ j = 0; //bitreverse (i);
int ii = i;
for (d=0;d<9;d++)
{ j<<=1;
if (ii % 2)
{ j++;
}
ii >>=1;
}
cf [i*2] = wv [j*2];
cf [i*2+1] = wv [j*2+1];
}
for (nr_of_groups=512; nr_of_groups>1; nr_of_groups>>=1)
{
for (group=0; group<nr_of_groups; group+=2)
{
for (i=0; i<group_length; i++) // zipWith3 butterfly ws xs ys
{ a_ix = group * group_length + i;
b_ix = a_ix + group_length;
w_ix = (i * 512 / group_length);
//butterfly (w_ix, a_ix, b_ix);
w_r = cosin [w_ix];
w_i = sinus [w_ix];
a_r_ix = a_ix * 2;
a_i_ix = a_r_ix + 1;
b_r_ix = b_ix * 2;
b_i_ix = b_r_ix + 1;
a_r = cf [a_r_ix];
a_i = cf [a_i_ix];
b_r = cf [b_r_ix];
b_i = cf [b_i_ix];
wb_r = (w_r * b_r) - (w_i * b_i);
wb_i = (w_r * b_i) + (w_i * b_r);
cf [a_r_ix] = (a_r + wb_r) * 0.5;
cf [a_i_ix] = (a_i + wb_i) * 0.5;
cf [b_r_ix] = (a_r - wb_r) * 0.5;
cf [b_i_ix] = (a_i - wb_i) * 0.5;
}
}
group_length *= 2;
}
}
// a + w * b
// (ar,ai) +- (wr,wi) * (br,bi)
// (wr*br - wi*bi, wr*bi+br*wi)
// (ar+wr*br-wi*bi, ai+wr*bi+br*wi)
// (ar-wr*br+wi*bi, ai-wr*bi+br*wi)
// 1024 i = cosin [i]
// 512 i = cosin [i*2] [i * 1024 / grouplength]
// 2 i = i * 512