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);
}
No comments:
Post a Comment