1
$\begingroup$

What i am trying to do is to detect the pitch of a given sound signal, so for that purpose, i wanted to find cepstrum of a given signal.

This is my code in MATLAB:

[x fs] = audioread('a.wav');
N = length(x);
n = 0:N-1;

figure, stem(n, x);


X = fft(x, N);
length(X)

figure, stem(n, X);

Y = X(1:6400);
N = length(Y);
n = 0:N-1;


figure, stem(n, Y);


Z = log(abs(Y));
figure, stem(n, Z);

z = ifft(Z, N);
figure, stem(n, z);

Now, all i did was that i found fft of audio signal and then i cut off the second half of it because it is basically the same thing i have in the first half, then, i just followed the standard procedure for cepstum, i moved to logarimic representation and then i found inverse fourier of it. Based on what i saw on the internet, i expected evenly spaced peaks since that represents existence of a definite pitch in the signal, however, this is what i get:

enter image description here

So basically i have no idea what can i do with this, since this what i have is speech signal, i am not sure why there's no any evenly spaced peaks. When i zoomed in a bit, this is what i got

enter image description here:

This also doesn't help at all, i am having trouble with understanding the way that cepstrum enables us to determine pitch frequency so basically, even if i had something what would seem to me as a proper cepstrum, i doubt that i would be able to determine pitch frequency from it, so any help is highly appreciated!

$\endgroup$
  • $\begingroup$ what kinda sound is it? a musical note? a bird tweeting? a car horn? someone farting into a microphone? $\endgroup$ – robert bristow-johnson Jan 11 at 19:21
  • $\begingroup$ If you look carefully, you might see evenly spaced peaks at around 40,80,110. A cepstrum is unlikely to be an accurate pitch estimator, but for harmonic rich signals it can provide the proper ballpark in which to target another estimator (interpolated autocorrelation, upsampled AMDF, etc.) $\endgroup$ – hotpaw2 Jan 11 at 19:24
  • $\begingroup$ @robertbristow-johnson If you've read my question, you could see that i said that it is speech. $\endgroup$ – cdummie Jan 11 at 19:26
  • $\begingroup$ @hotpaw2 well, i can see it has some components that are a bit above at 37, 74 and 116, but i am not quite sure if the last one can even be considered as peak, anyway, what does that means in terms of finding pitch? Can we say then that this is proper cepstrum considering that this is speech signal? $\endgroup$ – cdummie Jan 11 at 19:31
  • 1
    $\begingroup$ @robert bristow-johnson Thank you for links you provided, i appreciate it. $\endgroup$ – cdummie Jan 11 at 21:16
1
$\begingroup$

I wrote a very very basic cepstrum pitch track in the past, well we can try using a pure senoidal signal to show how its works... let me see

For Cepstrum I always have used this steps:

  • Apply hamming windows in the signal
  • Apply FFT
  • Get magnitude
  • Convert to log scale
  • Apply IFFT

The equation for cepstrum:

IFFT(log(abs(FFT(s))))

But you can use FFT or IFFT, take a look:

IFFT(log(abs(FFT(s)))) == real(FFT(log(abs(FFT(s)))))

The difference is the scale representation, if do you end using FFT you need extract just the real information, for both above equations you will get the same shape:

For IFFT(log(abs(FFT(s)))):

enter image description here

For real(FFT(log(abs(FFT(s))))):

enter image description here

This is a cepstrum shape example from 4096 points sine in 440hz sampled at 44100hz

Now try get the maximum from the half cepstrum data to find the periodicity...

see my extremely basic code of how to get a sine frequency, just to exemplify to you:

Fs=44100;


%creating one simple signal

f=440; %we need find this 
frame = sin(2*pi*f/Fs*(1:2048*2))';



win = hamming(length(frame));


%samples multplied by hamming window
windowedSignal = frame.*win;


fftResult=log(abs(fft(windowedSignal)));


ceps=real(ifft(fftResult));



nceps=length(ceps)

%find the peaks in ceps

peaks = zeros(nceps,1);

k=3;

while(k <= nceps/2 - 1)
   y1 = ceps(k - 1);
   y2 = ceps(k);
   y3 = ceps(k + 1);
   if (y2 > y1 && y2 >= y3)
      peaks(k)=ceps(k);
   end
k=k+1;
end



%get the maximum ...
[maxivalue, maxi]=max(peaks);



result = Fs/(maxi+1) 

my result was close 441hz for better results maybe do you need apply parabolic interpolation ....

| improve this answer | |
$\endgroup$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.