How to average values and get a one-sided spectrum from two-sided spectrum?

8 次查看(过去 30 天)
Hello Community! In this code i am doing a STFT on my WAV-File. If you look at the "parameter code-line", you can see, that i am defining three different frequency bands. Afterwards, if you look at the "for loop", here i am trying to find the values of indices from the signal "Ya" and try to get a single value, which is being put together through the function "mean". I am aware there is something missing, since it doesn't work like that. But this is, what i want. I am trying to average all values, which are being defined previously from my frequnecy bands and get every value until to the length of my signal. Another thing is, i seem to get a two-sided spectrum. How do i get rid of the second spectrum? If you can provide any solutions or tips, i would appreciate it.
[y,fs]=audioread('UnchainMyHeart.wav');
% audioread = Reading the WAV-File
% y = A vector, which contains our audio signal
% fs = Sampling frequency
% 'UnchainMyHeart' = Name of the WAV-File
%PARAMETER FOR THE CODE
%_________________________________________________________________________
t_seg=0.05; %Length of the segment, on which we use the STFT
fftlen = 4096;
% Length of the FFT
% L,M,H bands
% Start & Stop frequency defenition of bands
fL = [ 1, 250 ]; % Low frequencies
fM = [ 251, 600 ]; % Medium frequencies
fH = [ 601, 1000 ]; % High frequencies
%_________________________________________________________________________
segl =floor(t_seg*fs);
% Length of the segment(50ms), which is being multiplied by the sampling frequency
% The result is rounded off with the function "floor"
windowshift=segl/2;
% Defining the size of the window, which goes to next segment and so on, until to the
% end of the audio signal
window=hann(segl);
% Hanning Function, which is being stored in a vraiable
% Matlab usually works better with variables than actual numbers. Hence the
% workspace. This way, you can avoid errors.
window=window.';
% transpose vector from a line vector to a row vector
% In the workspace, you can see, what kind of vector it is
si=1;
% Start index
ei=segl;
% End index
AOS= length(y)/windowshift - 1;
% Determining the numbers of segments in my audio signal
f1=figure;
% New figure is being openend
f=0:1:fftlen-1;
f=f/(fftlen-1)*fs;
% Definig frequency vector
Ya=zeros(1,fftlen);
% The values between "1" and "fftlen" are being filled with zeros
for m= 1:1:AOS
y_a = y(si:ei);
y_a= y_a.*window;
Ya=fft(y_a, fftlen);
% indices of bands
LI = find((f>=fL(1))&(f<=fL(2)));
MI = find((f>=fM(1))&(f<=fM(2)));
HI = find((f>=fH(1))&(f<=fH(2)));
% mean values of bands
ML = mean(Ya(LI));
MM = mean(Ya(MI));
MH = mean(Ya(HI));
drawnow;
% Updates the graphical objects
figure(f1);
plot(f, 20*log10(abs(Ya)));
ylim([-90 50]);
% Limiting the length of my y-axis
title('Spectrum of audio signal');
% Title
xlabel('f(Hz)');
% Name of x-axis
ylabel('dB');
% Name of y-axis
grid on;
% Generating grid raster
si=si+windowshift;
%Startindex is being updated
ei=ei+windowshift;
%Endindex is being updated
end

回答(1 个)

Vandana Rajan
Vandana Rajan 2016-12-21
Hi,
Your code can be simplified a lot by using the MATLAB function 'spectrogram'. Please find the link below for details on this function.
https://www.mathworks.com/help/signal/ref/spectrogram.html
By taking mean values of frequency bands, I believe you wish to take average power in those bands. 'Ya=fft(y_a, fftlen);' returns complex vectors. You need to take the power spectrum '20*log10(abs(Ya)+eps)'.
Also, variables 'windowshift' and 'AOS' are not integers. You can use 'floor' or 'round' or 'ceil'.
The code snippet, % indices of bands LI = find((f>=fL(1))&(f<=fL(2))); MI = find((f>=fM(1))&(f<=fM(2))); HI = find((f>=fH(1))&(f<=fH(2))); can be taken out of the loop, since the values are not changing with each iteration of the loop.
For your query regarding single sided spectrum, you may read the contents here
https://www.mathworks.com/matlabcentral/answers/166697-plot-single-sided-amplitude-spectrum
  2 个评论
Denny Muttathil
Denny Muttathil 2016-12-22
Regarding the single-sided-amplitude-spectrum: Wouln't the function "xlim" enough? Since the documentation says, that values are being "freezed" at the current values. For example "xlim ([0 fs/2]);". Or is it, that i just can't see the double-sided spectrum and only see half of that spectrum? But the imaginary values are still being used.
Vandana Rajan
Vandana Rajan 2016-12-22
Single sided spectrum displays only the positive half of the frequency spectrum because the spectrum of a real-world signal is symmetrical around DC. The negative frequency information is redundant. A two-sided power spectrum displays half the energy at the positive frequency and half the energy at the negative frequency. Therefore, to convert a two-sided spectrum to a single-sided spectrum, you discard the second half of the array and multiply every point except for DC by two. The height of the non-DC frequency components in the single-sided spectrum is twice the height of the non-DC frequency component in the two-sided power spectrum. Also, the single-sided spectrum stops at half the frequency of that in the two-sided power spectrum.

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Measurements and Spatial Audio 的更多信息

标签

Community Treasure Hunt

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

Start Hunting!

Translated by