按频率划分彩色波形的代码

时间:2015-05-21 07:13:44

标签: audio drawing

我希望用本地频率内容显示每个部分的颜色编码的音频波形。基本上就是Serato / Traktor或任何其他DJ软件所做的事情,你可以看到声音并告诉它们有什么频率。它看起来像这样:

enter image description here

基本上,我会做一个FFT来获取我指定的任何bin宽度的频率,但是有人能引用我一些在实际绘制它时有用的代码(最好是c)吗?

1 个答案:

答案 0 :(得分:2)

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

问题太复杂了,无法提供此空间中所有代码的完整解决方案,但我会使用伪代码并假设您有一些可以窗口化样本块并计算FFT的库。

它类似于构建波形显示。在构建波形显示时,您可以确定适合的样本数量和#34;在当前缩放级别的单个水平像素中,它们开始给定您的X滚动位置,计算该段的最小和最大样本值,并为您提供该波形像素的最小/最大Y位置。 (这实际上有点简化,我在当天写回了波形渲染代码,但这是一个很好的近似值。)

要使用频率为波浪着色,您需要使用带有小间隔的短时间FFT对波形数据进行预处理,并为每个分区确定主要频率是什么,然后将其映射到从红色到紫色的光谱上的颜色

让我们在一个名为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值,以便为您提供整体视图。

我希望这会有所帮助。