Why are the results of my spectrogram sinusoidal?

8 ビュー (過去 30 日間)
Harvey
Harvey 2016 年 4 月 21 日
コメント済み: Harvey 2016 年 4 月 22 日
I am trying to determine the amplitude envelope of specific frequencies over time, from a sample of an instrument (a trumpet). I use the spectrogram function to find the amplitude of each frequency bin over time. Knowing that a harmonic lies within a certain bin, I can plot that particular bin against time to produce the following figure:
Although I can make out the general envelope, as marked in red, this method is much less accurate than what I was expecting.
I can't understand why the results are sinusoidal. Is this a result of aliasing, or something else entirely?
If we compare this plot, to a plot of all frequencies, we notice that there is no sinusoidal fluctuation in the power of the particular harmonic (The harmonic plotted in the first figure has been boxed):
So where is difference in the values used to plot the consistent power we see here, and the values that produce the sinusoidal plot?
For reference I have attached the audio file I am using. Bellow are the functions I used to get these results. Row 13 refers to the bin containing the specific harmonic;
[y,fs]=audioread('Trumpet_C4.wav');
[s,f,t]=spectrogram(y,hann(2048),1024,2048,fs,'yaxis');
s_real=real(s);
plot(t,s_real(13,:))
figure(2)
spectrogram(y,hann(2048),1024,2048,fs,'taxi's')
Any help would be extremely gratefully received!

採用された回答

J. Webster
J. Webster 2016 年 4 月 21 日
編集済み: J. Webster 2016 年 4 月 21 日
You don't want just the real part of the fft, you want the magnitude of it.
change
s_real = real(s)
to
s_mag = abs(s)
and use that in your plot.
  3 件のコメント
Harvey
Harvey 2016 年 4 月 22 日
Thank you!

サインインしてコメントする。

その他の回答 (1 件)

Star Strider
Star Strider 2016 年 4 月 21 日
I am not certain what you want to do. Just filtering the fundamental frequency gives it as a function of time, and the envelope is relatively easy to calculate:
[y,fs]=audioread('Trumpet_C4.wav');
t = linspace(0, length(y), length(y))/fs; % Time Vector
Fn = fs/2; % Nyquist Frequency
Wp = [0.2 0.4]*1E+3/Fn; % Filter Passband
Ws = [0.5 2.0].*Wp; % Filter Stopband
Rp = 10; % Passband Ripple
Rs = 45; % Stopband Ripple
[n,Wn] = buttord(Wp, Ws, Rp, Rs); % Filter Order
[b,a] = butter(n,Wn); % Transfer Function Coefficient Vectors
[sos,g] = tf2sos(b,a); % Second-Order-Section (For Stability)
figure(1)
freqz(sos, 4028, fs); % Filter Bode Plot
yf = filtfilt(sos,g, y); % Filter Signal (Phase-Neutral)
env = abs(hilbert(yf)); % Calculate Envelope
figure(2)
subplot(2,1,1)
plot(t, y)
title('Unfiltered Signal')
grid
axis([0 0.2 ylim]) % Axis Resolution (Comment-Out To See Entire Signal)
subplot(2,1,2)
plot(t, yf)
hold on
plot(t, env, '-r', t, -env, '-r')
hold off
title('Bandpass-Filtered Signal')
grid
axis([0 0.2 ylim]) % Axis Resolution (Comment-Out To See Entire Signal)
xlabel('Time (s)')
It’s a signal with a fundamental frequency and (apparently 13) harmonics, so you would have to filter each one, and calculate the envelope for each one. They seem to be evenly-spaced, so you could determine the spacing and then design a bank of filters (see How to shape the spectrum of an audio waveform? to filter each frequency.
  3 件のコメント
Harvey
Harvey 2016 年 4 月 21 日
I will try the filter bank method. Strange that the spectrogram appears steady in figure 2, but could be the windowing.
Thanks

サインインしてコメントする。

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by