Using the spectrogram function to analyse harmonic content

16 ビュー (過去 30 日間)
Harvey
Harvey 2016 年 4 月 19 日
回答済み: Greg Dionne 2016 年 5 月 11 日
What I'm trying to achieve;
I would like to use MATLAB to perform FFT on an audio file. The audio file is a recording of a single note of a musical instrument. I am trying to find the amplitude over time of each harmonic of the note.
Im first using the function
[y,fs]=audioread('sample.wav');
which creates a variable from the sample rate, and an array of each sample.
I then use
s=spectrogram(y,1024,512,fs);
which produces a matrix of 22051x580. Which is where I get a little lost. In fact I'm not certain, that is the best use of the function for my purpose.
So I believe that I'm right in thinking that the 22051 rows each correspond to a frequency, and that the file length (in seconds) divided by 580 would equal the time between each column. Is this correct?
Also, despite taking only the real parts of each result, many of them are negative. Is this due to negative phase?
Finally I'd greatly appreciate an idea of how I can process the results to extract the amplitude variation over time of just the harmonics of the note.

回答 (2 件)

Star Strider
Star Strider 2016 年 4 月 19 日
I don’t have your sound file so I can’t reply specifically to the data you get from it. The spectrogram function uses the surf function, so you can use that (or the mesh function as I did here) to see your signal in both frequency and time.
Run this code to get an idea how to approach your data:
fs = 4.41E+4;
t = linspace(0,2*fs,2*fs); % Time Vector
y = sin(2*pi*t*1000/fs).*exp(-2/fs*t); % Signal Vector
sound(y,fs) % Listen
figure(1)
plot(t, y)
grid
[s,f,t]=spectrogram(y,1024,512,fs);
[pks,idx] = findpeaks(abs(s(:,10)), 'MinPeakHeight',10); % Amplitude(s) & Index (Indices) Of Harmonics
figure(2)
mesh(t, f, abs(s))
grid on
xlabel('Time')
ylabel('Frequency')
So you would need to determine the columns that have your frequencies, then model each as an appropriate decaying exponential across rows.
  1 件のコメント
Harvey
Harvey 2016 年 4 月 20 日
Thank you very much for your help. That is a much better representation of the spectrogram, but I don't think I would be able to get the data I'm looking for from that method.
Ideally I would like to plot just amplitude against time for each of the specific harmonics. I have attached the reference file I am using. Although I would like to use the same method for other instrument samples.The fundamental frequency in this file should be at around 262Hz.
Many thanks.

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


Greg Dionne
Greg Dionne 2016 年 5 月 11 日
This plots the first 20 or so harmonics:
[y,fs] = audioread('Trumpet_C4.wav');
fund = 262;
spectrogram(y(1:20000),kaiser(2048,12),2048-441,(1:20)*fund,fs,'yaxis');
Or, if you like, you can show the voids in the middle too:
spectrogram(y,kaiser(2048,12),2048-441,(1:0.5:20)*fund,fs,'yaxis');
To get the power and frequencies out you can do:
[~,F,T,P] = spectrogram(y,kaiser(2048,12),2048-441,(1:0.5:20)*fund,fs);
That should give you the power output every 100ms or so (inspect the F and T vectors to get a sense of where the power is).

Community Treasure Hunt

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

Start Hunting!

Translated by