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

조회 수: 11 (최근 30일)
Denny Muttathil
Denny Muttathil 2016년 12월 18일
댓글: Vandana Rajan 2016년 12월 22일
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