I want to display the fundamental frequency of a voice signal while recording using matlab. I found here programming in matlab (how to process in real time) how to do the real-time part.
I learned that one of the techniques that are used to determine the fundamental frequency of a signal is the autocorrelation method. Also found a piece of code which implemented it.
Now I added the piece of code into the one found in the link above, but since I am a newbie in this field, I am not sure if what I've done does what I want - does the last plot display the fundamental frequency for each of the pieces of signal of length=1 second?
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.')
According to http://www.fit.vutbr.cz/~grezl/ZRE/comp_labs/03_pitch_codec_en.pdf, I added a few lines to my code(between %5555555
). The promblem is it outputs the same fundamental frequency. Why is that happening and how could I solve it?
Thank you.
It shows the autocorrelation, not the fundamental frequency, updated every 1 second. Code execution waits at recordblocking
until recording is done, then everything is plotted and then you record again, so total time of that loop will be a little bit more than 10 seconds.
If you have a clear note, with one frequency only, you'd get a nice sine wave of that frequency in your autocorrelation. If someone is speaking, that would be a pretty messy plot. Subplot 2 will show you your frequency content, which could give an indication of clear base frequencies.
Try this approach first with inputting clean sine waves to see how to interpret your plots. Then maybe try a note from an instrument (will include a lot of other frequencies) or try holding a note singing (good luck) and then think about whether this approach holds for speaking.
Honestly, a base frequency of someone speaking is not going to be easy. Also because of all the pauses between words, different tones in different words, etc. You could btw low pass filter to get some of the high frequency mess out.