经过FFT和改变频率分量值后,我只会在音频中产生噪音。我要去哪里错了?

时间:2018-11-12 19:53:15

标签: python signal-processing fft wav frequency-analysis

我的项目的目的是合成声音。我想做的是读取一个波形文件并将其转换为振幅频谱。由于我对幅度和相应的频率感兴趣。我还需要更改某些频率(我得到的)的大小,以便我可以生成不同的声音,然后将wav文件播放回来。但是,即使不改变幅度,重建的信号也会充满噪声。

简单地说,读取文件--- FFT ---改变幅度---播放它。

下面是代码

import scipy.io.wavfile
import sounfile as sf
data , rate = sf.read("bird_chirp.wav")
FFt_data =np.fft.rfft(data)
magnitude = np.abs(FFt_data)
phase = np.angle(FFt_data)
N= len(data) # Define the length of the wav file
timestamp = np.linspace(0.0, N*T, N)
T= 1.0/rate
n = data.size


#get the corresponding Frequencies
freq = np.fft.rfftfreq(n, d=1./rate)


# save it as a Dataframe
df = {"freq":freq, "mag":magnitude}
df =pd.DataFrame(df)


#Normalize the magnitude
a=df["mag"]
norm_a = a/a.max(axis=0)
df["mag"] = norm_a


# here I would play around with magnitude , make it high or low
#code to change magnitude

#Get back the new data to write in wav
y=0
for magnitudes ,frequencies in df.iterrows():
   y+= magnitudes["mag"]*(np.sin(frequencies["freq"] *2.0*np.pi*timestamp)) 


#save it 
sf.write(file="test.wav", data=y,samplerate=rate)

代码播放的声音充满杂音。

1 个答案:

答案 0 :(得分:0)

下面是一个简单的程序,(a)读取波形文件,(b)进行傅立叶变换,(c)修改特定频率下的振幅,(d)逆向进行傅立叶变换,将数据转换回时域,然后(e)将结果保存到另一个wave文件中,您可以使用任何常用的音频播放程序播放该文件。

为了演示您可以用简单的方式处理信号, 我们衰减了1 kHz的幅度,添加了440 Hz的连续音调,并添加了880的高斯形脉冲。

请注意,在傅立叶变换中,注入的信号被缩放到其他信号的最大值。或者,我们可以选择一个振幅,并根据数据的长度对其进行缩放。

这里的一个重要概念是傅立叶变换可以节省能量。因此,傅立叶变换中的信号按其持续时间进行缩放。

以下是实现您在问题中所要查找内容的代码:

import scipy.io.wavfile
import soundfile as sf

import numpy as np

# Input the wave file
data , rate = sf.read("bird_chirp.wav")

# Fourier transform
FFT_data = np.fft.rfft(data)

# Get the list of frequencies
freq = np.fft.rfftfreq(len(data), d=1./rate)

# Find the bin closest to 1kHz and attenuate
idx = (np.abs(freq - 1.E3)).argmin()
FFT_data[idx] *= 1./2

# Find the bin closest to 440 Hz and set a continuous tone
idx = (np.abs(freq - 440)).argmin()
FFT_data[idx] = max( abs( FFT_data) )

# Add a Gaussian pulse, width in frequency is inverse of its duration
FFT_data += max( abs( FFT_data) )/2. * np.exp( -((freq-880)/5.)**2 )

# Convert back to time domain
newdata = np.fft.irfft(FFT_data)

# And save it to a new wave file
sf.write(file="test.wav", data=newdata, samplerate=rate)