I have created a Octave code for MFCC calculation for speech recognition, which takes a wav file as input and then gives the MFCC as the output. But the final results are a bit confusing, so I am unable to verify if they are correct or not.
My process:-
- Read the file, extract the samples, frequency.
- Perform pre-emphasis, by passing the data to high pass filter of alpha=0.95
- Framing of the data. My frame size is 256 and overlap of 128.
- Creating a hamming window of size 256, multiplying it with each frame.
- Calculating the FFT of each frame, then finding its absolute values. And only selecting the first half as it refers to positive frequencies.
- Created 20 Mel Filters, with lower freq=300Hz and Upper Freq=8000Hz. Now applying it to each frame, to get 20 arrays for each frame. Summing up each arrays to get just 20 values for each frame.
- Taking Log base 10 of each these 20 values per frame.
- Performing DCT on these 20 values per frame. For this I am using
dct2
method of octave.
My code:-
#{
Perform MFCC on helloworld wav file.
#}
clear all;
close all;
#{Step 0: Reading the File & initializing the Time and Freq.
#}
[x,fs,nbits]=wavread('helloworld.wav');
ts=1/fs;
N=length(x);
Tmax=(N-1)*ts;
fsu=fs/(N-1);
t=(0:ts:Tmax);
f=(-fs/2:fsu:fs/2);
figure, subplot(411),plot(t,x),xlabel('Time'),title('Original Speech');
subplot(412),plot(f,fftshift(abs(fft(x)))),xlabel('Freq (Hz)'),title('Frequency Spectrum');
#{
Step 1: Pre-Emphasis
#}
a=[1];
b=[1 -0.95];
y=filter(b,a,x);
subplot(413),plot(t,y),xlabel('Time'),title('Signal After High Pass Filter - Time Domain');
subplot(414),plot(f,fftshift(abs(fft(y)))),xlabel('Freq (Hz)'),title('Signal After High Pass Filter - Frequency Spectrum');
#{
Step 2: Frame Blocking
#}
frameSize=256;
frameOverlap=128;
frames=enframe(y,frameSize,frameOverlap);
NumFrames=size(frames,1);
#{
Step 3: Hamming Windowing
#}
hamm=hamming(256)';
for i=1:NumFrames
windowed(i,:)=frames(i,:).*hamm;
end
#{
Step 4: FFT
Taking only the positive values in the FFT that is the first half of the frame after being computed.
#}
for i=1:NumFrames
ft(i,:)=abs(fft(windowed(i,:))(1:frameSize/2));
end
#{
Step 5: Mel Filterbanks
Lower Frequency = 300Hz
Upper Frequency = fs/2
With a total of 22 points we can create 20 filters.
#}
Nofilters=20;
lowhigh=[300 fs/2];
%Here logarithm is of base 'e'
lh_mel=1125*(log(1+lowhigh/700));
mel=linspace(lh_mel(1),lh_mel(2),Nofilters+2);
melinhz=700*(exp(mel/1125)-1);
%Converting to frequency resolution
fres=floor(((frameSize)+1)*melinhz/fs);
%Creating the filters
for m =2:length(mel)-1
for k=1:frameSize/2
if k<fres(m-1)
H(m-1,k) = 0;
elseif (k>=fres(m-1)&&k<=fres(m))
H(m-1,k)= (k-fres(m-1))/(fres(m)-fres(m-1));
elseif (k>=fres(m)&&k<=fres(m+1))
H(m-1,k)= (fres(m+1)-k)/(fres(m+1)-fres(m));
elseif k>fres(m+1)
H(m-1,k) = 0;
endif
end
end
%H contains the 20 filterbanks, we now apply it to the
%processed signal.
for i=1:NumFrames
for j=1:Nofilters
bankans(i,j)=sum(ft(i,:).*H(j,:));
end
end
#{
Step 6: Nautral Log and DCT
#}
pkg load signal
%Here logarithm is of base '10'
logged=log(bankans)/log(10);
for i=1:NumFrames
lnd(i,:)=dct2(logged(i,:));
end
%plotting the MFCC
figure
hold on
for i=1:NumFrames
plot(lnd(i,:));
end
hold off
MFCC PLOT:-
My questions:-
- Are all my steps efficient and correct for the MFCC calculations as per the speech recognition criterion?
- Some tutorials say to take Square of values after step 5, is it necessary here?
- My output MFCC's first frame's 20 values are -Infinity ,Nan,Nan.... Is it possible to happen if my first frame consist of just '0' values originally in time domain?
- Overall, is my code correct, of which I am unsure, as I have read the first element of each frame's MFCC has value much higher in magnitude then the rest, but for me for some case the first MFCC element is negative and the 2nd positive, which totally defies the preclaimed rule.
Sorry if the question is amateur. I have just started to learn the DSP and Speech Processing Concepts.
Thank you.