如何以对数方式绘制数据

时间:2015-06-30 15:23:05

标签: objective-c audio graphics fft

我已经对音频信号进行了FFT,并希望以对数刻度绘制结果

http://abletonuniverse.altervista.org/wp-content/uploads/2013/04/Spectrum.jpg

但出于某种原因,我无法弄清楚如何缩放数据以适应该对数曲线(从0开始,以奈奎斯特频率结束,即采样/块大小)。

目前这就是我所拥有的

CGContextMoveToPoint(context, 0, rect.size.height);

// Skip the DC Offset (index 0)
for (int i = 1; i < _bins; i++) {
    // Get frequency from bin
    float binFreq = i * 44100.0 / (_bins * 2);

    // Map to rect coordinate space
    float x = log10f(binFreq) * rect.size.width / log10f(44100.0 / 2);
    float y = _freqArray[i] * rect.size.height / -130.0;

    // Draw line
    CGContextAddLineToPoint(context, x, y);
}

我的数据在_freqArray中以0到-130之间的512点dB进行输入。忽略绘制点的y分量。

我的数据没有正确缩放,因为我的第一个bin(~43 hz)是log10(43)= 1.633而且图表的结尾是log10(22050)= 4.3,所以我的第一个bin之间的空间占用了窗口的三分之一。重要的是,我不要把我的第一个垃圾箱放在窗口的最左边,最左边必须是0。

有没有人知道将数据扩展到整齐的对数区间的正确方法,例如图片中?他们有三个整齐的箱子,代表数量级为10,它很方便地在22050结束。

作为参考,这就是我现在所拥有的,您可以看到光谱左侧的长直线。该行的第一个扭结是43赫兹,即我的第一个箱子。我还没有把网格放好,但是当我弄清楚缩放时会出现这种情况。enter image description here

1 个答案:

答案 0 :(得分:2)

0Hz频率无法在对数刻度频率轴上显示。您引用的图表上显示的左侧对应于10Hz。您可以映射频率坐标,使得此选定的最小频率(例如minFrequencyToDisplay=10Hz)以x=0的值绘制,最后一个bin以值x=rect.size.width-1绘制,如下所示:

// Map to rect coordinate space
float logMinFreq = log10f(minFrequencyToDisplay);
float x = (log10f(binFreq)-logMinFreq ) * (rect.size.width-1) /
          (log10f(44100.0 / 2)-logMinFreq );

可以使用相同的公式获得100Hz,1kHz和10kHz的网格线。