本篇涉及到.wav 声音文件的读取,FFT变换以及用matplotlib来显示声音的时域和频域信息。
.wav文件的读取和分析需用到标准库wave和数值计算库numpy。
示例代码如下:
代码语言:javascript复制import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import wave
class Wav_FFT(object):
def __init__(self, wav_path=r"c:WINDOWSMediaAlarm02.wav"):
self.path = wav_path
def read_wav(self):
with wave.open(self.path, "rb") as f:
parameters = f.getparams()
self.nchannels, self.sampwidth, self.framerate, self.nframes = parameters[:4]
self.time_len = self.nframes*1.0 / self.framerate #声音时长
print("声道数: ", self.nchannels) #声道数:可以是单声道或者是双声道
print("量化位数[byte]: ", self.sampwidth)#量化位数:一次采样所采集的数据的字节数
print("采样频率[Hz]: ", self.framerate) #采样频率:一秒内对声音信号的采集次数,常用的有8kHz, 16kHz, 32kHz, 48kHz, 11.025kHz, 22.05kHz, 44.1kHz
print("采样点数: ", self.nframes)#采样点数
print("声音时长[s]: ", round(self.time_len,3))#声音时长
# 读取波形数据
str_data = f.readframes(self.nframes)
wave_data = np.fromstring(str_data, dtype=np.short)
wave_data.shape = -1, self.nchannels
self.wave_data = wave_data.T
def FFT(self):
yf = np.fft.fft(self.wave_data)# FFT
bias = (yf[:, 0] / self.nframes).real
yf_amplitude = np.abs(yf)* (2.0/self.nframes)
yf_amplitude[:, 0] = bias #直流分量(0 Hz处)修正
self.yf_amplitude = yf_amplitude[:, 0:self.nframes//2]#有效信息只有一半
def plot(self):
matplotlib.rcParams["font.sans-serif"] = ["SimHei"]
matplotlib.rcParams["axes.unicode_minus"] = False
self.time = np.arange(0, self.nframes) * (1.0 / self.framerate)
self.freq = np.arange(0,self.nframes//2) * self.framerate / self.nframes #实际频率
for i in range(self.nchannels):
plt.subplot(2, self.nchannels, i 1)
plt.plot(self.time, self.wave_data[i,:])
plt.xlabel("time 时间")
plt.ylabel("信号值")
plt.grid()
plt.title("通道%d 时域信号" %(i 1))
plt.subplot(2, self.nchannels, self.nchannels i 1)
plt.plot(self.freq, self.yf_amplitude[i, :], "r-")
plt.xlabel("Frequency 频率[Hz]")
plt.ylabel("Amplitude 幅值")
plt.grid()
plt.title("FFT (通道%d 频域信号)"%(i 1))
plt.suptitle("wav 声音数据 快速傅里叶变换 示例", fontsize =14, color ="magenta")
plt.tight_layout()
plt.show()
if __name__ == "__main__":
wav = Wav_FFT(wav_path=r"c:WINDOWSMediaAlarm03.wav")
wav.read_wav()
wav.FFT()
wav.plot()