fft 查看wav的频域

参考链接:https://cloud.tencent.com/developer/article/1486919

import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import wave

project_path = "/home/amazing/python/sound"

music_file_path = project_path+"/data/2.wav"


class Wav_FFT(object):
    def __init__(self, wav_path=""):
        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):
        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("signal")
            plt.grid()
            plt.title("channel%d time signal" % (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 (channel %d freq)" % (i + 1))
        plt.suptitle("wav sound_data fft sample", fontsize=14, color="magenta")
        plt.tight_layout()
        plt.show()


if __name__ == "__main__":
    wav = Wav_FFT(wav_path=music_file_path)
    wav.read_wav()
    wav.FFT()
    wav.plot()
文章目录