4
$\begingroup$

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:-

  1. Read the file, extract the samples, frequency.
  2. Perform pre-emphasis, by passing the data to high pass filter of alpha=0.95
  3. Framing of the data. My frame size is 256 and overlap of 128.
  4. Creating a hamming window of size 256, multiplying it with each frame.
  5. Calculating the FFT of each frame, then finding its absolute values. And only selecting the first half as it refers to positive frequencies.
  6. 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.
  7. Taking Log base 10 of each these 20 values per frame.
  8. 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:-

enter image description here

My questions:-

  1. Are all my steps efficient and correct for the MFCC calculations as per the speech recognition criterion?
  2. Some tutorials say to take Square of values after step 5, is it necessary here?
  3. 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?
  4. 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.

$\endgroup$
  • 1
    $\begingroup$ I went through your code and it seems all right to me. If you have INFs I guess it's because first samples in the file are zero and log of 0 doesn't exist (in real numbers domain of course), so you get INF. There are implementations that take: abs value, power (squared amplitude) etc. You did not say exactly how your MFCC graph looks like. If you have first MFCC coefficients from each segment much different from the others (2,3,...), it is because the first component of DCT is constant and as the result of transformation, the first MFCC coefficient is literately sum off all energy logs. $\endgroup$ – Celdor Sep 29 '15 at 10:18
  • $\begingroup$ @Celdor MFCC PLot added, thats what I get after the code runs, i.e. plotting all frames MFCC in one figure. Seems right ? $\endgroup$ – Mohit Sep 29 '15 at 11:25
  • $\begingroup$ According my experience and knowledge (I might be wrong), it doesn't look suspicious. For reasons I described before, your first coefficients stay far below 0. Also, I guess you took MFCC from the whole file or long period as you got a large number of lines. You want to try to explore just a few segments if they look similar, e.g. while one was saying a letter or begun to pronoucne a word. You may want to compare this with other segements when the same word was pronounced but don't try to examine the whole word. $\endgroup$ – Celdor Sep 29 '15 at 11:39
  • $\begingroup$ Thanks a lot! Yeah I am using a 2 sec clip of speech saying "hello world". Well thats what I was worrying about, if mfcc are right or not. Thank you. $\endgroup$ – Mohit Sep 29 '15 at 11:43
  • 1
    $\begingroup$ My procedure is similar to yours. There's always differences because you can play with a lot of parameters here. I compared my results with results obtained from another function: PLP and RASTA (and MFCC, and inversion) in Matlab using melfcc.m and invmelfcc.m. I just needed to provide Dan Ellis'es filterbanks and I found that my results were almost exactly the same Dan's. So I really think you routine is correct. $\endgroup$ – Celdor Sep 29 '15 at 11:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.