Python 基频倒谱法
我试图用倒谱法来寻找频率。对于我的测试,我得到了以下文件,一个频率为440Hz的音频信号 我应用了以下公式: 倒谱=IFFT(对数FFT) 我得到256块,但我的结果总是错的Python 基频倒谱法,python,signal-processing,fft,frequency,ifft,Python,Signal Processing,Fft,Frequency,Ifft,我试图用倒谱法来寻找频率。对于我的测试,我得到了以下文件,一个频率为440Hz的音频信号 我应用了以下公式: 倒谱=IFFT(对数FFT) 我得到256块,但我的结果总是错的 from numpy.fft import fft, ifft import math import wave import numpy as np from scipy.signal import hamming index1=15000; frameSize=256; spf = wave.open('440.w
from numpy.fft import fft, ifft
import math
import wave
import numpy as np
from scipy.signal import hamming
index1=15000;
frameSize=256;
spf = wave.open('440.wav','r');
fs = spf.getframerate();
signal = spf.readframes(-1);
signal = np.fromstring(signal, 'Int16');
index2=index1+frameSize-1;
frames=signal[index1:int(index2)+1]
zeroPaddedFrameSize=16*frameSize;
frames2=frames*hamming(len(frames));
frameSize=len(frames);
if (zeroPaddedFrameSize>frameSize):
zrs= np.zeros(zeroPaddedFrameSize-frameSize);
frames2=np.concatenate((frames2, zrs), axis=0)
fftResult=np.log(abs(fft(frames2)));
ceps=ifft(fftResult);
posmax = ceps.argmax();
result = fs/zeroPaddedFrameSize*(posmax-1)
print result
对于这种情况,如何得到结果=440
**
更新:
**
我在matlab中重新编写了我的源代码,现在一切都正常了,我用440赫兹和250赫兹的频率做了测试
对于440Hz,我得到441Hz,还不错
对于250Hz,我得到249.1525Hz的近似结果
我做了一个简单的方法把峰值转换成倒谱值
我想我可以找到更好的结果使用四边形插值找到最大值
我正在绘制440Hz估计值的结果
共享用于倒谱频率估计的源:
%% ederwander Cepstral Frequency (Matlab)
waveFile='440.wav';
[y, fs, nbits]=wavread(waveFile);
subplot(4,2,1); plot(y); legend('Original signal');
startIndex=15000;
frameSize=4096;
endIndex=startIndex+frameSize-1;
frame = y(startIndex:endIndex);
subplot(4,2,2); plot(frame); legend('4096 CHUNK signal');
%make hamming window
win = hamming(length(frame));
%samples multplied by hamming window
windowedSignal = frame.*win;
fftResult=log(abs(fft(windowedSignal)));
subplot(4,2,3); plot(fftResult); legend('FFT signal');
ceps=ifft(fftResult);
subplot(4,2,4); plot(ceps); legend('ceps signal');
nceps=length(ceps)
%find the peaks in ceps
peaks = zeros(nceps,1);
k=3;
while(k <= nceps - 1)
y1 = ceps(k - 1);
y2 = ceps(k);
y3 = ceps(k + 1);
if (y2 > y1 && y2 >= y3)
peaks(k)=ceps(k);
end
k=k+1;
end
subplot(4,2,5); plot(peaks); legend('PEAKS');
%get the maximum ...
[maxivalue, maxi]=max(peaks)
result = fs/(maxi+1)
subplot(4,2,6); plot(result); %legend('Frequency is' result);
legend(sprintf('Final Result Frequency =====>>> (%8.3f)',result))
%%e前向倒谱频率(Matlab)
波形文件='440.wav';
[y,fs,nbits]=波形读取(波形文件);
子批次(4,2,1);地块(y);图例(“原始信号”);
startIndex=15000;
帧大小=4096;
endIndex=startIndex+frameSize-1;
帧=y(开始索引:结束索引);
子批次(4,2,2);情节(框架);图例(“4096块信号”);
%制作海明窗
win=汉明(长度(帧));
%汉明窗采样
windowedSignal=帧。*赢;
fftResult=log(abs(fft(加窗信号));
子批次(4,2,3);绘图(fftResult);图例(“FFT信号”);
ceps=ifft(fftResult);
子批次(4,2,4);地块(ceps);图例(“ceps信号”);
nceps=长度(ceps)
%查找CEP中的峰值
峰值=零(nceps,1);
k=3;
而(ky1&&y2>=y3)
峰值(k)=ceps(k);
结束
k=k+1;
结束
子批次(4,2,5);绘图(峰值);图例(“山峰”);
%获得最大。。。
[maxivalue,maxi]=最大值(峰值)
结果=fs/(最大值+1)
子批次(4,2,6);绘图(结果);%图例(“频率为”结果);
图例(sprintf(“最终结果频率===>>>(%8.3f)”,结果))
如果采样率为44.1 kHz,则256可能太小,无法执行任何有用的操作。在这种情况下,FFT的分辨率为44100/256=172 Hz。如果你想获得10 Hz的分辨率,那么你可以使用4096的FFT大小。倒谱方法最适合高次谐波含量的信号,而不是接近纯正弦波的信号
最佳测试信号可能更像是时域中重复的、非常接近等间隔的脉冲(每个FFT窗口越多越好),这将在频域中产生接近重复等间隔峰值的信号,这将显示为倒谱的激励部分。脉冲响应将在倒谱的下共振峰部分表示。我有一个类似的问题,因此我重用了部分代码,并通过对同一帧执行连续求值,然后从
我得到了一致的结果
def fondamentals(frames0, samplerate):
mid = 16
sample = mid*2+1
res = []
for first in xrange(sample):
last = first-sample
frames = frames0[first:last]
res.append(_fondamentals(frames, samplerate))
res = sorted(res)
return res[mid] # We use the medium value
def _fondamentals(frames, samplerate):
frames2=frames*hamming(len(frames));
frameSize=len(frames);
ceps=ifft(np.log(np.abs(fft(frames2))))
nceps=ceps.shape[-1]*2/3
peaks = []
k=3
while(k < nceps - 1):
y1 = (ceps[k - 1])
y2 = (ceps[k])
y3 = (ceps[k + 1])
if (y2 > y1 and y2 >= y3): peaks.append([float(samplerate)/(k+2),abs(y2), k, nceps])
k=k+1
maxi=max(peaks, key=lambda x: x[1])
return maxi[0]
def基础设施(框架0,采样器):
mid=16
样本=中间*2+1
res=[]
对于xrange中的第一个(示例):
最后一个=第一个样本
帧=帧0[第一帧:最后一帧]
res.append(_fondamentals(框架,采样器))
res=已排序(res)
return res[mid]#我们使用中间值
def_基础设施(框架、采样器):
frames2=帧*hamming(len(帧));
frameSize=len(帧);
ceps=ifft(np.log(np.abs(fft(frames2)))
nceps=ceps.形状[-1]*2/3
峰值=[]
k=3
而(ky1和y2>=y3):峰值。附加([浮动(采样器)/(k+2),绝对值(y2),k,nceps])
k=k+1
最大值=最大值(峰值,键=λx:x[1])
返回最大值[0]
好的,我将区块更改为4096。但即便如此,我的结果也是错误的:-(也许我需要使用二次插值来找到最大值。如果你能在你的帖子中添加初始对数幅度FFT和最终倒谱图,可能会有所帮助。而且我想我现在可能会省略零填充,并尽可能简单。酷,这只是一个测试,我将在复杂波形中使用它:-)您可以在峰值(最大)位置周围使用二次插值,并可以进一步改进结果。。。