从mp3文件绘制频谱图

6

我正在尝试使用Python 2.7.3(在Ubuntu上)直接从mp3文件绘制频谱图。我可以按以下方式从wav文件中完成此操作。

#!/usr/bin/python
from scikits.audiolab import wavread
from pylab import *

signal, fs, enc = wavread('XC124158.wav')
specgram(signal)
show()

如何在不将所有mp3文件转换为wav的情况下,以最干净的方式从mp3文件中完成相同的操作?

2个回答

13

另一种非常简单的绘制mp3文件频谱图的方法。

from pydub import AudioSegment
import matplotlib.pyplot as plt
from scipy.io import wavfile
from tempfile import mktemp

mp3_audio = AudioSegment.from_file('speech.mp3', format="mp3")  # read mp3
wname = mktemp('.wav')  # use temporary file
mp3_audio.export(wname, format="wav")  # convert to wav
FS, data = wavfile.read(wname)  # read wav file
plt.specgram(data, Fs=FS, NFFT=128, noverlap=0)  # plot
plt.show()

这使用了pydub库,相比调用外部命令更加方便。这样,您可以在不必将文件转换为.wav格式的情况下迭代所有的.mp3文件。

输入图像描述


2
这应该是被接受的答案,最直接并且可以在单个Python脚本中直接完成。 - jbuddy_13
1
很好的回答。 如果你遇到了广播形状错误,那么你的.wav文件是立体声的。使用data = data[:, 0]将其转换为单声道。 - undefined

9
我会安装Debian/Ubuntu的软件包libav-tools,并调用avconv将mp3解码为临时wav文件:

编辑:你的另一个问题已经关闭,所以我会在这里稍微扩展一下我的答案,附带一个简单的带通滤波器示例。在你链接的文件中,大部分鸟鸣集中在4 kHz - 5.5 kHz。

import os
from subprocess import check_call
from tempfile import mktemp
from scikits.audiolab import wavread, play
from scipy.signal import remez, lfilter
from pylab import *

# convert mp3, read wav
mp3filename = 'XC124158.mp3'
wname = mktemp('.wav')
check_call(['avconv', '-i', mp3filename, wname])
sig, fs, enc = wavread(wname)
os.unlink(wname)

# bandpass filter
bands = array([0,3500,4000,5500,6000,fs/2.0]) / fs
desired = [0, 1, 0]
b = remez(513, bands, desired)
sig_filt = lfilter(b, 1, sig)
sig_filt /=  1.05 * max(abs(sig_filt)) # normalize

subplot(211)
specgram(sig, Fs=fs, NFFT=1024, noverlap=0)
axis('tight'); axis(ymax=8000)
title('Original')
subplot(212)
specgram(sig_filt, Fs=fs, NFFT=1024, noverlap=0)
axis('tight'); axis(ymax=8000)
title('Filtered')
show()

play(sig_filt, fs)

Bird Song Spectrgrams


谢谢。这个可以运行,但是它给出了一个稍微不同的谱图。原始的mp3文件在http://www.xeno-canto.org/download.php?XC=124158。除了x轴标签不同之外,使用原始mp3和你的代码版本的主要区别是在图像末尾和顶部包括一个空白时期。我通过执行"lame --decode XC124158.mp3"来制作wav版本。 - Majid
我刚看到你可能也知道http://stackoverflow.com/questions/15309155/extract-faint-bird-song-from-background-noise。如果你对此也有任何看法,那就太好了。 - Majid
1
我简化了代码以只使用mktemp(因为发现avconv无法在管道中正确编写wav文件头),并添加了更多带宽到FFT,没有重叠。 axis('tight') 可以消除空白部分。 由于大部分功率低于8kHz,您可能还需要使用axis(ymax = 8000) - Eryk Sun
不客气。过滤器并不是完美的解决方案,但在我看来,它对于如此简单的东西来说表现得相当不错。典型的音频不是频谱稳定的,因此通常需要自适应滤波。 - Eryk Sun
@erykson 谢谢。现在我有一个小任务,就是试图在所有的噪音中找到鸟叫声。你有任何关于版本中你的Python代码播放的嗡嗡声/爆裂声来自何处的想法吗? - Majid
那个噪音在通带内,并随着鸟鸣被放大。一个简单的带通滤波器无法阻止它。 - Eryk Sun

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