Question

I'm trying to extract the peaks of an audio file. I have the following code to extract the envelope of my amplitude spectrum. However I'm not getting the desired output graph. Can someone tell me what adjustment I need to make to get a proper graph. Here's my code:

[song,FS] = wavread('c scale fast.wav');


P=20000/44100*FS;                   % length of filter 
N=length(song);                     % length of song
t=0:1/FS:(N-1)/FS;                  % define time period
% Plot time domain signal
figure(1);
subplot(3,1,1)
plot(t,(3*abs(song)))
title('Wave File')
ylabel('Amplitude')
xlabel('Length (in seconds)')
xlim([0 1.1])

xlim([0 N/FS])


% Gaussian Filter
x = linspace( -1, 1, P);         % create a vector of P values between -1 and 1 inclusive
sigma = 0.335;                  % standard deviation used in Gaussian formula
myFilter = -x .* exp( -(x.^2)/(2*sigma.^2));% compute first derivative, but leave constants out

myFilter = myFilter / sum( abs( myFilter ) ); % normalize
% Plot Gaussian Filter

subplot(3,1,2)       
plot(myFilter)
title('Edge Detection Filter')

% fft convolution
myFilter = myFilter(:);                         % create a column vector
song(length(song)+length(myFilter)-1) = 0;      %zero pad song
myFilter(length(song)) = 0;                     %zero pad myFilter
edges =ifft(fft(song).*fft(myFilter));

tedges=edges(P/2:N+P/2-1);                      % shift by P/2 so peaks line up w/ edges
tedges=tedges/max(abs(tedges));                 % normalize

% Plot song filtered with edge detector          
subplot(3,1,3)

plot(1/FS:1/FS:N/FS,tedges)
title('Song Filtered With Edge Detector')
xlabel('Time (s)')
ylabel('Amplitude')
ylim([-1 1.1])
xlim([0 N/FS])

This is the graph i get for the above code and im focusing on the

This is the graph i get for the above code and im focusing on the "song filtered with edge detector" plot

enter image description here

And this is the "song filtered with edge detector" plot I NEED to get

Était-ce utile?

La solution

You can use a Hilbert transform to get the envelope. Technically, this returns the analytic signal. You get the envelope with the following line:

envelope = abs(hilbert(Song));

What the Hilbert transform does is to take the fft of the input, zeroes out the negative frequencies, and then does an ifft. The real part of the transform is the original signal, the imaginary part is the transformed signal. The absolute value of the real and imaginary part is the envelope, and the argument (angle(hilbert(Song))) is the instantaneous phase.

Autres conseils

I assume you want to obtain the envelope of the signal (not of its spectrum as you say). If that is the case, for envelope detection I would use a lowpass filter applied to abs(song) (you can substituye abs by a similar non-linear function). The cutoff frequency of the filter should be (slightly) above the highest frequency of the envelope variations.

You are applying the filter directly to the waveform, and the filter does not seem to be a lowpass filter. Perhaps if you explain your approach we can provide more focused help.

By the way, if your song is much longer than your filter, the zero-padding followed by fft followed by ifft seems to be a slow way of doing the filtering. Why not just use conv?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top