我想在使用matlab录制时显示语音信号的基频。我在这里找到programming in matlab (how to process in real time)如何做实时部分。
我了解到用于确定信号基频的技术之一是自相关方法。还找到了一段实现它的代码。
现在我将这段代码添加到上面链接中找到的代码中,但由于我是这个领域的新手,我不确定我所做的是否符合我的要求 - 最后一个情节显示长度= 1秒的每个信号的基频?
clear all
clc
Fs = 8000; %# sampling frequency in Hz
T = 1; %# length of one interval signal in sec
t = 0:1/Fs:T-1/Fs; %# time vector
nfft = 2^nextpow2(Fs); %# n-point DFT
numUniq = ceil((nfft+1)/2); %# half point
f = (0:numUniq-1)'*Fs/nfft; %'# frequency vector (one sided)
%# prepare plots
figure
hAx(1) = subplot(311);
hLine(1) = line('XData',t, 'YData',nan(size(t)), 'Color','b', 'Parent',hAx(1));
xlabel('Time (s)'), ylabel('Amplitude')
hAx(2) = subplot(312);
hLine(2) = line('XData',f, 'YData',nan(size(f)), 'Color','b', 'Parent',hAx(2));
xlabel('Frequency (Hz)'), ylabel('Magnitude (dB)')
set(hAx, 'Box','on', 'XGrid','on', 'YGrid','on')
%#specgram(sig, nfft, Fs);
%# prepare audio recording
recObj = audiorecorder(Fs,8,1);
%# Record for 10 intervals of 1sec each
disp('Start speaking...')
for i=1:10
recordblocking(recObj, T);
%# get data and compute FFT
sig = getaudiodata(recObj);
%%%%%%%%%%%%%%%%%%%%%%%%%%%
ms20=Fs/50; % minimum speech Fx at 50Hz
r=xcorr(sig,'coeff');
%d=(-ms20:ms20)/Fs; % times of delays
subplot(3,1,3);
plot(r);
legend('Autocorrelation');
xlabel('Delay (s)');
ylabel('Correlation coeff.');
%55555555555555555555555555555555555
% R = xcorr (x);
r = r(160:end);
% n = 0:159; plot (n, R);
% some constants
Lmin = 20; Lmax = 146;
thr = 0.3; % maximum needs to be at least thr * R[0]
% detect lag
[Rmax,ii] = max(r((Lmin+1):(Lmax+1))); % needs to add 1 because of Matlab indexing
if Rmax >= thr * r(1) % R[0] in Matlab indexing
L=ii+Lmin-1; % and here needs to remove it again...
else
L=0;
end
%hold on; plot (L,Rmax,'or'); hold off;
% show lag in samples
L
% in seconds
T0 = L / 8000
% and fundamental frequency in Hz
F0 = 1/T0
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
fftMag = 20*log10( abs(fft(sig,nfft)) );
%# update plots
set(hLine(1), 'YData',sig)
set(hLine(2), 'YData',fftMag(1:numUniq))
title(hAx(1), num2str(i,'Interval = %d'))
drawnow %# force MATLAB to flush any queued displays
end
disp('Done.')
根据http://www.fit.vutbr.cz/~grezl/ZRE/comp_labs/03_pitch_codec_en.pdf,我在代码中添加了几行(%5555555
之间)。问题是它输出相同的基频。为什么会发生这种情况,我该如何解决?
谢谢。
答案 0 :(得分:1)
它显示自相关,而不是基频,每1秒更新一次。代码执行在recordblocking
等待,直到记录完成,然后绘制所有内容,然后再次记录,因此该循环的总时间将略多于10秒。
如果你有一个明确的音符,只有一个频率,你就会在自相关中得到一个很好的正弦波。如果有人说话,那将是一个相当混乱的情节。子图2将显示您的频率内容,这可以指示清晰的基频。
首先尝试这种方法,输入干净的正弦波,看看如何解释你的情节。然后可以尝试一个乐器的音符(将包括许多其他频率)或尝试拿着音符唱歌(祝你好运),然后考虑这种方法是否适用于说话。
老实说,有人说话的基本频率并不容易。还因为单词之间的所有暂停,不同单词中的不同音调等等。你可以通过低通滤波器来获得一些高频混乱。