FFT / PWELCH Matlab define sampling frequency - matlab

I have a TXT-Doc https://www.mikrocontroller.net/attachment/428580/Probe_1.txt with analog values. I'm using FFT and Pwelch in Matlab to find the frequency of my analog signal. Theoreticly the frequency should be somewhere ~300 Hz. That's why i thought about an area of 0-500 Hz.
I tried fft:
>> load pr_1.txt;
>> Fs = 1000;
>> T = 1/Fs;
>> L = length(pr_1);
>> FFT = fft(pr_1);
>> P2 = abs(FFT/L);
>> P1 = P2(1:L/2+1);
>> P1(2:end-1) = 2*P1(2:end-1);
>> f = Fs*(0:(L/2))/L;
>> plot(f,20*log10(P1))
and pwelch:
>> len = 2050;
>> h = kaiser(len,4.53);
>> pwelch(pr_1,h,[],len,Fs)
Both is showing me the same answer: Peak at ~300 Hz.
But my question is how to I define the right sampling frequence Fs?
If i change Fs for example to Fs=10000 instead of Fs=1000 I'll get Peak Points at ~3000 Hz instead of 300 Hz. And if I change Fs = 500, the Peak results at 150 Hz. I have the problem to understand and define the right Fs.

Assuming your provided file was generated by some measurement device, you can take the 3rd line
# Aufnahmerate [Hz]: 9997.4286613483
as your sample rate Fs. This is a fixed rate which is defined by the capturing device, just as #Irreducible said. Therefore you can't randomly change it.
The header of the file tells you also more information: It says there are 100000 samples, which is true, and also if you multiply the timeinterval per sample (5th line) with the number of samples(100000, 2nd line), you get exactly the measurement duration (4th line). From this I assume, that these values are true.
For completeness/future reference: the top content of your file:
# 2019-08-26 15:38:49.661906
# Anzahl Messwerte: 100000
# Aufnahmerate [Hz]: 9997.4286613483
# Messdauer [s]: 10.002572
# Zeitintervall je Messpunkt [ms]: 0.10002572
2.820286226094503856e+00
2.820608226282290687e+00
2.820286226094503856e+00
2.820608226282290687e+00
2.820286226094503856e+00
2.820608226282290687e+00
2.820608226282290687e+00
2.820608226282290687e+00
2.819642225722452267e+00
2.820286226094503856e+00
2.820608226282290687e+00
2.819964225907891198e+00
2.820286226094503856e+00
2.819964225907891198e+00
...

Related

How to interpret dependency on order for 1/3-octave band filters in Matlab?

I am trying to obtain a third-octave band representation of the frequency content of an acoustic signal, obtained by numerical simulation. The signal is the following:
The code I use (you can reproduce it by replacing P and t with other signals):
P = PNL(:,3) ; % Acoustic pressure signal
t = timeWindow ; % Time array
T = t(end) - t(1) ; % Signal duration
fs = length(t)/T ; % = 98123 [Hz]
T0 = 1 ; % Reference duration of 1 [s]
filterOrder = 6 ;
allANSIFrequencies = getANSICenterFrequencies(octaveFilter('FilterOrder', filterOrder, 'Bandwidth', '1/3 octave', 'SampleRate', fs));
cf = allANSIFrequencies(19 : 50) ; % Restricting the frequency range to [15 Hz - 20000 Hz]
for k = 1 : length(cf)
octFilt = octaveFilter(cf(k), 'Bandwidth', '1/3 octave','SampleRate', fs, 'FilterOrder', filterOrder, 'Oversample', false);
y = octFilt(P);
Prms = sqrt((1/T0) * trapz(t, y.^2)) ; % Root mean square pressure level
LE(k) = 20 * log10(Prms/20e-6) ; % [db] Sound Exposure Level
end
semilogx(cf, LE)
grid on
xlabel('Frequency (Hz)') ;
ylabel('L_{E} (dB)') ;
legend('Order 2', 'Order 4', 'Order 6', 'Order 12')
The frequency content I would expect based on experimental data is a mix of the results at different orders: up to 1000 [Hz] the levels from order 6 are correct, while from 1000 [Hz] onwards, it's the order 2 that describes best the frequency content.
I obtain very different results depending on the filter order I am using. To a certain degree that's normal. Higher orders should provide a sharper response of the filter, but I fail to interpret these results.
The resolution of the signal under investigation should be high enough (98123 [Hz]). Any idea of what the issue could be?
Thank you in advance, I'd appreciate any insight on this!

Getting matrix dimension error while modulating audio waveform on matlab

