0

我在 wav 文件中录制了钢琴音符 G#4/ Ab4。我正在使用 scipy read 来读取这个 wav 文件并绘制 FFT,我只期望 415Hz 的主频率。FFT 显示的是这个频率,但有其他频率更接近它,​​我不确定为什么会看到它们。请解释

来自 wav 文件的原始信号 在此处输入图像描述

原始信号的 FFT

在此处输入图像描述

峰值频率为 415.2012138678529,幅度为 2271 位

但是当我检查 FFT 频率序列时,我还看到这些值更接近 415 Hz

在此处输入图像描述

以下是我的代码

import scipy.io.wavfile as wavfile
import scipy
import scipy.fftpack as fftpack
from matplotlib import pyplot as plt
import pandas as pd
import numpy as np
import csv

def plotGraph(figNum,x,y,xlabel,ylabel,graphlabel,color,isFFT):
    plt.figure(figNum)
    plt.xscale('log')
    plt.xlabel(xlabel)
    plt.ylabel(ylabel)
    if(isFFT=='true'):
        plt.stem(x, y, label=graphlabel,use_line_collection=True)
    else:
        plt.plot(x, y, color=color,linewidth=4.0,label=graphlabel)    
    plt.legend()

def exportToCSV(x,y,xlabel,ylabel,csvfilename):
    df = pd.DataFrame({xlabel : x, ylabel : y})
    df.to_csv(csvfilename, index=False)

def filtersignal(x,y,xlabel,ylabel,csvfilename):
    mask = y >0
    signal_with_mask = abs(y[mask])
    mean=np.mean(signal_with_mask,dtype=np.float64)
    standard_deviation=np.std(signal_with_mask,dtype=np.float64)
    third_standard_deviation=3*standard_deviation
    df = pd.DataFrame({xlabel : x[mask], ylabel : signal_with_mask - mean})   
    # print(third_standard_deviation,df[df[ylabel] > third_standard_deviation])
    signal_after_filter = df[df[ylabel] > third_standard_deviation]
    signal_after_filter.to_csv(csvfilename,header=None,index=False)

def setPlotParams():
    params = {'legend.fontsize': '20',
          'font.family': 'Times New Roman Bold',
          'font.size': '15',
          'axes.labelsize': 'x-large',
          'axes.labelweight': 'bold',
          'axes.titlesize':'x-large',
          'xtick.labelsize':'x-large',
          'ytick.labelsize':'x-large',
          'font.weight':'bold'}
    plt.rcParams.update(params)

  
def plotBarGraphFromCSV(figNum,csvfile1,csvfile2,xlabel,ylabel):
    Original_X = []
    Original_Y = []
    
    Reconstructed_X = []
    Reconstructed_Y = []
    
    with open(csvfile1,'r') as csvfile:
        plots = csv.reader(csvfile, delimiter=',')
        for row in plots:
            Original_X.append(float(row[0]))
            Original_Y.append(float(row[1]))
            
    with open(csvfile2,'r') as csvfile:
        plots = csv.reader(csvfile, delimiter=',')
        for row in plots:
            Reconstructed_X.append(float(row[0]))
            Reconstructed_Y.append(float(row[1]))
    
    plt.figure(figNum)
    lenx=len(Original_X)
    rlenx=len(Reconstructed_X)
    ind = np.arange(lenx) 
    indr = np.arange(rlenx)
    width = 0.35 
    plt.bar(ind, Original_Y, width, color='blue', label='Original Sample')
    plt.bar(indr + width, Reconstructed_Y, width,color='green',label='Reconstructed FFT Sample')
    plt.xlabel(xlabel)
    plt.ylabel(ylabel)
    plt.legend()
    plt.show()
    
# -----------------------Read the wav file to generate Time---------------
# wavFileName ="latest/PuriyaWOTanpura.wav"
wavFileName ="piano_Ab4.wav"
sample_rate, sample_data = wavfile.read(wavFileName)
print ("Sample Rate or Sampling Frequency is", sample_rate," Hz")
print(sample_data.dtype)
l_audio = len(sample_data.shape)

print ("Channels", l_audio,"Audio data shape",sample_data.shape,"l_audio",l_audio)
if l_audio == 2:
    sample_data = sample_data.sum(axis=1) / 2
N = sample_data.shape[0]
length = N / sample_rate
print ("Duration of audio wav file in secs", length,"Number of Samples chosen",sample_data.shape[0])
time =np.linspace(0, length, sample_data.shape[0])
sampling_interval=time[1]-time[0]
#---------------FFT of Original signal-----------------------
fft_amplitude=2.0*np.abs(fftpack.fft(sample_data)/len(time))
fft_freqs=fftpack.fftfreq(len(time),sampling_interval)
idx = np.argmax(np.abs(fft_amplitude))
freq = fft_freqs[idx]
freq_in_hertz = abs(freq * sample_rate)
print('Frequency ',freq,' Amplitude ',idx)
mask = fft_freqs > 0
#---------------Inverse FFT------------------------------------
inverse_fft_amplitude = scipy.ifft(fftpack.fft(sample_data))
#-----------------------Graph plotting----------------------------
setPlotParams()
plotGraph(1,time,sample_data,'Time [s]','Sample Data [bits]','Time vs Sample Data','red','false')
plotGraph(2,fft_freqs[mask],fft_amplitude[mask],'Frequency [Hz]','Sample Data [bits]','Frequency vs Sample Data','blue','true')
plotGraph(3,time,inverse_fft_amplitude,'Time [s]','Sample Data [bits]','Time vs Sample Data','green','false')
# -----------------------Exporting Results to CSV-----------------------------
exportToCSV(time,sample_data,'Time','Sample Data','OriginalData.csv')
exportToCSV(fft_freqs[mask],fft_amplitude[mask],'Frequency','Sample Data','FFTDataSet.csv')
exportToCSV(time,inverse_fft_amplitude,'Time','Sample Data','ReconstructedDataSet.csv')
# -----------------------Plot Original and Reconstructed Signal-------------
filtersignal(time,sample_data,'Time','Sample Data','OriginalDataWithMask.csv')
filtersignal(time,inverse_fft_amplitude,'Time','Sample Data','ReconstructedDataSetWithMask.csv')
plotBarGraphFromCSV(4,'OriginalDataWithMask.csv', 'ReconstructedDataSetWithMask.csv','Time [s]','Sample Data [bits]')
4

0 回答 0