如何以对数方式绘制数据

How to plot data logarithmically

我已经对音频信号进行了 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 个分贝点。忽略绘图点的 y 分量。

我的数据没有正确缩放,因为我的第一个 bin (~43 hz) 是 log10(43)= 1.633,图表的末尾是 log10(22050) = 4.3,所以我的 space第一个垃圾箱占据了 window 的三分之一以上。重要的是我不只是把我的第一个垃圾桶放在 window 的最左边,最左边必须是 0。

有人知道将数据缩放到如图所示的整齐对数 bin 中的正确方法吗?他们有三个整齐的容器,代表 10 的数量级,它很方便地在 22050 处结束。

供参考,这是我现在拥有的,您可以看到光谱左侧的长直线。该行的第一个扭结点是 43 赫兹,即我的第一个垃圾箱。我还没有建立网格,但是当我弄清楚缩放比例时就会出现。

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的网格线