用Python从音频文件中提取音频频谱

10
抱歉如果我提交了重复的内容,但我想知道是否有Python库可以从音频文件中提取声谱。我想能够获取一个音频文件并编写一个算法,该算法将返回一组数据{文件中的时间戳;频率-振幅}。
我听说这通常被称为节拍检测,但据我所见,节拍检测不是一种精确的方法,它只适用于可视化,而我想在提取的数据上进行操作,然后将其转换回音频文件。我不需要实时处理。
我将感激任何建议和推荐。
2个回答

15
你可以使用scipy计算和可视化频谱和声谱图,为了进行此测试,我使用了这个音频文件:vignesh.wav
from scipy.io import wavfile # scipy library to read wav files
import numpy as np

AudioName = "vignesh.wav" # Audio File
fs, Audiodata = wavfile.read(AudioName)

# Plot the audio signal in time
import matplotlib.pyplot as plt
plt.plot(Audiodata)
plt.title('Audio signal in time',size=16)

# spectrum
from scipy.fftpack import fft # fourier transform
n = len(Audiodata) 
AudioFreq = fft(Audiodata)
AudioFreq = AudioFreq[0:int(np.ceil((n+1)/2.0))] #Half of the spectrum
MagFreq = np.abs(AudioFreq) # Magnitude
MagFreq = MagFreq / float(n)
# power spectrum
MagFreq = MagFreq**2
if n % 2 > 0: # ffte odd 
    MagFreq[1:len(MagFreq)] = MagFreq[1:len(MagFreq)] * 2
else:# fft even
    MagFreq[1:len(MagFreq) -1] = MagFreq[1:len(MagFreq) - 1] * 2 

plt.figure()
freqAxis = np.arange(0,int(np.ceil((n+1)/2.0)), 1.0) * (fs / n);
plt.plot(freqAxis/1000.0, 10*np.log10(MagFreq)) #Power spectrum
plt.xlabel('Frequency (kHz)'); plt.ylabel('Power spectrum (dB)');


#Spectrogram
from scipy import signal
N = 512 #Number of point in the fft
f, t, Sxx = signal.spectrogram(Audiodata, fs,window = signal.blackman(N),nfft=N)
plt.figure()
plt.pcolormesh(t, f,10*np.log10(Sxx)) # dB spectrogram
#plt.pcolormesh(t, f,Sxx) # Lineal spectrogram
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [seg]')
plt.title('Spectrogram with scipy.signal',size=16);

plt.show()

我测试了所有代码,它能正常工作,你需要使用numpy、matplotlib和scipy。

祝好!

1
谢谢你的脚本!只需在顶部添加“import numpy as np”即可使其正常工作。 - Florian Arndt
获取这些错误: plt.plot(freqAxis / 1000.0,10 * np.log10(MagFreq))#功率谱 Traceback(最近的调用最后一次): packages / scipy / signal / _spectral_py.py“,第1971行,在_triage_segments raise ValueError('window is longer than input signal') ValueError:窗口比输入信号长。 dirk.schiller@C02DT9UMML7H scipy%``` - Dirk Schiller

11

我认为你的问题有三个独立的部分:

  1. 如何在Python中加载音频文件?
  2. 如何在Python中计算频谱?
  3. 对于频谱应该怎么做?

1. 如何在Python中加载音频文件?

最好使用 scipy,因为它提供了许多信号处理函数。加载音频文件:

import scipy.io.wavfile

samplerate, data = scipy.io.wavfile.read("mywav.wav")

现在您可以在 samplerate 中获取采样率(samples/s),并且在 data 中以 numpy.array 的形式获取数据。根据您的应用程序,您可能希望将数据转换为浮点数。

还有一个标准的 Python 模块 wave 可以加载 wav 文件,但是 numpy/scipy 提供了更简单的接口和更多的信号处理选项。

2. 如何计算频谱

简短回答:使用 FFT。更多智慧之言,请参见:

使用快速傅里叶变换分析音频

较长回答比较长。窗函数非常重要,否则您将获得奇怪的频谱。

3. 如何处理频谱

这有点困难。对于较长的信号,通常在时域中执行滤波。也许如果您告诉我们您想要实现什么,您将会得到一个好的答案。计算频谱是一回事,在信号处理中获得有意义的结果则稍微复杂一些。

(我知道您没有问这个问题,但是我认为它的概率 >> 0。当然,可能您对音频信号处理有很好的了解,那么这就无关紧要了。)


谢谢,这真的很有帮助。我计划使用scikit-learn或PyBrain编写软件,分析音频文件并尝试确定它属于哪种音乐类型。 - Maksim Khaitovich
1
有些晚了,但考虑到你的目标(编写一个用于分类音乐流派的库),你可以看一下这个链接:https://github.com/tyiannak/pyAudioAnalysis - Manuel G

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