2015-04-01 68 views
0

我正在写一个脚本来处理在Python中的波形文件,并显示一个频谱分析仪,只是为了良好的音频文件的可视化。在阅读了一些文档和论坛后,我认为我需要使用rfft。频谱分析仪波形文件与numpy.rfft

我正在处理2048个值的样本,在rfft的输出中创建1024个波段。事情是,为了我的需要,我需要将乐队的数量大幅减少到12个乐队(1个八度)。由于我正在处理音频文件并且乐队数量有限,因此我想知道是否有一种巧妙的方法来组合频率,以便90%的歌曲在左侧低音节拍和高调的声音/留言/正确的说明。

有了这个初步的代码,我有更多的乐队,我需要的,但也大多数峰值集中在低频率与大多数歌曲,除了20至20K的测试范围。有了这个范围,我也意识到,音高越高,幅度越低。

def fft(self, sample_range): 
    # sample_range is a sample of 2048 ints read from the self.file wave file 
    fft_data = abs(numpy.fft.rfft(sample_range)) # real fft gives samplewidth/2 bands 
    fft_freq = numpy.fft.rfftfreq(len(sample_range)) 
    freq_hz = [abs(fft_freq[i])*self.file.getframerate() for i, fft in enumerate(fft_data)] 

    print len(zip(freq_hz, fft_data)), len(freq_hz), len(fft_data), zip(freq_hz, fft_data) 

下面是RAMPE的第一样品(〜20Hz的)打印输出:

1025 1025 1025 [(0.0, 1850501.0), (21.533203125, 2779524.1730200453), (43.06640625, 15469093.29481476), ... (22028.466796875, 3538.1225240980043), (22050.0, 3553.0)] 

所以我的问题是:

  • 我做的东西,我不该在上面的代码中? =)

  • 大多数音乐播放器中的频谱分析仪通常代表什么单位,范围是多少?我应该将幅度转换为dB吗?

  • 有没有一种简单的方法将频带数减少到12个?我猜这个带宽对于音高来说是指数级的吗?我会说我需要手动实现这个指数和。

编辑:我使用参考数比例,我生成用于与带任意数量现在求和FFT频率:

In [22]: num_bands = 10 
In [23]: [44100*2**(b-num_bands) for b in range(num_bands)] 
Out[23]: [43.06640625, 86.1328125, 172.265625, 344.53125, 689.0625, 1378.125, 2756.25, 5512.5, 11025.0, 22050.0] 

In [24]: num_bands = 12 
In [25]: [44100*2**(b-num_bands) for b in range(num_bands)] 
Out[25]: [10.7666015625, 21.533203125, 43.06640625, 86.1328125, 172.265625, 344.53125, 689.0625, 1378.125, 2756.25, 5512.5, 11025.0, 22050.0] 

我使用这些作为各频带中的最大频率。它一直运行到num_bands = 10的最大值。从11岁起,我开始在可听范围内获得非常低的频率。任何想法缩小范围比这更好?无论如何,第一频段的最大频率应至少为40 Hz。

回答

1

是的,频谱显示通常转换为dB(或其他对数标度)。

减少频带数量的最简单方法就是将每个八度音程(或者每半音阶或12个八度音程等)中的相邻FFT结果分组加在一起,其中每个音阶表示的最高频率和最低频率之间的比例大致相等波段或一组FFT结果仓。使比例大小的组足够大或小,以便最终获得所需的总带数。

+0

“上下”是指正面还是负面?如果我理解的很好,*真实* fft已经为我做了。 – myoan 2015-04-01 20:09:42

+0

改进的答案是说每个频段或一组FFT结果箱的最高和最低频率。每倍频程,顶部bin的索引大约是每个组中底部bin的两倍(可能是-1)。 – hotpaw2 2015-04-02 00:46:08

+0

我明白了,这就是我实际做的。如果你看看我上面编辑的问题,我会生成一个列表,它是每个组的最高频率。因此,使用'[43.06640625,86.1328125,172.265625,...]'列表'我将创建'[(0Hz,43Hz),(43Hz,86Hz),(86Hz,172Hz),(172,...)]'频带''。但是我不能设法生成这个列表,以便它适用于任何给定的n个频段。我增加得越多,就越能听到非常低的频率(例如,频带11到22Hz以下)。所以我有两个新问题:我应该如何处理<20Hz频率?以及如何生成清单来消除它们? – myoan 2015-04-02 19:48:33