1
$\begingroup$

I am trying to detect the pitch of a given sound signal, so for that purpose, I wanted to find the Cepstrum of a that 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);

All I did was:

  1. Compute the FFT of the audio signal and discard the 1st half since it is redundant.

  2. Followed the standard procedure to compute the Cepstrum:

    • Move to a logarithmic representation
    • Compute the inverse FFT.

Based on what I saw on the internet, I expected evenly spaced peaks that would represent the definite pitch in the signal.

However, this is what I get:

enter image description here

I have no idea what can I do with this. Since what I have is a speech signal, I am not sure why there's not any evenly spaced peaks. Zooming in a bit, this is what I get:

enter image description here:

This also doesn't help at all. I am having trouble understanding the way that the Cepstrum enables us to determine pitch frequency.
Even if I had something that resembled a proper Cepstrum, I doubt that I would be able to determine the pitch frequency from it, so any help is highly appreciated!

$\endgroup$
8
  • $\begingroup$ what kinda sound is it? a musical note? a bird tweeting? a car horn? someone farting into a microphone? $\endgroup$ Commented Jan 11, 2020 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
    Commented Jan 11, 2020 at 19:24
  • $\begingroup$ @robertbristow-johnson If you've read my question, you could see that i said that it is speech. $\endgroup$
    – cdummie
    Commented Jan 11, 2020 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
    Commented Jan 11, 2020 at 19:31
  • 1
    $\begingroup$ @robert bristow-johnson Thank you for links you provided, i appreciate it. $\endgroup$
    – cdummie
    Commented Jan 11, 2020 at 21:16

2 Answers 2

2
$\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 ....

$\endgroup$
0
$\begingroup$

For one thing, you should probably not eliminate the upper part of the FFT spectrum. Doing that distorts the signal in the time domain.

The IFFT returns real numbers because of the symmetry of the FFT output. Once you modify that, the IFFT will not be real anymore.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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