按频率对波形进行编码的代码

3
我希望能够展示彩色音频波形,每个部分根据当地的频率内容进行编码。基本上就像Serato/Traktor或任何其他DJ软件所做的那样,您可以查看声音并告诉哪些频率存在。它看起来像这样:enter image description here因此,本质上,我将执行FFT以获取我指定的任何bin宽度的频率,但是有人可以为我提供一些有用于实际绘制的代码吗?(最好使用c语言)

Audacity是一款流行的免费/开源音频编辑器,适用于多个平台,包括可以从http://web.audacityteam.org/download/source下载的源代码 - 我相信如果您在其中寻找,您会找到绘制波形的代码。(如果您使用此代码,请务必根据其开源许可证包括所有开源归属。) - Ron Kuper
@RonKuper 1) 不,它没有。它有一些主题来将整个波形绘制为某种颜色。这不是我要问的。2)你是个缺乏洞察力回答就给这个问题投反对票的人。而且,我已经花了很长时间查阅关于Serato/Traktor/Comparisonics的音频技术论文。 - user656028
1
我没有给你的问题投反对票,事实上我刚刚为你点了赞,让它回到了0。 - Ron Kuper
1个回答

4

这次我们试着给出一个真正的答案。 :-)

问题太复杂了,在这个空间里无法提供完整的解决方案,但是我将使用伪代码,并假设您有一些库可以对样本块进行窗口化并计算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);
}

这将提供给你一个RGB数组,你可以在波形显示中缩放它来进行放大和缩小。当你缩放时,你可能想要对相邻帧的RGB值进行平均,以便给你一个总体视图。
我希望这能帮到你。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接