wav 声音文件快速傅里叶变换

2019-08-14 16:38:46 浏览数 (2)

本篇涉及到.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()

0 人点赞