使用matlab实时测量语音信号的基频

时间:2014-09-18 07:17:29

标签: matlab real-time signal-processing

我想在使用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之间)。问题是它输出相同的基频。为什么会发生这种情况,我该如何解决?

谢谢。

1 个答案:

答案 0 :(得分:1)

它显示自相关,而不是基频,每1秒更新一次。代码执行在recordblocking等待,直到记录完成,然后绘制所有内容,然后再次记录,因此该循环的总时间将略多于10秒。

如果你有一个明确的音符,只有一个频率,你就会在自相关中得到一个很好的正弦波。如果有人说话,那将是一个相当混乱的情节。子图2将显示您的频率内容,这可以指示清晰的基频。

首先尝试这种方法,输入干净的正弦波,看看如何解释你的情节。然后可以尝试一个乐器的音符(将包括许多其他频率)或尝试拿着音符唱歌(祝你好运),然后考虑这种方法是否适用于说话。

老实说,有人说话的基本频率并不容易。还因为单词之间的所有暂停,不同单词中的不同音调等等。你可以通过低通滤波器来获得一些高频混乱。