I am getting the matrix dimension error for the following code. What I am trying to do below is modulation of an audio waveform but I could not get passed the error I specified. I have checked the length of the sample.wav and adjusted time axis(t) accordingly but I must have done something wrong. I appreciate if anyone could help. Thanks in advance!.
function [sm]= modulation(ss,fc,mtype)
ss= audioread('C:\Users\furka\Documents\MATLAB\sample.wav'); %audio waveform to be modulated is loaded.
plot(ss)
length(ss)
t=linspace(0,3e6,3161538);
fc= input('Carrier Frequency='); %carrier frequency will be determined by the user
mtype= menu('Modulation type?','dsb','dsbsc','ssb','fm'); %modulation type will be determined by the user
%fs=44100; %sampling frequency is determined for common audio waveform.(44.1kHz)
%t= 0:1/fs:(2e-5)-1/fs;
if mtype==1
ka= 0.7;
sm= ss.*(1+ka*cos(2*pi*fc*t));
plot(t,sm)
elseif mtype==2 %if doublesideband suppress carrier is selected the statements below will be carried out.
y = ss.*cos(2*pi*fc*t);
plot(y)
% sm = fftshift(fft(abs(y)));
% frequency_axis= (-fs/2):(fs/length(sm)):(fs/2-fs/length(sm));
%plot(frequency_axis,sm)
elseif mtype==3
sm=0.5*[ss.*cos(2*pi*fc*t)-hilbert(ss).*sin(2*pi*fc*t)];
plot(t,sm)
elseif mtype==4
kf=0.7; %frequency sensitivity.
sm= cos(2*pi*fc*t+2*pi*kf*int(ss,t,0,t));
plot(t,sm)
end
end
I can't access the link provided for the sound file but a time length of 3e6 seconds seems like a really long sound. I figure that's something around 30 days long.
Using the handel.mat example provided by MathWorks I get this.
load handel.mat
audiowrite('sample.wav', y, Fs);
[ss, Fs] = audioread('sample.wav');
t = linspace(0, length(ss) / Fs, length(ss));
t = t'; % this is important to match ss <-- this is your matrix dimension error I think
fc = 2000;
ka = 0.7
sm = ss .* (1 + ka * cos(2 * pi * fc * t));
The error of mismatched dimensions comes from linspace output being a row vector and audioread output being a column vector. Transpose one or the other. In my case: t = t'

How to make sound signal length the same in MATLAB?

