Related
I build a pam-2 modulation, then I make a pulse shaping with half sine (matched filter).
Then I send it through the AWGN channel.
At the end I do down sampling and demodulation.
But i have problem with plotting BER. I don't understand what I'm doing wrong:
clc;
clear;
N=1e4;
N2 = 1e2;
M = 2;
range = 0:10;
error = zeros(1,length(range)); %BER
%
% half sine
Rc = 1e3; % Chip rate
T = 1/Rc; % inverse of chip rate
Tc = 0.5* T;
Fs = 2e3; % sampling frequency
dt = 1/Fs;
over = Fs/Rc; % sampling factor
sps = 10;
time = 0:dt/sps:2*T;
half_Sine = sin(pi*time/(2*T)).^3;
%% BER
for i = 1:length(range)
for n = 1:N2
% Modulation
x=randi([0 M-1],N,1);
h_mod = pammod(x,M);
over_data=upsample(h_mod,over);
txSig = conv(over_data,half_Sine, 'same');
% AWGN
Ps = mean(((txSig)).^2);
Sigma = sqrt(Ps * 10^(-range(i)/10) / 2);
Noise = randn(length(txSig), 1) * Sigma;
rx_SIG = Noise + txSig;
% Downsample
down = rx_SIG(1:over:end);
% Demodulation
hDemod = pamdemod(down,M);
% Errors
error(i) = error(i)+...
sum(hDemod~=x) / length(hDemod);
end
BER = error/n;
end
figure(1);
grid on
semilogy(range,BER);
title('BER');
Update:I need to build a ber from 10^1 to 10^6
1.- Your script up and running :
There are many code lines turned comments that I used to get to run the start script. I have left them along, that should be used while debugging only.
close all;clear all;clc;
N=1024;
M = 2;
% pulse : half sine
Rc = 1e3; % [b/s] chip rate
T = 1/Rc; % [s/b] inverse of chip rate
Tc = 0.5* T;
Fs = 2e3; % [Hz] sampling frequency
dt = 1/Fs; % [s]
ov1 = Fs/Rc; % sampling factor
sps = 10;
dt2=dt/sps
% single pulse time reference
t = [0:dt2:2*T]; % [s]
% signals usually have a known preable
% a heading known sequence that helps receivers
% extract with relative ease when pulse peaks take place
% the sync preamble has to be long enough to acquire
% the sampling interval.
% For simplicity here I just make sure that the first bit of the signal is always 1
nsync=64 % length sync header
x=[ones(1,nsync) randi([0 M-1],1,N-nsync)]; % signal : data
xm=reshape(x([nsync+1:end]),[(N-nsync)/8 8])
L1=sum(repmat(2.^[7:-1:0],size(xm,1),1).*xm,2); % string to check received bytes against, to measure BER
over_data = pammod(x,M); % signal : PAM symbols
% err1 = zeros(1,length(x)); %BER
% single pulse
pulse_half_Sine = sin(pi*t/(2*T)).^3;
figure;plot(t,pulse_half_Sine)
grid on;xlabel('t');title('single pulse')
% A=[.0001:.0001:1];
A=[1e-3 5e-3 1e-2 5e-2 .1 .5 1 10 100];
% A=[5e-2:1e-2:2];
rng1 = [1:numel(A)]; % amount S power levels to check for BER
% to use power on requires a reference impedance
% usually assumed 1, in accademic literature, but then when attempting to correlated
% BER with used Watts if R0=1 the comparison is not correct.
R0=50 % [Ohm]
%% BER measuring loop
% k=1
% Logging BER for different signal power levels,
% Logging signal power levels, it was useful when getting script up and running
BER=[];
SNR_log=[];
figure(1)
ax1=gca
for k = 1:length(rng1)
% generating signal
x2=2*(x-.5); % [0 1] to [-1 1]
S=[]
for k2=1:1:numel(x)
S=[S A(k)*x2(k2)*pulse_half_Sine];
end
Ps = mean(S.^2)/R0; % signal power
% adding AWGN
% you are making the noise proportional to the signal
% this causes BER not to improve when signal power up
% sigma1 = sqrt(Ps * 10^(-rng1(k)/10) / 2); % not used
sigma1=.1
noise1 = randn(length(S), 1) * sigma1;
Pn=mean(noise1.^2)/R0;
rx_S = noise1' + S; % noise + S
% Downsample
% this downsampling is an attempt to sync received signal
% to the time stamps where pulse peaks are expected
% but it does not work
% dwn1 = rx_SIG(1:ov1:end);
% Demodulation
% because the sampling times of the previous line are not
% centered pamdemod doesn't work either
% hDemod = pamdemod(dwn1,M);
% the missing key step : conv on reception with expected pulse shape
rx2_S=conv(pulse_half_Sine,rx_S);
rx2_sync=conv(pulse_half_Sine,rx_S([1:1:nsync*numel(pulse_half_Sine)]));
% removing leading samples that only correspond to the
% pulse used to correlate over received signal
rx2_S([1:numel(pulse_half_Sine)-1])=[];
% syncing
[pks,locs]=findpeaks(abs(rx2_sync),'NPeaks',nsync,'MinPeakHeight',A(k)/2);
% [pks,locs]=findpeaks(abs(rx2_S));
% x3(find(pks<.1))=[]; % do not use sign results close to zero
% locs(find(pks<.1))=[];
% t0=dt2*[0:1:numel(rx2_sync)-1];
% figure;plot(t0,rx2_sync);hold on
% plot(t0(locs),pks,'bo')
% 5 header pulses needed, 1st and last header samples are null, not needed
n01=find(pks<.2*A(k));
if ~isempty(n01) peaks(n01)=[];locs(n01)=[]; end
% pks([1 end])=[];locs([1 end])=[];
% plot(t0(locs),pks,'rs')
% since we know there have to be 5 leading pulses to be all ones
% we extract the sampling interval from this header
nT2=round(mean(diff(locs)))
% t3=dt2*[0:1:numel(rx2_S)-1];
% figure;plot(t3,abs(rx2_S));
% hold on
% xlabel('t')
% plot(t3(locs),pks,'ro')
% nt3=[1:nT2:numel(x)*nT2]; % sampling times
% plot(t3(nt3),max(pks)*ones(1,numel(nt3)),'sg')
x3=sign(rx2_S([1:nT2:N*nT2])); % only N bits expected so only sample N times
% x3 [-1 1] back to [0 1] otherwise when comparing v3 against x
% a roughtly 50% of bits are always going to be wrong, which comes
% from the signal statistics
x3=.5*(1+x3);
% sampling
% x3=sign(rx_S(locs));
% making sure x3 and x same length
% x3(find(pks<.1))=[]; % do not use sign results close to zero
SNR=Ps/Pn;
SNR_log=[SNR_log Ps];
x3_8=reshape(x3([nsync+1:end]),[(N-nsync)/8 8])
Lrx=sum(repmat(2.^[7:-1:0],size(x3_8,1),1).*x3_8,2);
err1 = sum(L1~=Lrx) / length(Lrx);
BER = [BER err1];
end
%% BER(S)
figure(1);
plot(rng1,BER);
grid on
title('BER/rng1');
This is not BIT ERROR RATIO as we know it and as it is used in all sort of quality measurements.
Note that Bit Error Ratio is not the same as Bit Error Rate despite both terms commonly used alike.
A rate implies and amount/seconds a velocity, speed.
BER as used commonly used to measure signal quality is a RATIO, not a rate.
BER = correct_bits/total_bits , but it's not as simple as this, as I am going to show.
For instance note that worst BER obtained with your script with a quick fix doesn't reach above 0.5 (!?) BER certainly reaches 1 when message not 'getting-there'.
I believe the following points are important for you to understand how BER really works.
2.- BER was completely flat for really dispare signal power levels
In an earlier working script not shown even using pulse amplitude A=100, and low noise mean(noise1)=-7.36e-04 about 1/3 of the received symbols are erroneous while figure;plot(rx_S) shows a rather clean signal, no riding ripple, no sudden changes ..
The 1/3 errorenous bit were not corrupted by channel noise but it was already in the transmitted signal. I have spaced each pulse enough to avoid overlapped pulses.
Adjacent pulses need at least 2ms to avoid overlapping.
This is without considering doppler.
Heavily overlapping symbols is what happens when command conv is used on a train of pulses generated the way you did :
S = conv(over_data,A(k)*pulse_half_Sine, 'same');
3.- You started with 1e4 data bits treated as 1e4 modulation symbols
But your transmitted-received time signal also showed length 1e4 time samples, cannot be, way too few time samples.
The time reference of over_data and pulse_half_Sine should not be the same.
Nyquist; signal is currupted beyond recovery if only 2 samples er cycle of let's say carrier modulating pulses.
I tried
h_mod = pammod(x,M);
over_data=upsample(h_mod,ov1);
S = conv(h_mod,A(k)*pulse_half_Sine, 'same'); % modulated signal
h_mod = pammod(x,M);
S = conv(h_mod,A(k)*pulse_half_Sine, 'same'); % modulated signal
S = conv(over_data,A(k)*pulse_half_Sine, 'same'); % modulated signal
and none of these 3 got the expected BER showing whether the signal is strong or weak.
4.- It turns out command upsample is for discrete-time models
sys = tf(0.75,[1 10 2],2.25)
L = 14;
sys1 = upsample(sys,L)
not to directly interpolate a signal to, for instance, double the amount of samples as it seems you attempted.
5.- This is how the transmitted signal (before noise added) should look like
t2=dt2*[0:1:numel(S)-1];
figure;plot(t2,S);
grid on;xlabel('t');title('transmitted signal before noise')
t3=dt2*[0:1:numel(rx2_S)-1];
[pks,locs]=findpeaks(abs(rx2_S))
figure;plot(t3,rx2_S);
hold on
xlabel('t')
plot(t3(locs),pks,'ro')
6.- The chosen pulse is not particularly strong against AWGN
The main reason being because it's a baseband pulse. not modulated, and on top of this only has positive values.
Convolution efficiency highly improves when modulating the pulse, the positive and negative pulse samples to be found across each pulse increases robustness when attempting to decide whether there's pulse or just noise.
For instance Chirp pulses are a lot stronger.
7.- To measure BER : Use bytes, constellation points, coded symbols, but not bare bits
Measuring BER with bare bits, or more broadly speaking, using a random test signal with fixed statistical moments BER is constrained to whatever mean and var assinged to signal and/or mean var from noise in absence of with weak signal.
Rewording, testing for BER with bare bits counting, when weak or no signal BER is actually measuring the noise the signal was trying to avoid.
Roughly 50% of the received bits, regardless of signal or noise, the way you are attempting BER measurement, will always hit what are apparently correct bits : false positives.
To avoid these false positives following I show how to measure BER against expected caracters.
N=1024
..
nsync=64 % length sync header
x=[ones(1,nsync) randi([0 M-1],1,N-nsync)]; % signal : data
Now x is 1024 and the initial 64 bits are for syncing only, leaving N-sync for message.
Let's check BER against let's say L1 the expected sequence of bytes
xm=reshape(x([nsync+1:end]),[(N-nsync)/8 8])
L1=sum(repmat(2.^[7:-1:0],size(xm,1),1).*xm,2);
L1 is checked against Lrx generated with x3_8 the message part of x3 the demodulated symbols
8.- the upsampling downsampling didn't work
this downsampling on reception
dwn1 = rx_SIG(1:ov1:end);
was an attempt to sync received signal to the time stamps where pulse peaks are expected but it didn't not work.
Because the sampling times were not centered pamdemod didn't work either.
9.- Use sync header to calculate sampling interval
I only convolve the nsync (64) initial bits
rx2_sync=conv(pulse_half_Sine,rx_S([1:1:nsync*numel(pulse_half_Sine)]));
These pulses allow a reliable calculation of nT2 the sampling interval to check along the rest of the received frame.
I obtain nT2 with
[pks,locs]=findpeaks(abs(rx2_sync),'NPeaks',nsync,'MinPeakHeight',A(k)/2);
There's need for further conditioning but basically locs already has the necessary information to obtain nT2 .
10.- This is the graph obtained
when no signal BER = 1 and when signal strength high enough PAM signals show good `BER' ending to 0.
When refining A step, by this meaning making it smaller, one gets the following
BER testers are often plugged to base stations upon setup and left a few hours or even days recording, and such testers do not record bare bit errors, bytes, constellation points, and even frames are checked.
11.- BER/SNR BER/EbN0 not against signal only
BER is usually plotted against SNR (analog signals) or Eb/N0 (digital signals) not just against signal amplitude or signal power.
12.- The Communications Toolbox is an add-on
This toolbox adds the following support functions: pammod pamdemod genqammod genqamdemod, yes pammod and pamdemod use genqammod genqamdemod respectively.
These functions are not available unless the Communications Toolbox is installed.
for BER simulations try Simulink, there are already available BER examples.
I have a function file:
function dxdt=function3009(t,x)
% Initialize model vector with zeroes,
dxdt=zeros(5,1);
% Parameters
%% Rate values with many decimal places causing error:
%k1= 1*10^-6; % k1*alac*lacI -> LacI-alac
%k2 = 1*10^-13; % k3*lacI*gop -> LacI-g_op
%% Script runs fine with these instead
k1= 10; % k1*alac*lacI -> LacI-alac
k2 = 10; % k2*lacI*gop -> LacI-g_op
% Differential Equations:
% d[E]/dt
dxdt(1)= - k1*x(1)*x(3) + (k1^-1)*x(2);
% d[ER]/dt
dxdt(2)= k1*x(1)*x(3) - (k1^-1)*x(2);
% d[R]/dt
dxdt(3)= - k1*x(1)*x(3) + (k1^-1)*x(2) - k2*x(3)*x(4) + (k2^-1) * x(5);
% d[O]/dt
dxdt(4)= - k2*x(3)*x(4) + (k2^-1) * x(5);
% d[OR]/dt
dxdt(5)= k2*x(3)*x(4) - (k2^-1) * x(5);
%%%%%%%%%%%%%%%%%%%%%%%%%%%
and my script file:
% Settings
options = odeset('InitialStep',0.1,'MaxStep',0.1);
t_range= [0 10];
%% many decimal points, causes error:
%x_ini= [1*10^-4 0 2*10^-8 0 8.47*10^-12];
%% Runs fine without decimal places:
x_ini= [100 0 10 0 1];
% Simulation
[t,x]=ode45(#function3009,t_range,x_ini,options);
% Plot time series of all variables
subplot(1,3,1);
plot(t,x(:,4:5)); %plot gop and lac:gop
xlabel('Time');
ylabel('Concentration');
title('gop and LacI:gop');
legend('gop', 'lacI:gop');
subplot(1,3,2);
plot(t,x(:,2:3)); %plot lac and lac:alac
xlabel('Time');
ylabel('Concentration');
title('lacI and alac:LacI');
legend('alac:LacI','LacI');
subplot(1,3,3);
plot(t,x(:,1)); %plot alac
xlabel('Time');
ylabel('Concentration');
title('Alac');
When I run ODE45 with the numbers with many decimal places vs the whole numbers, I receive this error:
Error using horzcat Requested 5x212292600 (7.9GB) array exceeds maximum array size preference.
Creation of arrays greater than this limit may take a long time and cause MATLAB to become unresponsive.
See array size limit or preference panel for more information.
I have 5 DEGs, a time range of 10 with steps of 0.1 (therefore 100 total), so surely the total array size should be 500 regardless of input values? Why does using the input values with many decimal places increase the array size?
Thanks for any help/advice!
It looks like your ode becomes numerically stiff when you swap to the "problematic" values. I would suggest using a stiff solver, such as ode15s. If you replace that line:
[t,x]=ode45(#function3009,t_range,x_ini,options);
with that line:
[t,x]=ode15s(#function3009,t_range,x_ini,options);
It converges really quickly and gives the following results (I can't comment on whether they are correct or not):
For more details on solver, see Choose an ODE Solver in the documentation.
I'm writing a program on MATLAB that generates 13 waveforms of varying amplitude, duration, and frequency. Each waveform is repeated 5 times, which means I have 65 'trials' in total.
The total length of each trial = 1.5 ms. The sampling frequency = 4 kHz. I would like the wave to begin at 0.5 ms. Prior to the onset of the wave, and following its offset, I would like the amplitude to be zero (i.e. a 'flatline' prior to and following the wave).
I have created a 65x3 matrix where the columns denote the frequency ('hz'), amplitude ('a'), and duration (ms) of the 65 sine waves. Each row denotes a single wave.
I would like to use the information contained in this 65x3 matrix to generate 65 sine waves of amplitude 'a', frequency 'hz', and duration 'ms'. To be specific: each wave should be created using the parameters (hz,a,ms) specified in the nth row of the matrix. E.g. if row 1 = 100, 1, 50... this means I would like to generate a 100 Hz sine wave (amplitude = 1) lasting 50 ms.
I have attempted to construct a for loop to solve this problem. However, the loop returns a number of errors, and I'm not sure how to resolve them. I have adapted the code to the point where no errors are returned; however, my latest attempt seems to generate 65 waves of equal duration, when in fact the duration of each wave should be that which is stated in vector 'ms'.
Here is my latest, albeit newbie and still unsuccessful, attempt: (note that 'trials' represents the 65x3 matrix discussed above; mA = amplitude).
hz=trials(:,1); mA=trials(:,2); ms=trials(:,3);
trials_waves=zeros(65,500); % the max duration (= 500ms); unsure of this part?
for n = 1:size(order,1)
trials_waves = mA*sin(2*pi*hz*0:ms);
end
Apologies if the information provided is scarce. This is the first time I have asked a question on this website. I can provide more information if needed.
Thank you for your help.
Best,
H
Looks like you've got a good start, I'll try to help you get further towards your solution.
Make a Sine Wave
For starters, let's make a sine wave with variable rate, amplitude, and length.
Fs = 4e3; % sample rate of 4 kHz
Sr = 100; % example rate
Sa = 1; % amplitude
St = 10e-3; % signal duration is 10 ms
% To create a sine wave in MATLAB, I'm going to first create a vector of time,
% `t`, and then create the vector of sine wave samples.
N = St * Fs; % number of samples = duration times sample rate;
t = (1:N) * 1/Fs; % time increment is one over sample rate
% Now I can build my sine wave:
Wave = Sa * sin( 2 * pi * Sr * t );
figure; plot(t, Wave);
Note! This is barely enough time for a full wavelength, so be careful with slow rates and short time lengths.
Make many Sine Waves
To turn this into a loop, I need to index into vectors of input variables. Using my previous example:
Fs = 4e3; % sample rate of 4 kHz
Sr = [100 200 300]; % rates
Sa = [1 .8 .5]; % amplitudes
St = [10e-3 20e-3 25e-3]; % signal durations
nWaves = length(Sr);
N = max(St) * Fs; % number of samples = duration times sample rate;
t = (1:N) /Fs; % time increment is one over sample rate
% initialize the array
waves = zeros(nWaves, N);
for iWaves = 1:nWaves
% index into each variable
thisT = (1:St(iWaves) * Fs) * 1/Fs;
myWave = Sa(iWaves) * sin( 2 * pi * Sr(iWaves) * thisT );
waves(iWaves,1:length(myWave)) = myWave;
end
figure; plot(t, waves);
You still have one more piece, zero padding the front end of your signals, there's lots of ways to do it, one way would be to build the signal the way I've described and then concatenate an appropriate number of zeros to the front of your signal array. Feel free to ask a new question if you get stuck. Good luck!
I apologize in advance, if the title is confusing. Basically, i have a Audio-file, on which I perform a STFT every 50ms. My File is about 11 seconds long (10.8526s), which i have cut off from a soundtrack. Btw, i am not allowed to use the built-in function in Matlab for the STFT. I am aware it is much more easier. Anyway, after i run my code, every 50 ms a STFT is performed and the picture is being plotted.
Now i want to seperate it in 3 different plots. In the first plot i have the lower frequencies (0-300Hz), in the second plot medium frequencies(300-5kHz) and in the last plot i have high frequencies(5Khz-fs/2). fs=44100 --> Further explanations below in the code. How can i define now the areas?
%AUDIO-FILE
%______________________________________________________
[y,fs]=audioread('UnchainMyHeart.wav');
% audioread = Reads Audio file
% y = A vector, which contains the audio signal
% fs = sample rate
% 'UnchainMyHeart' = Audio file
%______________________________________________________
% Paramter for the real-time spectral-analysis
%______________________________________________________
NFA=2;
% Every second picture is being plotted
% Don't need every picture
t_seg=0.05;
%Length of the audio signal on which is a STFT performed
fftlen = 4096;
% Length of the FFT, frequency resolution
TPF= 300;
BPF= 5000;
HPF= 22050;
% Trying to define the frequencies areas
% Isn't working right now
LOW=((TPF*fftlen)/fs);
MEDIUM=((BPF*fftlen)/fs);
HIGH=((HPF*fftlen)/fs);
% Contains the number of FFT points in the frequency
%_______________________________________________________
segl =floor(t_seg*fs);
windowshift=segl/2;
window=hann(segl);
window=window.';
si=1;
% Start Index
ei=segl;
% End Index
AOS= length(y)/windowshift - 1;
f1=figure;
f=0:1:fftlen-1;
f=f/(fftlen-1)*fs;
Ya=zeros(1,fftlen);
n=0;
for m= 1:1:AOS
y_a = y(si:ei);
y_a= y_a.*window;
Ya=fft(y_a, fftlen);
n=n+1;
if n==1
Yres=abs(Ya);
else
Yres=Yres+abs(Ya);
end
if n==NFA
Yres=Yres/NFA;
n=0;
drawnow;
%Updates the graphical objects which are being plotted every 50ms
figure(f1);
plot(f(1:end/2), 20*log10(abs(Yres(1:end/2))));
ylim([-90 50]);
title('Spektrum of audio signal');
xlabel('f(Hz)');
ylabel('dB');
grid on;
end
si=si+windowshift;
% Updating Start Index
ei=ei+windowshift;
% Updating End index
end
I am not able to run you code as I do not have your audio file but I will try to explain conceptually, and use pseudo code.
Frequency brick-wall
If you just want to separate the frequencies for visual purposes you can just use brick-wall filters.
Perform an fft of the full signal. Define a frequency vector.
SigFD = fft(signal);
n = length(signal); % number of samples
fs = 44100; % sampling rate
deltaF = fs/n; % frequency resolution
F = [0:floor(n/2)-1, -(floor(n/2)):-1]*deltaF; % frequency vector
Slice the signal based on the frequency range that you want.
lowF = 0;
highF = 500;
part1Range = abs(F)>lowF&abs(F)<highF;
Fpart1 = F(part1Range);
Sig1FD = SigFD(part1Range);
Note that I am unable to test the code on your waveform so this should be considered more of pseudo code!
Here in this code i am doing a stft on my wav-file. There is no problem with that. At the beginning, i am defining my parameter, afterwards using my wav file and then applying the stft. Basically what i am doing is a real-time spectral analysis. Anyway my question is, how do i a frequency band? I want my signal to be separated in LOW/MEDIUM/HIGH. I want my vector to be saved, from 0-250 Hz in the LOW-Band, 250-5000 Hz in the MEDIUM-Band, 5-22.05k Hz in the HIGH-Band. I advise you, to try my code in Matlab, if you don't understand it. Just take any wav-file. Btw my signal is plotted in the variable "Yres". Any solution is appreciated!
NFA=2; % Number is used for plotting every 2nd picture
t_seg=0.05; % Length of segment in ms
fftlen = 4096;
% Lenght of "fft",because our segment contains 2205 points
[y,fs]=audioread('UnchainMyHeart.wav');
% audioread = functions reads WAV-file
% y = A vector which contains my audio signal
% fs = sample frequency (44100)
% 'UnchainMyHeart' = WAV-file
t=linspace(0,length(y)/fs,length(y));
% linspace = Creating time vector
% 0 = Start time
% length(y)/fs = End time
% length(y) = Number of samples in y
plot(t,y)
% plotting signal in the time domain
segl =floor(t_seg*fs);
% Applying fft function on the variable "segl"
windowshift=segl/2;
% Defining the size of the window, which goes to the next "segl"
window=hann(segl);
% hann function
window=window.';
si=1;
%Start index
ei=segl;
%End index
AOS= length(y)/windowshift - 1;
% AOS is the number of "segl" we use (About 433)
f1=figure;
% Opening new window
f=0:1:fftlen-1;
f=f/(fftlen-1)*fs;
% Defining frequency vector
Ya=zeros(1,fftlen);
plot(f,Ya),axis([0 fs -90 50])
grid on
n=0;
%start variable
for m= 1:1:AOS
y_a = y(si:ei);
y_a= y_a.*window;
Ya=fft(y_a, fftlen);
n=n+1;
if n==1
Yres=abs(Ya);
else
Yres=Yres+abs(Ya);
end
if n==NFA
Yres=Yres/NFA;
n=0;
drawnow;
%Tut die Grafikobjekte immer auf den neuesten Stand updaten
figure(f1);
plot(f(1:end/2), 20*log10(abs(Yres(1:end/2))));
ylim([-90 50]);
title('Spektrum eines Audiosignal');
xlabel('f(Hz)');
ylabel('dB');
grid on;
end
si=si+windowshift;
% Updating start index
ei=ei+windowshift;
% Updating end index
end
This may not be the best answer! But this may help you get started on something. You can use spectrogram() function from MATLAB's Signal Processing Toolbox.
Let's suppose you have an audio file named ''UnchainMyHeart.wav'(in your case) with one channel. The code goes as follows:
% Reading the audio file
[y1,fs] = audioread('UnchainMyHeart.wav');
% Parameters for STFT (or spectrogram)
windowDuration = 30e-3; overlapDuration = 15e-3;
windowLength = round(windowDuration*fs); % window length
overlapLength = round(overlapDuration*fs); % overlapping of windows
nfft = 1024;
% Executing STFT for the signal
[S1,F1,T1,P1] = spectrogram(x1,hanning(windowLength), ...
overlapLength, nfft, fs, 'yaxis');
S1 and P1 contain STFT and Power Spectrum Density(PSD) of the signal for a time interval of each section with a time interval whose estimations are contained in T1.
For your question, you are looking for F1 which is a vector of cyclical frequencies expressed in terms of sampling frequency, fs. For example: if you have a sampling frequency of 48 kHz (fs) and nfft of 1024, then you will have 513 [(1024/2) +1)] frequency values spaced by (fs/nfft). i.e. 46.875. So your frequency components will be 0, 46.875, 46.875*2, ..., 46.875*512. The maximum you will have is 24 kHz due to Nyquist criterion.
Now, you can easily write a simple routine specifying the ranges as you said. The same technique can be used in your code which is an implementation of stft. I would suggest using MATLAB's built-in function unless your problem requires an implementation. Hope this helps!
If needed, I can answer why the parameters for STFT are chosen as included in the code.