Obtain the envelop of a signal using MATLAB
Asked Answered
B

2

5

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 "song filtered with edge detector" plot

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

Byington answered 22/7, 2013 at 5:51 Comment(2)
Adjustments you need: (a) Format your post in a comprehensible way. (b) post a figure of what plot you currently have, what's wrong with it and what you expect to get.Saideman
Sorry for the inconvenience. Ive included the plots.Byington
A
14

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.

Accommodation answered 22/7, 2013 at 22:55 Comment(3)
Good as long as the OP can use a transform rather than a filter. The Hilbert transform is non-causal. However, Hilbert transform IIR and FIR filter approximations can be constructed.Gulfweed
In OP's code, the entire song is put into memory and then processed, so the non-causality should not be a problem (if OP wanted to find the envelope in real time, this method would not work).Accommodation
Thank you. Well the Hilbert transform doesnt give me a proper envelop. There seems to be noise, while the 5th graph from top, is what I'd like to get. And yes, i might have to work with real time.Byington
A
1

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?

Ampereturn answered 22/7, 2013 at 20:56 Comment(1)
I got this idea from a previous work.I basically need to detect the notes played from a piano piece. it should be done real time, but for now I'm working with recorded pieces. The initial step is to detect the note onsets and that is why I'm trying to create a Gaussian filter and do fast convolution with my song, so i can get the envelop of the song and define the note onsets by finding the peaks. As you can see from the above graphs (3rd from top to be exact) I'm not getting a proper envelop of my input waveform. From what I've read,FFT conv is better than just conv as its more faster.Byington

© 2022 - 2024 — McMap. All rights reserved.