我希望能够展示彩色音频波形,每个部分根据当地的频率内容进行编码。基本上就像Serato/Traktor或任何其他DJ软件所做的那样,您可以查看声音并告诉哪些频率存在。它看起来像这样:
因此,本质上,我将执行FFT以获取我指定的任何bin宽度的频率,但是有人可以为我提供一些有用于实际绘制的代码吗?(最好使用c语言)
![enter image description here](https://istack.dev59.com/sUqDd.webp)
这次我们试着给出一个真正的答案。 :-)
问题太复杂了,在这个空间里无法提供完整的解决方案,但是我将使用伪代码,并假设您有一些库可以对样本块进行窗口化并计算FFT。
这类似于构建波形显示。当您构建波形显示时,您确定在当前缩放级别下有多少样本“适合”单个水平像素,它们在给定X滚动位置处开始,计算该段的最小和最大样本值,并为该波形像素提供最小/最大Y位置。(实际上这有点简化了,我曾经编写过波形渲染代码,但这是一个很好的近似值。)
要按频率为波形着色,您需要使用短时间FFT对波形数据进行预处理,使用较小的bin来确定每个bin的主要频率,然后将其映射到从红色到紫色的光谱上的颜色。
假设您的音频样本存储在一个名为samples
的数组中,以下是伪代码。
// sample rate
float fS = 44100;
// size of frame for analysis, you may want to play with this
float frameMsec = 10;
// samples in a frame
int frameSamples = (int)(fS / (frameMsec * 1000));
// how much overlap each frame, you may want to play with this one too
int overlapSamples = (frameSamples / 2);
// number of samples in the sound file
int numSamples = ...;
// input array of samples
float inSamples[] = ...;
// color to use for each frame
RGB outColors[] = new float[(numSamples / frameOverlap) + 1];
// scratch buffers
float tmpWindow[frameSamples];
float tmpFFT[frameSamples];
// helper function to apply a windowing function to a frame of samples
void calcWindow(float* dst, const float* src, int size);
// helper function to compute FFT
void fft(float* dst, const float* src, int size);
// find the index of array element with the highest absolute value
// probably want to take some kind of moving average of buf[i]^2
// and return the maximum found
int maxFreqIndex(const float* buf, int size);
// map a frequency to a color, red = lower freq -> violet = high freq
RGB freqToColor(int i);
for (int i = 0, outptr = 0; i < numSamples; i += frameOverlap, outptr++)
{
// window another frame for FFT
calcWindow(tmpWindow, &inSamples[i], frameSamples);
// compute the FFT on the next frame
fft(tmpFFT, tmpWindow, frameSamples);
// which frequency is the highest?
int freqIndex = maxFreqIndex(tmpFFT, frameSamples);
// map to color
outColor[outptr] = freqToColor(freqIndex);
}