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()