我试图为aiff文件创建一个低通滤波器,但发出的声音是白噪声。我只了解FFT的工作原理的广泛概述,所以我猜我的问题与此有关。
基本上,我打开音频文件(例如钢琴循环),将其转换为单声道,然后对样本执行FFT,然后尝试通过将它们设置为零来去除较高的频率。最后,我执行IFTT并将结果保存到新文件中。
import aifc
import struct
import numpy as np
def getMonoSamples(fileName):
enter code here`obj = aifc.open(fileName,'r')
obj.setpos(0)
numFrames = obj.getnframes()
myFrames = obj.readframes(numFrames)
samplingRate = obj.getframerate()
data = struct.unpack('{n}h'.format(n=numFrames*2), myFrames)
data = np.array(data)
dataLeft =[]
for i,x in enumerate(data):
if i%2==1:
dataLeft.append(x)
obj.close()
return dataLeft,numFrames,samplingRate
def writeMonoFile(fileName,samples,nframes):
mono_file=aifc.open(file, 'w')
comptype="NONE"
compname="not compressed"
nchannels=1
sampwidth=2
mono_file.setparams((nchannels, sampwidth, int(sampling_rate), nframes, comptype, compname))
print "writing sample aif..."
for s in samples:
mono_file.writeframes(struct.pack('h', s))
mono_file.close()
def lpFilter(dataFft):
new =[None]*len(dataFft)
for i,x in enumerate(dataFft):
#if the frequency is above 5000, remove it
if i>5000:
new[i]=0
else:
new[i]=x
return new
# get audio samples from a function that converts stereo to mono
sampleData,numFrames,samplingRate = getMonoSamples('beetP2.aif')
dataFft = np.fft.fft(sampleData)
filtered = lpFilter(dataFft)
invFft = np.fft.ifft(filtered)
invFft = [int(x) for x in invFft]
file = "test.aif"
writeMonoFile(file,invFft,numFrames)
我的确收到警告:“ComplexWarning:将复数值转换为实数会丢弃虚部”,但在执行立体声到单声道转换并保存时,也会收到此警告。直到我尝试过滤音频为止,声音似乎都很好。我猜这是相关的,但不确定如何解决。
我过滤的任何音频样本都会听起来像白噪声,而不是本身的过滤版本。
最佳答案
切换为实数到复杂的 numpy.fft.rfft
及其相反的 numpy.fft.irfft
可能会解决此问题。
由于将复数到复数DFT变换应用于实际数组sampleData
,因此输出数组是相同大小的复杂数组dataFft
。该阵列的第一项对应于DC分量,第二项对应于频率1 / N,第三项对应于频率2 / N ...然而,该阵列的后半部分应描述为负频率分量。因此,数组最后一项的频率为-1 / N,即-2 / N之前的项...如what FFTW really computes中所述
由于信号是实数,因此频率-k / N的分量必须是频率k / N的分量的复共轭。例如,频率为k / N的余弦波产生了频率为k / N和-k / N的两个相等的实数分量。
通过将阵列的后半部分归零,将丢弃具有低负频率的分量,并且该阵列不再对应于实际阵列的DFT。它不是低通滤波器,可能会解释产生的白噪声。当应用逆DFT invFft = np.fft.ifft(filtered)
时,其结果invFft
很复杂,其大小与原始数组sampleData
相同。
使用实际到复杂的DFT,会将实际数组sampleData
转换为大小约为一半的复杂数组dataFft
。将此阵列的一个分量置零意味着将正频率和负频率均置零,确保将阵列仍视为真实阵列的DFT。最终可以通过应用逆变换irfft
恢复此实际数组。
关于python - 如何使用fft为音频创建低通滤波器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57225531/