I found this speech recognition code that I downloaded from a blog. It works fine, it asks to record sounds to create a dataset and then you have to call a function to train the system using neural networks.
I want to use this code to train using my dataset of 20 words that I want to recognise.
Problem:
I have a dataset of 800 files for twenty words i.e. 40 recordings from different people for each word. I used Windows sound recorder to collect the files.
The problem is that in the code is that the size of the input file is set to ALWAYS be 8000, my dataset on the other hand is not constant, some files are 2 seconds long, some are 3 that means there'll be different number of samples in each file.
If the samples per input signal variate it'll probably generate errors.
I want to use my files to train the system.
How do I do that?
Code:
clc;clear all;
load('voicetrainfinal.mat');
Fs=8000;
for l=1:20
clear y1 y2 y3;
display('record voice');
pause();
x=wavrecord(Fs,Fs); % wavrecord(n,Fs) records n samples at a sampling rate of Fs
maxval = max(x);
if maxval<0.04
display('Threshold value is too large!');
end
t=0.04;
j=1;
for i=1:8000
if(abs(x(i))>t)
y1(j)=x(i);
j=j+1;
end
end
y2=y1/(max(abs(y1)));
y3=[y2,zeros(1,3120-length(y2))];
y=filter([1 -0.9],1,y3');%high pass filter to boost the high frequency components
%%frame blocking
blocklen=240;%30ms block
overlap=80;
block(1,:)=y(1:240);
for i=1:18
block(i+1,:)=y(i*160:(i*160+blocklen-1));
end
w=hamming(blocklen);
for i=1:19
a=xcorr((block(i,:).*w'),12);%finding auto correlation from lag -12 to 12
for j=1:12
auto(j,:)=fliplr(a(j+1:j+12));%forming autocorrelation matrix from lag 0 to 11
end
z=fliplr(a(1:12));%forming a column matrix of autocorrelations for lags 1 to 12
alpha=pinv(auto)*z';
lpc(:,i)=alpha;
end
wavplay(x,Fs);
X1=reshape(lpc,1,228);
a1=sigmoid(Theta1*[1;X1']);
h=sigmoid(Theta2*[1;a1]);
m=max(h);
p1=find(h==m);
if(p1==10)
P=0
else
P=p1
end
end
In your code you have:
Fs=8000;
wavrecord(n,Fs) % records n samples at a sampling rate Fs
for i=1:8000
if(abs(x(i))>t)
y1(j)=x(i);
j=j+1;
end
end
It seems that instead of recording you are going to import your sound file (here for a .wave file):
[y, Fs] = wavread(filename);
Instead of hardcoding the 8000value you can read the length of your file:
n = length(y);
and then just use that n variable in the for loop:
for i=1:n
if(abs(x(i))>t)
y1(j)=x(i);
j=j+1;
end
end
The rest of the code seems to be independent of that 8000 value.
If you are worried that having non-constant file length. Compute n_max, the maximum length of all the audio recordings you have. And for recording shorter than n_max samples pad them with zeros so as to make them all n_max long.
n_max = 0;
for file = ["file1" "file2" ... "filen"]
[y, Fs] = wavread(filename);
n_max = max(n_max,length(y));
end
Then each time you process a sound vector you can pad it with 0 (harmless for you, because 0 means no sound) like so:
y = [y, zeros(1, n_max - length(y))];
n=noOfFiles
for k=1:n
M(k,1:length(filedata{k})) = filedata{k}
end
:P

MATLAB "Index out of bounds" Error

I have a project to make FIR filter coefficients but when in process of Minimum-Order Lowpass Filter there is error which
I have no idea what that means and which part I need to repair:
function [ output_args ] = FIR_FilterCoeff()
N = 100; % FIR filter order
Fp = 20e3; % 20 kHz passband-edge frequency
Fp = 20e3; % 20 kHz passband-edge frequency
Fs = 96e3; % 96 kHz sampling frequency
Rp = 0.00057565; % Corresponds to 0.01 dB peak-to-peak ripple
Rst = 1e-4; % Corresponds to 80 dB stopband attenuation
NUM = firceqrip (N,Fp/(Fs/2),[Rp Rst],'passedge');
N2= 200; % change filter order to 200
NUM200 = firceqrip(N2,Fp/(Fs/2),[Rp Rst],'passedge');
Fst = 23e3; % transition width = Fst-Fp
NUM_MIN = firgr('minorder',[0,Fp/(Fs/2),Fst(Fs/2),1],[ 1 1 0 0 ],[Rp Rst]);
Your error lies in Fst(Fs/2) on your last line. Fst is a vector of length 1. It has 1 value 23e3. Round brackets, (), in MATLAB directly after a variable are used for indexing variables.
When you type Fst(Fs/2) you are attempting to access the 48000 element in Fst but it does not exist so MATLAB throws an error. I think you may have meant this to be
Fst/(Fs/2)
or (possibly)
Fst*(Fs/2)
The * sign is needed to perform multiplication in MATLAB. It is not good enough to simply use round brackets, (), as they have another purpose, Matrix Indexing.

'findpeaks' function on matlab outputs error. the error is 'too many output arguments'?

well first thanks in advance.
i am a machine learning person.
for a project, i have created a matlab function which returns several features of a signal in frequency domain.
the function returns signal's energy, sum of fourier coefficients, entropy, pwr_at_DC, power at peak frequency, and peak freq/dominant frequency.
the error states 'two many output arguments'!
code is this...
%signal = [120 111 117 109 94 104 125 161]; %for example consider this discrete signal.
%the function returns Singal's energy, sum of fourier coefficients, entropy,
%pwr_at_DC, power at peak frq, and peak freq.
function [signalFeatures] = SigFreqAnalysis(signal)
NFFT = length(signal); %leangth of the signal
signal = signal - mean(signal); %remove DC comp (avoid peak at 0Freq.
FT = fft(signal,NFFT); %fourier transform n point
sEnergy = sum(abs(FT).^2)/NFFT; %spectral energy
SumCoeff = sum(abs(FT)); %total of all NFFT coefficients!
%[P,F] = periodogram(signal,[],NFFT,'power');
[P,F] = pwelch(signal,ones(NFFT,1),0,NFFT,'power'); %[P,F] - PSD of the signal
%P1=real(P1);
%Steps for Entropy: calc PSD ---> normalize p ---> entropy = ??(P)log2(P);
Pn=P/norm(P); log2Pn = log2(Pn + 1e-12);
Entropy = -sum(Pn.*log2Pn)/log2(length(Pn));
PdBW = 10*log10(P); pwr_at_DC = PdBW(F==0); % power in dBW
%the most important dominant frquency! ! !
[pks_dBW,locs] = findpeaks(PdBW,'NPEAKS',1,'SORTSTR','descend'); %peak/dominant!
%findpeak returns empty vector if no freq found!
if isempty(pks_dBW)
pks_dBW=0; pkFrq = 0; %if pks_dbs is 0 findpeak returns empty matrix;
else
pkFrq = F(locs); %this is the dominant/peak frequency of X axes!!
end
signalFeatures = [sEnergy SumCoeff Entropy pwr_at_DC pks_dBW pkFrq];
%return this vector.
end
error ---> 'too many output arguments' in findpeak function!
can anyone help me resolve this error!
thanks,
Adesh Shah
Your code that calls the function should look like this:
signal = [120 111 117 109 94 104 125 161]
a = SigFreqAnalysis(signal)
but you are probably calling it this way
[a b] = SigFreqAnalysis(signal)
Hence, too many outputs