Discrete Fourier Transformation (DFT) based Spectrum Tracer

DFT can be used to convert audio samples from time domain to frequency domain. That is the dancing spectrum in graphic equalizers. This piece of code (C++ with MFC) traces the spectrum of a wave file.

const double PI = 3.14159265;
const int N = 1024; // DFT point count
void TraceSpectrum(CDC* pDC)
{
char* pzFile ="D:\\in.wav";
HMMIO h = mmioOpen((LPTSTR)pzFile, NULL, MMIO_READ | MMIO_ALLOCBUF | MMIO_DENYWRITE); for (int i = 0; i < 50000; ++i)
{
double realInput[N] = { 0 }; for (int j = 0; j < N; ++j)
{
SHORT iLeft;
SHORT iRight;
mmioRead(h, (HPSTR)&iLeft, 2); // 16 bit samples
mmioRead(h, (HPSTR)&iRight, 2); // 16 bit samples realInput[j] = iLeft / 1000.0;
}
TraceDFT(realInput, pDC);
Sleep(10);
} mmioClose(h, 0);
}

void TraceDFT(double* realInput, CDC* pDC) {
double realOutput[N] = { 0 };
double imagOutput[N] = { 0 }; for (int k = 0; k < N / 2; ++k) // Output is symmetric, hence N/2
{
for (int n = 0; n < N; ++n)
{
// Theory: F(k) = sigma(T(n) * (cos(x) - j*sin(x))) Where x = 2PIkn/N double x = 2 * PI * k * n / N;
double re = realInput[n] * cos(x);
double im = realInput[n] * -sin(x);
realOutput[k] += re;
imagOutput[k] += im;
}
}

// To Decibels
double spectrum[N / 2];
for (int i = 0; i < N / 2; ++i)
{
double d = sqrt(realOutput[i] * realOutput[i] + imagOutput[i] * imagOutput[i]);
d = d < 1 ? 0 : 20 * log(d);
spectrum[i] = min(d, 200);
}
// Draw the graph
pDC->FillSolidRect(0, 0, 1000, 500, 0xffffff);
for (int i = 0; i < N / 2; ++i)
pDC->FillSolidRect(20 + i, 200 - spectrum[i], 1, spectrum[i], 0x0);
}

Output

Image

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s