Equal Loudness Curves (ISO226)
function [spl, freq] = iso226(phon);
%
% Generates an Equal Loudness Contour as described in ISO 226
%
% Usage: [SPL FREQ] = ISO226(PHON);
%
% PHON is the phon value in dB SPL that you want the equal
% loudness curve to represent. (1phon = 1dB @ 1kHz)
% SPL is the Sound Pressure Level amplitude returned for
% each of the 29 frequencies evaluated by ISO226.
% FREQ is the returned vector of frequencies that ISO226
% evaluates to generate the contour.
%
% Desc: This function will return the equal loudness contour for
% your desired phon level. The frequencies evaulated in this
% function only span from 20Hz - 12.5kHz, and only 29 selective
% frequencies are covered. This is the limitation of the ISO
% standard.
%
% In addition the valid phon range should be 0 - 90 dB SPL.
% Values outside this range do not have experimental values
% and their contours should be treated as inaccurate.
%
% If more samples are required you should be able to easily
% interpolate these values using spline().
%
% Author: sparafucile17 03/01/05
% /---------------------------------------\
%%%%%%%%%%%%%%%%% TABLES FROM ISO226 %%%%%%%%%%%%%%%%%
% \---------------------------------------/
f = [20 25 31.5 40 50 63 80 100 125 160 200 250 315 400 500 630 800 ...
1000 1250 1600 2000 2500 3150 4000 5000 6300 8000 10000 12500];
af = [0.532 0.506 0.480 0.455 0.432 0.409 0.387 0.367 0.349 0.330 0.315 ...
0.301 0.288 0.276 0.267 0.259 0.253 0.250 0.246 0.244 0.243 0.243 ...
0.243 0.242 0.242 0.245 0.254 0.271 0.301];
Lu = [-31.6 -27.2 -23.0 -19.1 -15.9 -13.0 -10.3 -8.1 -6.2 -4.5 -3.1 ...
-2.0 -1.1 -0.4 0.0 0.3 0.5 0.0 -2.7 -4.1 -1.0 1.7 ...
2.5 1.2 -2.1 -7.1 -11.2 -10.7 -3.1];
Tf = [ 78.5 68.7 59.5 51.1 44.0 37.5 31.5 26.5 22.1 17.9 14.4 ...
11.4 8.6 6.2 4.4 3.0 2.2 2.4 3.5 1.7 -1.3 -4.2 ...
-6.0 -5.4 -1.5 6.0 12.6 13.9 12.3];
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Error Trapping
if((phon < 0) | (phon > 90))
disp('Phon value out of bounds!')
spl = 0;
freq = 0;
else
%Setup user-defined values for equation
Ln = phon;
%Deriving sound pressure level from loudness level (iso226 sect 4.1)
Af=4.47E-3 * (10.^(0.025*Ln) - 1.15) + (0.4*10.^(((Tf+Lu)/10)-9 )).^af;
Lp=((10./af).*log10(Af)) - Lu + 94;
%Return user data
spl = Lp;
freq = f;
end
ML Estimation of Several Frequencies Using the Nonuniform FFT
function st = Demo
% Author: J. Selva.
% Date: July 2011.
% Version: 0.
st = [];
n = input('Options: 1 perform single estimation, 2 estimate RMS error: ');
switch n
case 1
st = TestSingleTrial;
case 2
TestRMSError;
end
function st = TestSingleTrial
%Scenario with 5 frequencies.
M = 2048;
SNRInSpecdB = 27; %Signal-to-noise ratio after correlation.
Nf = 5;
df = 1/M; %Minimum separation among frequencies.
MaxAmp = 1; %Maximum amplitude.
PFA = 10.^-5;
nVar = M*MaxAmp^2/10^(SNRInSpecdB/10);
nThres = NoiseThres(M,nVar,PFA);
MinAmp = 2*nThres/M;
[vf,va] = RandomFreqAndAmpVectors(Nf,df,MinAmp,MaxAmp);
y = DataRealization(vf,va,M,nVar);
p = Preprocessing(y,nVar,PFA);
disp('True frequencies: ')
disp(vf)
disp('True amplitudes: ')
disp(va)
disp(['Post-correlation Signal-to-noise ratio: ',...
num2str(SNRInSpecdB),' dB'])
s = input('To compute ML estimate, use (S)erial or (M)anual method? ','s');
if strcmp(lower(s),'s')
st = MethodSerial1(p);
else
st = MethodManual1(p);
end
disp('ML frequency estimates: ')
disp(st.Freqs)
disp('ML amplitude estimates: ')
disp(st.Amps)
function TestRMSError
%Estimates the RMS error and computes the Cramer-Rao bounds.
format compact
format short g
M = 2048;
SNRInSpecdB = 27;
Nf = 5;
df = 1/M;
MaxAmp = 1;
PFA = 10.^-5;
nVar = M*MaxAmp^2/10^(SNRInSpecdB/10);
nThres = NoiseThres(M,nVar,PFA);
MinAmp = 2*nThres/M;
[vf,va] = RandomFreqAndAmpVectors(Nf,df,MinAmp,MaxAmp);
crb = CRBBound(vf,va,M,nVar);
Ntr = 0;
S2 = zeros(Nf,1);
for k = 1:1e5
y = DataRealization(vf,va,M,nVar);
p = Preprocessing(y,nVar,PFA);
st = MethodSerial1(p);
if length(st.Freqs) == 5
Ntr = Ntr + 1;
S2 = S2 + (vf-st.Freqs).^2;
end
if mod(k,100) == 0
disp(['Number or trials: ', num2str(k)])
disp([' Frequencies: ' num2str(vf.')])
disp(['Deviation CRB bounds (dB): ' num2str(20*log10(crb.'))])
disp([' RMS errors (dB): ' num2str(10*log10(S2(:).'/Ntr))])
disp(' ');
end
end
function [vf,va] = RandomFreqAndAmpVectors(Nf,MinFreqSep,MinAmp,MaxAmp)
%Constructs random vectors of frequencies and amplitudes. The module of the largest
%amplitude is MaxAmp. There are no amplitudes with module below MinAmp, and the minimum
%separation among frequencies is MinFreqSep.
vf = sort(rand(Nf,1));
vf = vf + MinFreqSep*(cumsum(ones(Nf,1))-1);
vf = vf/(1+(Nf-1)*MinFreqSep) - 0.5;
pr = rand(Nf,1);
ind = floor(rand(1)/Nf)+1;
pr(ind) = 1;
va = (MinAmp+(MaxAmp-MinAmp)*pr) .* exp(1i*2*pi*rand(Nf,1));
function y = DataRealization(vf,a,M,nVar)
m1 = FirstIndex(M);
y = exp(1i*2*pi*(m1:m1+M-1).'*vf(:).')*a(:)+randn(M,2)*[1 ; 1i]*sqrt(nVar/2);
function p = Preprocessing(y,nVar,PFA)
%Performs the preprocessing. Fundamentally this consists in computing the FFT inside
%"Correlation.m".
%The input parameters are
%
% y: Data vector.
% nVar: Noise variance estimate.
% PFA: Probability of seeing a frequency when there isn't any. Usually a very low value
% like 1e-5.
p = [];
p.M = length(y);
p.nVar = nVar;
p.PFA = PFA;
p.nThres = NoiseThres(p.M,p.nVar,p.PFA); %Noise threshold.
icf = Correlation(y,p.nThres); %Struct with data for interpolating the correlation.
p.cfd = Cost(real(y(:)'*y(:)),icf); %Struct with data for computing the ML cost function ...
%and its derivatives.
p.freqThres = 1/(10*p.M); %If two frequencies differ in less than ...
%freqThres in the iterative search, then one of them is
%discarded. This prevents ill-conditioning.
p.freqStopThres = 1/(p.M*1e4); %Threshold for stopping the ML cost function minimization.
function st = MethodSerial1(p)
%Adds frequencies and computes ML estimates sequentially.
vfEst = [];
ModifiedEstimation = logical(1);
while ModifiedEstimation
[vf1,va1] = Correlation(p.cfd.icf,'gridMainLocalMaxima',vfEst);
ModifiedEstimation = ~isempty(vf1);
if ModifiedEstimation
vfEst(end+1) = vf1(1);
[listv,listLv,listCL,ErrRatio] = LookForMinimum(p.cfd,vfEst,...
10.^-8,p.freqThres,p.freqStopThres);
vfEst = sort(listv(:,end));
end
end
st = Report(p,vfEst);
function st = MethodManual1(p,varargin)
%Allows the user to set the initial frequency estimates on a plot.
if nargin == 1
vfEst = [];
else
vfEst = varargin{1};
end
vfEst = vfEst(:);
figure
subplot(2,1,1)
Correlation(p.cfd.icf,'PlotPeriodogramFit',vfEst);
yl = get(gca,'YLim');
subplot(2,1,2)
Correlation(p.cfd.icf,'PlotPeriodogramFitError',vfEst);
while 1
pr1 = input('A/a -> Add freq., D/d -> Delete freq, X/x -> exit: ','s');
switch lower(pr1)
case 'a'
[f1,pr] = ginput(1);
vfEst = sort([vfEst; f1]);
[listv,listLv,listCL,ErrRatio] = LookForMinimum(p.cfd,vfEst,10.^-8,...
p.freqThres,p.freqStopThres);
vfEst = sort(listv(:,end));
subplot(2,1,1)
Correlation(p.cfd.icf,'PlotPeriodogramFit',vfEst);
subplot(2,1,2)
Correlation(p.cfd.icf,'PlotPeriodogramFitError',vfEst);
case 'd'
[f1,pr] = ginput(1);
[pr,ind] = min(abs(f1-vfEst));
vfEst(ind) = [];
subplot(2,1,1)
Correlation(p.cfd.icf,'PlotPeriodogramFit',vfEst);
subplot(2,1,2)
Correlation(p.cfd.icf,'PlotPeriodogramFitError',vfEst);
case 'x'
st = Report(p,vfEst);
return
end
end
function thres = NoiseThres(M,nVar,PFA)
%Computes the noise threshold. The method will discard any correlation local maximum below
%this threshold.
thres = sqrt((M*nVar/2)*icdf('chi2',(1-PFA)^(1/M),2));
function m1 = FirstIndex(M)
m1 = -ceil(M/2);
function varargout = Correlation(varargin)
%Computes the correlation value and its derivatives by calling "Barycentric". It does
%other things like plotting.
if ~isstruct(varargin{1})
st = [];
temp = {[],[],10.^-15,1.5};
[temp{1:nargin}] = deal(varargin{:});
[a,st.nThres,epsilon,OvFMin] = deal(temp{:});
a = a(:).';
st.M = length(a);
st.K = 2^nextpow2(st.M*OvFMin);
st.bary = Barycentric(0,SampleFourierCorrelation1DVer1(a,st.K),...
-2*FirstIndex(st.M),1/st.K,whatP(1/st.K,-2*FirstIndex(st.M),epsilon));
st.IndActive = find(abs(st.bary.a) > st.nThres);
st.IndActive = unique([st.IndActive-1,st.IndActive,st.IndActive+1]);
if st.IndActive(1) == 0
st.IndActive(1) = [];
end
if st.IndActive(end) == st.K+1
st.IndActive(end) = [];
end
st.aTActive = st.bary.a(st.IndActive);
st.vfActive = centreFreq((st.IndActive-1)/st.K);
varargout = {st};
return
end
[st,msg] = deal(varargin{1:2});
switch msg
case 'value'
varargout = {Barycentric(st.bary,varargin{3:end})};
case 'gridValueInRange'
[ind1,ind2] = deal(varargin{3:4});
varargout = {st.bary.a(mod(ind1:ind2,st.K)+1)};
case 'ampEstimates'
vf = varargin{3};
if length(vf) == 0
varargout = {[]};
end
varargout = {RegGeoSum(st.M,vf,vf,0,0) \ Barycentric(st.bary,vf)};
case 'gridValue'
lInd = varargin{3};
if nargin == 4
vf = varargin{4};
else
vf = [];
end
if isempty(vf)
varargout = {st.bary.a(mod(lInd,st.K)+1)};
else
vf1 = centreFreq(lInd/st.K);
VRaa = RegGeoSum(st.M,vf,vf,0,0);
VRa1a = RegGeoSum(st.M,vf1,vf,0,0);
pr = VRa1a*(VRaa\Barycentric(st.bary,vf));
pr = reshape(pr,size(lInd));
varargout = {st.bary.a(mod(lInd,st.K)+1)-pr};
end
case 'gridFit'
lInd = varargin{3};
if nargin == 4
vf = varargin{4};
else
vf = [];
end
if isempty(vf)
varargout = {zeros(size(lInd))};
else
vf1 = centreFreq(lInd/st.K);
VRaa = RegGeoSum(st.M,vf,vf,0,0);
VRa1a = RegGeoSum(st.M,vf1,vf,0,0);
pr = VRa1a*(VRaa\Barycentric(st.bary,vf));
pr = reshape(pr,size(lInd));
varargout = {pr};
end
case 'plotErrorIndB'
if nargin == 2
vf = [];
else
vf = varargin{3};
end
s = 20*log10(abs(Correlation(st,'gridValue',0:st.K-1,vf)));
gf = centreFreq((0:st.K-1)/st.K);
[gf,ord] = sort(gf);
s = s(ord);
plot(gf,s,[-0.5,0.5],20*log10(abs(st.nThres)*[1,1]))
Ms = max(s);
set(gca,'YLim',[Ms-50,Ms+10])
xlabel('Frequency (f)')
ylabel('Error spectrum (dB)')
grid on
varargout = {};
case 'PlotPeriodogramFit'
vfEst = varargin{3};
if isempty(vfEst)
s0 = 20*log10(abs(Correlation(st,'gridValue',0:st.K-1)));
gf = centreFreq((0:st.K-1)/st.K);
[gf,ord] = sort(gf);
s0 = s0(ord);
plot(gf,s0)
hold on
nt = 20*log10(abs(st.nThres));
plot([-0.5,0.5],nt([1,1]).',...
'LineWidth',2,'LineStyle','--','Color',[1 0 0])
hold off
text(-0.49,nt+2,'Noise threshold')
xlabel('Frequency (f)')
ylabel('Amplitude (dB)')
title('Periodogram data, fit, and est. frequencies (stems)')
return
end
vaEst = Correlation(st,'ampEstimates',vfEst);
stem(vfEst,20*log10(st.M*abs(vaEst)),'g')
hold on
s0 = 20*log10(abs(Correlation(st,'gridValue',0:st.K-1)));
gf = centreFreq((0:st.K-1)/st.K);
[gf,ord] = sort(gf);
s0 = s0(ord);
plot(gf,s0,'b')
hold on
nt = 20*log10(abs(st.nThres));
plot([-0.5,0.5],nt([1,1]).',...
'LineWidth',2,'LineStyle','--','Color',[1 0 0])
s1 = 20*log10(abs(Correlation(st,'gridFit',0:st.K-1,vfEst)));
s1 = s1(ord);
plot(gf,s1,'r')
Ms = max(s0);
set(gca,'YLim',[Ms-50,Ms+10])
xlabel('Frequency (f)')
ylabel('Amplitude (dB)')
title('Periodogram fit')
hold off
varargout = {};
case 'PlotPeriodogramFitError'
if nargin == 2
vfEst = [];
else
vfEst = varargin{3};
end
vaEst = Correlation(st,'ampEstimates',vfEst);
s0 = 20*log10(abs(Correlation(st,'gridValue',0:st.K-1,vfEst)));
gf = centreFreq((0:st.K-1)/st.K);
[gf,ord] = sort(gf);
s0 = s0(ord);
nt = 20*log10(abs(st.nThres));
plot(gf,s0)
hold on
plot([-0.5,0.5],nt([1,1]).',...
'LineWidth',2,'LineStyle','--','Color',[1 0 0])
hold off
Ms = max(s0);
set(gca,'YLim',[Ms-50,Ms+10])
xlabel('Frequency (f)')
ylabel('Amplitude (dB)')
title('Periodogram error')
varargout = {};
case 'gridValueGivenAmps'
[lInd,vf,aEst] = deal(varargin{3:5});
vf1 = centreFreq(lInd/st.K);
VRa1a = RegGeoSum(st.M,vf1,vf,0,0);
pr1 = st.bary.a(mod(lInd,st.K)+1);
pr1 = reshape(pr1,size(lInd));
pr2 = VRa1a*aEst;
pr2 = reshape(pr2,size(lInd));
varargout = {pr1-pr2};
case 'gridLocalMaxima'
if nargin == 2
pr = [-2,-1,0].';
pr = abs(st.bary.a(mod(st.IndActive([1;1;1],:) + ...
pr(:,ones(1,length(st.IndActive))),st.K)+1));
pr = pr(1,:)<=pr(2,:) & pr(3,:)<=pr(2,:);
vf = st.vfActive(pr);
va = st.aTActive(pr);
varargout = {vf,va};
return
end
vf = varargin{3};
if length(vf) == 0
[varargout{1:2}] = Correlation(st,'gridLocalMaxima');
return
end
amp = Correlation(st,'ampEstimates',vf);
tmp = abs(Correlation(st,...
'gridValueGivenAmps',st.IndActive-1,vf,amp)) >= st.nThres;
ind = st.IndActive(tmp);
pr = [-2,-1,0].';
ind1 = ind([1,1,1].',:) + pr(:,ones(1,length(ind)));
pr = abs(Correlation(st,'gridValueGivenAmps',ind1,vf,amp));
pr = pr(1,:)<=pr(2,:) & pr(3,:)<=pr(2,:);
ind = ind(pr)-1;
if isempty(ind)
varargout = {[],[]};
else
varargout = {centreFreq(ind/st.K),Correlation(st,...
'gridValueGivenAmps',ind,vf,amp)};
end
case 'gridMainLocalMaxima'
[vf,va] = Correlation(st,'gridLocalMaxima',varargin{3:end});
if length(vf) == 0
varargout = {[],[]};
return
end
[varargout{1:2}] = selectLocalMaximaVer3(vf,va,st.nThres,st.M);
case 'gridMaximum'
pr = Correlation(st,'gridValue',0:st.K-1,varargin{3:end});
[ma,ind] = max(abs(pr));
varargout = {(ind-1)/st.K,ma};
end
function tab = SampleFourierCorrelation1DVer1(a,K)
M = length(a);
m1 = FirstIndex(M);
a = a(:).';
tab = fft([a(-m1+1:end),zeros(1,K-M),a(1:-m1)]);
function out = centreFreq(f)
out = f + ceil(-0.5-f);
function P = whatP(T,B,epsilon)
P = ceil(acsch(epsilon)/(pi*(1-B*T)));
function d = dist(x,y)
if x<y
d = min([y-x,x+1-y]);
else
d = min([x-y,y+1-x]);
end
function v = sincMask(x,y,M)
v = zeros(size(x));
for k = 1:length(x)
x1 = max([dist(x(k),y)-1/(2*M),0]);
v(k) = 1/max([M*sin(pi*x1),1]);
end
function v = slBoundVer2(x,vam,vfe,nThres,M1)
vam = vam(:);
vfe = vfe(:);
sll = sincMask(vfe,x,M1).'*vam;
v = max([sll+nThres,1.1*sll]);
function varargout = selectLocalMaximaVer3(vf,va,nThres,M)
va1 = abs(va(:));
[pr,ord] = sort(va1);
ord = flipud(ord);
vf1 = vf(ord);
va1 = va1(ord);
n1 = length(va1);
if va1(1) < nThres
varargout = {[],[]};
return
end
va2 = va1(1);
va2Abs = va1(1);
vf2 = vf1(1);
for n=2:n1
if va1(n)<nThres
continue
end
if va1(n) < slBoundVer2(vf1(n),va2Abs,vf2,nThres,M)
continue
end
vf2(end+1) = vf1(n);
va2(end+1) = va1(n);
va2Abs(end+1) = abs(va(ord(n)));
end
varargout = {vf2,va2};
function out = Barycentric(varargin)
%Performs barycentric interpolation using the method in [Bary].
if ~isstruct(varargin{1})
st = [];
[st.n0,st.a,st.B,st.T,st.P] = deal(varargin{:});
st.N = length(st.a);
st.alpha = baryWeights(st.T,st.B,st.P);
st.alpha = st.alpha([1:st.P,st.P+2:end,st.P+1]);
st.vt = (-st.P:st.P)*st.T;
st.vt = st.vt([1:st.P,st.P+2:end,st.P+1]);
out = st;
else
[st,v] = deal(varargin{1:2});
if nargin == 3
nd = varargin{3};
else
nd = 0;
end
v = v(:);
Nv = numel(v);
n = floor(v/st.T+0.5);
u = v - n*st.T;
n1 = n - st.n0;
pr = [-st.P:-1,1:st.P,0];
da = st.a(mod(n1(:,ones(1,2*st.P+1)) + pr(ones(Nv,1),:),st.N)+1);
out = DerBarycentricInterp3Vec(st.alpha,da,st.vt,u,nd);
end
function w = baryWeights(T,B,P)
vt = (-P:P)*T;
g = APPulse(vt,1/T-B,T*(P+1));
gam = gamma(vt/T+P+1) .* gamma(-vt/T+P+1) .* g;
N = length(vt);
LD = ones(1,N);
for k = 1:N
LD(k) = prod(vt(k)-vt(1:k-1))* prod(vt(k)-vt(k+1:N));
end
w = gam ./ LD;
w = w / max(abs(w));
function v = APPulse(t,B,TSL)
v = real(sinc(B*sqrt(t.^2-TSL^2)))/real(sinc(1i*pi*B*TSL));
function out = DerBarycentricInterp3Vec(alpha,zL,t,tauL,nd)
NtauL = size(tauL,1);
LBtau = 200; %Block size for vectorized processing. Change this to adjust the memory
%usage.
NBlock = 1+floor(NtauL/LBtau);
t = t(:).';
Nt = length(t);
out = zeros(NtauL,nd+1);
for r = 0:NBlock-1
ind1 = 1+r*LBtau;
ind2 = min([(r+1)*LBtau,NtauL]);
Ntau = ind2-ind1+1;
z = zL(ind1:ind2,:);
tau = tauL(ind1:ind2);
vD = zeros(Ntau,1);
LF = [1,zeros(1,Nt-1)];
LF = LF(ones(Ntau,1),:);
for k = 1:Nt-1
vD = vD .* (tau-t(k))+alpha(k)*LF(:,k);
LF(:,k+1) = LF(:,k) .* (tau-t(k));
end
vD = vD .* (tau-t(Nt)) + alpha(Nt) * LF(:,Nt);
for kd = 0:nd
pr = z(:,end); z1 = z-pr(:,ones(1,Nt)); cN = zeros(Ntau,1);
for k = 1:Nt-1
cN = cN .* (tau-t(k)) + z1(:,k) .* alpha(k) .* LF(:,k);
end
cN = cN ./ vD;
ztau = z(:,end)+(tau-t(end)) .* cN;
out(ind1:ind2,kd+1) = ztau;
if kd < nd
pr1 = ztau;
pr1 = z(:,1:end-1) - pr1(:,ones(1,Nt-1));
pr2 = t(1:end-1);
pr2 = pr2(ones(Ntau,1),:)-tau(:,ones(1,Nt-1));
z = [pr1 ./ pr2, cN] * (kd+1);
end
end
end
function varargout = Cost(varargin)
%Computes the ML cost function differentials by calling "Correlation" and "RegGeoSum".
if ~isstruct(varargin{1})
st = [];
[st.EnergyRyy,st.icf] = deal(varargin{:});
varargout = {st};
return
end
st = varargin{1};
if nargin > 2
vf = varargin{3};
else
vf = [];
end
switch varargin{2}
case 'value'
vf = varargin{3};
Rss = RegGeoSum(st.icf.M,vf,vf,0,0);
Rsd = RegGeoSum(st.icf.M,vf,vf,0,1);
Rdd = RegGeoSum(st.icf.M,vf,vf,1,1);
pr = Correlation(st.icf,'value',vf,1);
Rsy = pr(:,1);
Rdy = pr(:,2);
pr = Rss\[Rsy,Rsd];
MRsy = pr(:,1);
MRsd = pr(:,2:end);
varargout = {st.EnergyRyy-RealTrace(Rsy',MRsy),-2*RealDiag(MRsy,Rdy'-MRsy'*Rsd),...
2*RealHadamard((Rdd'-Rsd'*MRsd).',MRsy*MRsy')};
case 'value0'
if length(vf) == 0
varargout = {st.EnergyRyy};
return
end
vf = varargin{3};
Rss = RegGeoSum(st.icf.M,vf,vf,0,0);
Rsy = Correlation(st.icf,'value',vf);
[varargout{1}] = st.EnergyRyy-RealTrace(Rsy',Rss\Rsy);
end
function v = RealHadamard(A,B)
v = real(A).*real(B)-imag(A).*imag(B);
function C = RealDiag(A,B)
% Same as real(diag(A*B)) but using less flops.
C = RealHadamard(A.',B);
if size(C,1) == 1
C = C.';
else
C = sum(C).';
end
function C = RealTrace(A,B)
% Same as real(trace(A*B)) but using less flops.
C=RealHadamard(A.',B);
C=sum(C(:));
function [listv,listLv,listCL,ErrRatio] = ...
LookForMinimum(L,v0,nThres,freqThres,freqStopThres,varargin)
%Executes a descent algorithm using a method similar to that in [ML].
if ~isempty(varargin)
nItMax = varargin{1};
else
nItMax = 20;
end
v0 = v0(:);
Nf = numel(v0);
listv = [v0,zeros(Nf,nItMax)];
listLv = [Cost(L,'value0',v0),zeros(1,nItMax)];
listCL = [NaN,zeros(1,nItMax)];
succ = 1;
nIt = 1;
while succ && nIt <= nItMax
[succ,v,Lv,CL] = NewtonIt(L,listv(:,nIt),freqThres);
if succ
nIt = nIt + 1;
listv(:,nIt) = v;
listLv(nIt) = Lv;
listCL(nIt) = CL;
else
break
end
if max(abs(listv(:,nIt)-listv(:,nIt-1))) < freqStopThres
break
end
end
ErrRatio = (Cost(L,'value0')-listLv(end))/listLv(end);
listv(:,nIt+1:end) = [];
listLv(nIt+1:end) = [];
listCL(nIt+1:end) = [];
function [v,vf] = validVector(vf,thres)
vf = sort(vf(:));
if length(vf)==1
v = 1;
return
end
m = vf(2:end)-vf(1:end-1) < thres;
if any(m)
v = 0;
vf([logical(0); m]) = [];
else
v = 1;
end
function [succ,v1,Lv1,nCutsLeft] = NewtonIt(L,v0,thres)
Lv1 = [];
nCutsLeft = [];
[vv,v1] = validVector(v0,thres);
if ~vv
succ = 0;
return
end
[Lv0,g0,h0] = Cost(L,'value',v0);
d = -h0\g0;
nCutsLeft = 20;
while nCutsLeft > 0
[vv,v1] = validVector(v0+d,thres);
if ~vv
succ = 0;
v1 = v0;
end
Lv1 = Cost(L,'value0',v0+d);
if Lv1 < Lv0
succ = 1;
v1 = v0 + d;
break;
end
nCutsLeft = nCutsLeft - 1;
d = d/2;
end
if nCutsLeft == 0
succ = 0;
end
function out = RegGeoSum(varargin)
%Computes the value of a geometric sum or its differentials using the exact formula. It
%takes care of the preventable singularity at zero.
switch nargin
case 2
[M,vf] = deal(varargin{:});
nd = 0;
msg = 'value';
case 3
[M,vf,nd] = deal(varargin{:});
msg = 'value';
case 5
[M,vf1,vf2,nd1,nd2] = deal(varargin{:});
msg = 'corr';
end
switch msg
case 'value'
out = RegGeoSum1(M,vf,nd);
case 'corr'
vf1 = vf1(:);
Nf1 = length(vf1);
vf2 = vf2(:);
Nf2 = length(vf2);
out = RegGeoSum1(M,-vf1(:,ones(1,Nf2))+vf2(:,ones(1,Nf1)).',nd1+nd2)*(-1)^nd1;
end
function v = RegGeoSum1(M,vf,nd)
m1 = -ceil(M/2);
ind = abs(vf)>eps^(1/3);
vf1 = vf(ind);
v = zeros(size(vf));
switch nd
case 0
v(ind) = -(exp(1i*2*pi*m1*vf1)-exp(1i*2*pi*(m1+M)*vf1))./(-1+exp(1i*2*pi*vf1));
v(~ind) = M;
case 1
v(ind) = (-2*1i*pi*( exp(1i*2*pi*vf1*(1 + m1))*(-1 + m1) - exp(1i*2*pi*vf1*m1)*m1 ...
-exp(1i*pi*2*vf1*(1 + M + m1))*(-1 + M + m1) + ...
exp(1i*2*pi*vf1*(M + m1))*(M + m1)))./(-1 + exp(1i*2*pi*vf1)).^2;
v(~ind) = pi*1i*M*(-1+M+2*m1);
case 2
v(ind) = (4*(exp(1i*2*pi*vf1*(2 + m1))*(-1 + m1)^2 + exp(1i*2*pi*vf1*m1)*m1^2 - ...
exp(1i*2*pi*vf1*(2 + M + m1))*(-1 + M + m1)^2 - ...
exp(1i*2*pi*vf1*(M + m1))*(M + m1)^2 + ...
exp(1i*2*pi*vf1*(1 + m1))*(1 - 2*(-1 + m1)*m1) + ...
exp(1i*2*pi*vf1*(1 + M + m1))* ...
(-1 + 2*M^2 + 2*(-1 + m1)*m1 + M*(-2 + 4*m1)))*pi^2)./ ...
(-1 + exp(1i*2*pi*vf1)).^3;
v(~ind) = -(2*pi^2/3)*M*(1+6*m1^2+6*m1*(-1+M)-3*M+2*M^2);
end
function st = Report(p,vfEst)
st = [];
st.Freqs = vfEst;
st.Amps = Correlation(p.cfd.icf,'ampEstimates',vfEst);
function FreqsDevBounds = CRBBound(vf,va,M,nVar)
%Computes the Cramer-Rao bound of the frequencies.
va = va(:);
vf = vf(:);
Raa = RegGeoSum(M,vf,vf,0,0);
Rad = RegGeoSum(M,vf,vf,0,1);
Rdd = RegGeoSum(M,vf,vf,1,1);
FreqsDevBounds = sqrt((nVar/2)*diag(inv(real((conj(va)*va.') .* (Rdd-Rad'*(Raa\Rad))))));
function st = MLEstimate(y,nVar,PFA)
p = Preprocessing(y,nVar,PFA);
st = MethodSerial1(p);
st.CRBBoundsOnFreqDevs = CRBBound(st.Freqs,st.Amps,length(y),nVar);
Amplitude spectrum of 1D signal
function plot_amp_spectrum(Fs, y, varargin)
%PLOT_AMP_SPECTRUM Plot amplitude spectrum of a one dimensional signal
% PLOT_AMP_SPECTRUM(FS, Y, COLOR, SEMILOG_SCALE, TITLE_STRING) plots the
% amplitude spectrum of y which has sampling frency Fs. Specification
% of color of the plot, wheather the plot is needed in semilog_scale or
% not, and the title string for the figure are OPTIONAL.
%
% Fs: Sampling frequency.
% y: Plots the one sided amplitude spectrum of the signal with,
% color: color of the plot specified in string,
% semilog_scale: [1]= Plot in log scale.
% Example:
% load ecg;
% plot_amp_spectrum(hz, signal); OR
% plot_amp_spectrum(hz, signal, 'r', 1) OR
% plot_amp_spectrum(hz, signal, 'r', 0, 'Amplitude spectrum of ECG signal')
%--------------------------------------------------------------------------
% Author: Aniket Vartak
% Email: aniket.vartak@gmail.com
% This function uses Matlab's fft() function, and builds on top of it to give
% a handy interface to get a nicely formatted plot of the amplitude
% spectrum.
%--------------------------------------------------------------------------
% Specify the default string incase its not provided
default_title_string = 'Single-Sided Amplitude Spectrum of y(t)';
%Deal with variable number of inputs after fs and x.
if(isempty(varargin)) % No optional information provided
color = 'b';
semilog_scale = 0;
title_string = default_title_string;
end;
if(length(varargin) == 1) % Only color info provided
color = varargin{1};
semilog_scale = 0;
title_string = default_title_string;
end;
if(length(varargin) == 2) % color and integer indicating semilog plot is needed is provided
color = varargin{1};
semilog_scale = varargin{2};
title_string = default_title_string;
end;
if(length(varargin) == 3) % All optional info provided
color = varargin{1};
semilog_scale = varargin{2};
title_string = varargin{3};
end;
%--------------------------------------------------------------------------
T = 1/Fs; % Sample time
L = max(size(y)); % Length of signal
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
Y = fft(y,NFFT)/L; % Take the fourier transform
f = Fs/2*linspace(0,1,NFFT/2+1);% Space out the frequencies
set(gcf, 'Name', strcat('Amplitude Spectrum: [Fs = ',num2str(Fs),' Hz]'));
set(gcf, 'NumberTitle', 'off');
% Plot single-sided amplitude spectrum.
if (semilog_scale)
semilogx(f,20*log10(2*abs(Y(1:NFFT/2+1))), color, 'LineWidth', 2);
else
plot(f,20*log10(2*abs(Y(1:NFFT/2+1))), color,'LineWidth', 2);
end;
title(title_string);
xlabel('Frequency (Hz)');
ylabel('|Y(f)| dB');
grid on;
Gray Code Generator - Matlab Script to Generate Verilog Header for Gray Coding
%==============================================================================
%
% Gray Code Generator for Verilog
%
% This script generates a Verilog header (.vh) file which contains a set of
% of `define directives to establish Gray-coded states for a state machine.
% The output of this script is intended to be used in conjunction with a
% Verilog design which uses Gray coding in some application. For more
% information on Gray coding, please see
% http://mathworld.wolfram.com/GrayCode.html.
%
% Usage:
%
% The bit width of the Gray coded states is set as a script variable.
% 2^bit_width states are generated. The output filename is also
% set as a script variable.
%
% Author: Tom Chatt
%
%------------------------------------------------------------------------------
% Revision History:
%
% Original Version Tom Chatt 11/2/2010
%
%==============================================================================
clear all; clc;
%------------------------------------------------------------------------------
bit_width = 8; % Bit width of the generated code
% Print the generated code entries to a Verilog defines file?
print_to_v_def_file = true;
output_file = ['gray_code_',num2str(bit_width),'.vh']; % Output file name
% Gray code state name prefix. State names will be of the form
% GC<bit_width>B_<state number>.
prefix = ['GC',num2str(bit_width),'B_'];
%--------------Do not edit code below this point-------------------------------
% Generate the code, starting with 1 bit code and looping upward
code = [0; 1];
if bit_width ~= 1
for i = 2 : bit_width
code = [zeros(size(code,1), 1), code; ones(size(code,1), 1), flipud(code)]; %#ok<AGROW>
end
end
% Print out the generated code
fid = fopen(output_file, 'w');
for i = 1 : size(code,1)
macro_name = [prefix, num2str(i)];
macro_val = [num2str(bit_width),'''', dec2bin(binvec2dec(code(i,:)),bit_width)];
fprintf(fid, ['ifndef ',macro_name,'\n']);
fprintf(fid, [' ','`define ', macro_name, ' ', macro_val, '\n']);
fprintf(fid, 'endif\n');
end
fclose('all');
DWT frequency division graphing
% ----------------------------------------------------------
% Title: Discrete Wavelet Transform
% Author: David Valencia
% UPIITA IPN 2010
%
% For DSPRelated.com
% in: http://www.dsprelated.com/showcode/13.php
%
% Computes the Discrete Wavelet Transform
% equivalent filters
%
% Dependencies:
% formfilter.m - http://www.dsprelated.com/showcode/12.php
% upsample2.m - http://www.dsprelated.com/showcode/10.php
%
% Revisions:
% v1.0a Commented and translated in English
%
% More information at:
% http://www.dsprelated.com/showarticle/115.php
% -----------------------------------------------------------
close all; clear all; clc;
disp('== GENERALIZED DWT FILTERS ==')
%% STEP 1 - Base Filters
% Select type of base filters
typeofbasis = 'o';
typbior = 'bior2.2';
typor = 'db6';
% Obtain base filters
if(typeofbasis == 'b')
[Rf,Df] = biorwavf(typbior);
[h0,h1,g0,g1] = biorfilt(Df,Rf);
elseif (typeofbasis == 'o')
[h0,h1,g0,g1] = wfilters(typor);
end;
%% STEP 2 - Parameter configuration
% One can declare or recover an input vector from another
% program, but here an example vector is built for testing.
L = length(h0); %Base filter lenght
n_stages = 2; %Of the low-pass stage
n_branches = 2^n_stages; %Number of branches
% L = Basic filters length (h0 ó h1)
% N = Input vector length
% n_stages = stage quantity, it generates (2^n_stages) branches
figure;
[H1,Wg]=freqz(h1,1,512);
plot(Wg,abs(H1),'r','linewidth',2); hold on;
for i = 0:(n_branches/2)-1
if n_stages < 3
hx = formfilter(n_stages, (n_branches/2) - i, h0, h1);
else
hx = formfilter(n_stages, (n_branches/2) - i - 1, h0, h1);
end
Lhx = length(hx);
% Graphing code
[H0,Wg]=freqz(hx,1,512);
plot(Wg,abs(H0),'b','linewidth',2); hold on;
pause; % Used to see how each filter appears
end
Image Denoising -threshold calculation using modified bivariate method
function [T,sigma1,sigma2] = model3_soft(CD,CH,CH1)
%function used to calculate the threshold and variance using modified
%bivariate model
%CD and CH : obtained after first stage wavelet decomposition
%CH1: obtained after second stage 2D-wavelet decomposition
sigman = (median(median(abs(CD))))/0.6745;
sigmay1 = 0;
sigmay2 = 0;
[m,n] = size(CD);
[m1,n1] = size(CH1);
%To calculate sigma1 value
for i =1:m
for j = 1:n
sigmay1 = sigmay1+((CH(i,j))^2);
end
end
sigmay1 = sqrt(2)*sigmay1/(m*n);
sigma1 = sqrt(max((((sigmay1))-((sigman)^2)),0));
if sigma1~=0
T = sqrt(3)*(sigman^2);
else
T = max(max(abs(CH)));
end
%To calculate sigma2 value
for i =1:m1
for j = 1:n1
sigmay2 = sigmay2+((CH1(i,j))^2);
end
end
sigmay2 = sqrt(2)*sigmay2/(m1*n1);
sigma2 = sqrt(max((((sigmay2))-((sigman)^2)),0));
double2cfloat.m - TMX Filter formatting for C compilers
% UPIITA IPN 2010
% José David Valencia Pesqueira
% This program is useful to convert numbers in MATLAB's Double
% format to a text file in float format for C compilers
% You should copy the resulting text to a file and save it with .h
% extension
% THIS PROGRAM RECEIVES AN UNIDIMENTIONAL VECTOR OF DOUBLE NUMBERS
% close all; clear all; clc;
function double2cfloat(x , namex, y, namey, sinc_factor)
[m,n] = size(x);
fprintf('// Begin of file\n\n');
fprintf('#define sinc %d // Sincronization factor\n',sinc_factor);
fprintf('#define N %d // Filter length\n',n);
if m~=0
fprintf('#define M %d // Number of filters(branches)\n\n',m);
fprintf('float %s[M][N]=',namex);
else
fprintf('float %s[N]=',namex);
end
disp('');
disp('{');
for i=0:m-1 %Rows
if m~=1
disp('{');
end
for j=0:n-1 %columns
fprintf('%1.4e,\n',x(i+1,j+1));
end
if m~=1
fprintf('},\n');
end
end
disp('};');
fprintf('\n\n');
if m~=0
fprintf('float %s[M][N]=',namey);
else
fprintf('float %s[N]=',namey);
end
disp('');
disp('{');
for i=0:m-1 %Rows
if m~=1
disp('{');
end
for j=0:n-1 %columns
fprintf('%1.4e,\n',y(i+1,j+1));
end
if m~=1
fprintf('},\n');
end
end
disp('};');
fprintf('\n// EOF\n\n');
Circular Convolution Matrix
function HC = convmtx_circ(h, N);
% CONVMTX_CIRC Circular Convolution Matrix.
% CONVMTX_CIRC(h,N) returns the circular convolution matrix for vector h.
% h must be a column vector. If X is a column vector of length N,
% then CONVMTX_CIRC(h,N)*X is the same as the circular convolution h * X.
%
% by Danilo Zanatta - 01.02.2011
h = h(:);
Nh = length(h);
Nc = N + Nh - 1;
if N < Nh,
error('The circular convolution matrix size must be greater or equal the channel length');
end
H = convmtx(h,N);
HC = H(1:N, 1:N);
HC(1:(Nh-1), 1:N) = HC(1:(Nh-1), 1:N) + H((N+1):Nc, 1:N);
return
Image Quantizer
%number of bits to truncate
tred = 4;
tgreen = 2;
tblue = 3;
clf;
x = imread('input.jpg');
red = x(:,:,1);
green = x(:,:,2);
blue = x(:,:,3);
red_t = (red/2^tred) * 2^tred;
green_t = (green/2^tgreen) * 2^tgreen;
blue_t = (blue/2^tblue) * 2^tblue;
x_t(:,:,1) = red_t;
x_t(:,:,2) = green_t;
x_t(:,:,3) = blue_t;
imshow(x);
pause;
imshow(x_t)
size = (24 - tred - tgreen - tblue) / 24
getsincdwt.m - Get DWT synchronization for chain-processing
% UPIITA IPN 2010
% Valencia Pesqueira José David
% Function used to obtain the synchronization factor for each
% branch in the DWT chain-processing program
function [x] = getsincdwt(n_etapas, rama, Lfiltrobase)
switch(n_etapas)
case 1 %One stage, two-branches. DWPT equivalent
x = 0;
case 2 %2 stages, 3 branches
switch(rama)
case 1 % High-pass branch
x = (Lfiltrobase-1)*2;
otherwise
x = 0;
end
case 3 %3 branches, 4 stages
switch(rama)
case 1 % High-pass branch
x = (Lfiltrobase-1)*2;
case 2
x = 10;
otherwise
x = 0;
end
end
% Experimental ANALISIS
% 2 etapas
% lfiltro - sinc_factor experimental
%
% 4 - 6 (4-1)*2 = 6
% 6 - 10 (6-1)*2 = 10
% 8 - 14 (8-1)*2 = 7
TMX Transmultiplexer (MATLAB Version)
% UPIITA IPN 2010
% Procesamiento Digital de Señales
% Grupo 6TM1 Equipo #8
% Team members
% Rogelio Baeza Nieves
% Ponce Mosso Catarina
% Valencia Pesqueira José David
% TMX Transmultiplexer -> Chain processing
close all;clear all;clc;
n_stages = 2;
n_branches = 2^n_stages;
dec_factor = 2^n_stages;
niter = 500;
N = 16;
input = zeros(2^n_stages,N);
for(k = 0:2^n_stages-1)
input(k+1,:) = (1 + k * N ):((k+1)*N);
end
input;
in_cnt = 1;
typeofbasis = 'o';
typbior = 'bior2.2';
typor = 'db2';
if(typeofbasis == 'b')
[Rf,Df] = biorwavf(typbior);
[h0,h1,g0,g1] = biorfilt(Df,Rf);
elseif (typeofbasis == 'o')
[h0,h1,g0,g1] = wfilters(typor);
end;
L = length(h0);
try
sinc_factor = getsinc(n_stages,L) - 1;
catch
disp('Error');
return
end
for i = 1:1
hx = fliplr(formafiltrosdwpt(n_stages,2^n_stages,h0,h1));
Lhx = length(hx);
H = zeros(2^n_stages, Lhx);
for i=0:(2^n_stages)-1
H(i+1,:)=fliplr(formafiltrosdwpt(n_stages,2^n_stages-i,h0,h1));
end
La = length(H(1,:));
G = zeros(2^n_stages, Lhx);
for i=0:(2^n_stages)-1
G(i+1,:)=fliplr(formafiltrosdwpt(n_stages,2^n_stages-i,g0,g1));
end
Ls = length(G(1,:));
double2cfloat(H,'h', G,'g',sinc_factor);
analysisbuffer = zeros(1,La);
y = zeros(2^n_stages,1);
sbuffer = zeros(2^n_stages, Ls);
xnbuff = zeros(2^n_stages,1);
chanbuffer = [0];
outputbuffer = zeros(2^n_stages,1);
end
for i=1:niter %General iteration counter
%% Synthesis stage
i
% Vector shifting (CLK/1)
for j = 1:(2^n_stages)
sbuffer(j,:) = recorreder(sbuffer(j,:),1);
end
% Input interpolation
if (mod(i,2^n_stages) == 1)&&(in_cnt<N-1)
sbuffer(:,1) = input(:,in_cnt);
in_cnt = in_cnt + 1;
else
sbuffer(:,1) = zeros(2^n_stages,1);
end
disp('inputs: ');
disp(sbuffer)
xnbuff = zeros(2^n_stages,1);
for j=0:(2^n_stages)-1
for k = 1 : Ls %convolution
xnbuff(j+1,1) = xnbuff(j+1,1) + sbuffer(j+1,k)*G(j+1,k);
end
end
chanbuffer = sum(xnbuff)
%% Analysis stage
analysisbuffer = recorreder(analysisbuffer,1);
analysisbuffer(1)=chanbuffer;
analysisbuffer;
if (i>sinc_factor && mod(i-sinc_factor,2^n_stages) == 1)
% If the counter is a multiply of the decimating factor, then compute
y = zeros(2^n_stages,1);
for j = 0:(2^n_stages)-1
for k=1:La %convolución
y(j+1,1) = y(j+1,1) + analysisbuffer(k)*H(j+1,k);
end;
end
outputbuffer = y;
end
input;
i
outputbuffer
pause;
end
return;
TMX formafiltrosdwpt.m - Integrated version
function [hx] = formafiltrosdwpt(n_stages,branch,h0,h1)
p = branch;
% Integrated version for DWPT/TMX filter generation
hx = 0;
hx(1) = 1;
switch n_stages
case 1
if mod(branch,2) ~= 0
hx = h0;
else
hx = h1;
end
case 2
switch branch
case 1
hx = conv(h0,upsample(h0,2));
case 2
hx = conv(h0,upsample(h1,2));
case 3
hx = conv(h1,upsample(h0,2));
case 4
hx = conv(h1,upsample(h1,2));
otherwise
beep;
fprintf('\nERROR');
end
otherwise
for i=0:n_stages-2
q = floor(p /(2^(n_stages-1-i)));
if (q == 1)
hx = conv(hx,upsample(h1,2^i));
else
hx = conv(hx,upsample(h0,2^i));
end
p = mod(p,2^(n_stages-1-i)); %For DWPT and TMX
end
t = mod(branch,2);
if(t == 1)
hx = conv(hx,upsample(h0,2^(n_stages-1)));
else
hx = conv(hx,upsample(h1,2^(n_stages-1)));
end
end
getsinc.m - TMX Transmultiplexer (MATLAB version)
function [sf] = getsinc(n_etapas, L)
% Experimentally obtained synchronization factors
if(n_etapas == 1)
sf = 2;
elseif (n_etapas == 2)
sf = L;
elseif L == 4
if(n_etapas == 3) % 8 branches
sf = 22;
elseif(n_etapas == 4) % 16 branches
sf = 36;
elseif(n_etapas == 5) % 32 branches
sf = 82;
end
elseif L == 6
if n_etapas == 3 % 8 branches
sf = 20;
elseif n_etapas == 4 % 16 branches
sf = 30;
elseif n_etapas == 5 % 32 branches
sf = 80;
end
elseif L == 8
if(n_etapas == 3) % 8 branches
sf = 26;
elseif(n_etapas == 4) % 16 branches
sf = 32;
end
elseif L == 10
if(n_etapas == 1)
sf = 2;
elseif(n_etapas == 2)
sf = 10;
end
end
double2cfloat.m - TMX Filter formatting for C compilers
% UPIITA IPN 2010
% José David Valencia Pesqueira
% This program is useful to convert numbers in MATLAB's Double
% format to a text file in float format for C compilers
% You should copy the resulting text to a file and save it with .h
% extension
% THIS PROGRAM RECEIVES AN UNIDIMENTIONAL VECTOR OF DOUBLE NUMBERS
% close all; clear all; clc;
function double2cfloat(x , namex, y, namey, sinc_factor)
[m,n] = size(x);
fprintf('// Begin of file\n\n');
fprintf('#define sinc %d // Sincronization factor\n',sinc_factor);
fprintf('#define N %d // Filter length\n',n);
if m~=0
fprintf('#define M %d // Number of filters(branches)\n\n',m);
fprintf('float %s[M][N]=',namex);
else
fprintf('float %s[N]=',namex);
end
disp('');
disp('{');
for i=0:m-1 %Rows
if m~=1
disp('{');
end
for j=0:n-1 %columns
fprintf('%1.4e,\n',x(i+1,j+1));
end
if m~=1
fprintf('},\n');
end
end
disp('};');
fprintf('\n\n');
if m~=0
fprintf('float %s[M][N]=',namey);
else
fprintf('float %s[N]=',namey);
end
disp('');
disp('{');
for i=0:m-1 %Rows
if m~=1
disp('{');
end
for j=0:n-1 %columns
fprintf('%1.4e,\n',y(i+1,j+1));
end
if m~=1
fprintf('},\n');
end
end
disp('};');
fprintf('\n// EOF\n\n');
Circular Convolution Matrix
function HC = convmtx_circ(h, N);
% CONVMTX_CIRC Circular Convolution Matrix.
% CONVMTX_CIRC(h,N) returns the circular convolution matrix for vector h.
% h must be a column vector. If X is a column vector of length N,
% then CONVMTX_CIRC(h,N)*X is the same as the circular convolution h * X.
%
% by Danilo Zanatta - 01.02.2011
h = h(:);
Nh = length(h);
Nc = N + Nh - 1;
if N < Nh,
error('The circular convolution matrix size must be greater or equal the channel length');
end
H = convmtx(h,N);
HC = H(1:N, 1:N);
HC(1:(Nh-1), 1:N) = HC(1:(Nh-1), 1:N) + H((N+1):Nc, 1:N);
return
This function helps in converting linear phase fir filter transfer function to min phase fir filter transfer function
function [hn_min] = lp_fir_2_mp_fir(hn_lin)
% This function helps in converting the linear phase
% FIR filter to minimum phase FIR filter. It essentially
% brings all zeros which are outside the unit circle to
% inside of unit circle.
r = roots(hn_lin);
k = abs(r) > 1.01;
r1 = r(k); % roots outside of unit circle.
r2 = r(~k);% roots on or within the unit circle
s = [1./r1; r2];
hn_min = poly(s);
hn_min = hn_min*sqrt(sum(hn_lin.^2))/sqrt(sum(hn_min.^2));
Fourier Trigonometric Series Approximation
%Trigonometric Fourier Series Approximation
%José David Valencia Pesqueira - UPIITA-IPN
%As posted for Dsprelated.com
close all; clear all; clc;
syms t k;
fprintf('\n ### FOURIER TRIGONOMETRICAL SERIES###');
fprintf('\nSpecify the range (t1,t2) for the approximation:\n');
t1=input('t1= ');
t2=input('t2= ');
% Getting the period
fprintf('\nIs there a repeating patterin in this range? (Y/N): ');
resp1=input('','s');
switch resp1
case 'Y'
fprintf('\nWhat is the period for the function?\n');
T=input('T= ');
omega0=(2*pi)/T;
case 'N'
T=t2-t1;
omega0=(2*pi)/T;
otherwise
fprintf('\nInvalid Option');
fprintf('\nEnd of program>>>');
return
end
fprintf('\nThe approximation will be generated in a trigonometrical series: \n\n');
fprintf('f(t)=a0+a1*cos(omega0*t)+a2*cos(2*omega0*t)+...+b1*sen(omega0*t)+b2*sen(2*omega0*t)');
fprintf('\n\nUntil what coefficient ak,bk should I compute? (positive integer) n= ');
n=input('');
if n<=0
fprintf('Invalid n');
fprintf('\nProgram Stop >>>');
return
end
fprintf('\nIs the function defined by parts? (Y/N): ');
resp1=input('','s');
switch resp1
case 'N'
fprintf('\nWrite the function in terms of t\nf(t)= ');
f=input('');
faprox=0;
a0=(1/T)*int(f,t,t1,(t1+T));
faprox=a0;
for k=1:n
a(k)=(2/T)*int((f*cos(k*omega0*t)),t,t1,(t1+T));
faprox=faprox+a(k)*cos(k*omega0*t);
end
for k=1:n
b(k)=(2/T)*int((f*sin(k*omega0*t)),t,t1,(t1+T));
faprox=faprox+b(k)*sin(k*omega0*t);
end
% If the function is defined in many parts
case 'Y'
fprintf('\nHow many ranges do you want to define (positive integer): ');
numinterv=input('');
numinterv=round(numinterv);
for k=1:numinterv
fprintf('\n## Range #%d definition',k);
fprintf('\n Write the range in the form of t(%d)<t<t(%d) : ',k-1,k);
fprintf('\nt(%d)= ',k-1);
a(k,1)=input(''); %Initial limits vector
fprintf('\nt(%d)= ',k);
a(k,2)=input(''); %Final limit vector
fprintf('\nThe range # %d has a start in %d and ends in %d',k,a(k),a(k+1));
fprintf('\nPlease define f(t) for the %d th interval:\nf(t)= ',k);
ft(k)=input('');
fprintf('\nEnd of definition of the function f%d',k);
end
faprox=0;
a0=0
for j=1:numinterv
a0=a0+(1/T)*int(ft(j),t,a(j,1),a(j,2));
end
faprox=a0;
% ak coefficient
ak=0;
for j=1:numinterv
acumulador=(2/T)*int((f(j)*cos(k*omega0*t)),t,a(j,1),a(j,2));
ak=ak+acumulador;
end
return
fprintf('\n## End of Debug Execution');
return
otherwise
fprintf('\nEND OF PROGRAM>>');
return
end
%% Salida de datos
fprintf('\nThe resulting coeficcients are: ');
a0
a
b
fprintf('\n Do you wish to plot the graph of f(t) against the approximate series? (Y/N): ');
resp1=input('','s');
if resp1=='Y'
ezplot(f,[t1,t2]);
hold on
ezplot(faprox,[t1,t2]);
grid;
end
fprintf('\nEND OF PROGRAM');
Resampling based on FFT
% FFTRESAMPLE Resample a real signal by the ratio p/q
function y = fftResample(x,p,q)
% --- take FFT of signal ---
f = fft(x);
% --- resize in the FFT domain ---
% add/remove the highest frequency components such that len(f) = len2
len1 = length(f);
len2 = round(len1*p/q);
lby2 = 1+len1/2;
if len2 < len1
% remove some high frequency samples
d = len1-len2;
f = f(:);
f(floor(lby2-(d-1)/2:lby2+(d-1)/2)) = [];
elseif len2 > len1
% add some high frequency zero samples
d = len2-len1;
lby2 = floor(lby2);
f = f(:);
f = [f(1:lby2); zeros(d,1); f(lby2+1:end)];
end
% --- take the IFFT ---
% odd number of sample removal/addition may make the FFT of a real signal
% asymmetric and artificially introduce imaginary components - we take the
% real value of the IFFT to remove these, at the cost of not being able to
% reample complex signals
y = real(ifft(f));
2-D Ping Pong Game.
%By vkc
function RunGame
hMainWindow = figure(...
'Color', [1 1 1],...
'Name', 'Game Window',...
'Units', 'pixels',...
'Position',[100 100 800 500]);
img = imread('ball.bmp','bmp');
[m,n,c] = size(img);
hBall = axes(...
'parent', hMainWindow,...
'color', [1 1 1],...
'visible', 'off',...
'units', 'pixels',...
'position', [345, 280, n, m] );
hBallImage = imshow( img );
set(hBallImage, 'parent', hBall, 'visible', 'off' );
ballSpeed = 3;
ballDirection = 0;
hTempBall = axes( ...
'parent', hMainWindow,...
'units', 'pixels',...
'color', 'none',...
'visible', 'off',...
'position', get(hBall, 'position' ) );
img = imread('paddle.bmp','bmp');
[m,n,c] = size(img);
hRightPaddle = axes(...
'parent', hMainWindow,...
'color', 'none',...
'visible', 'off',...
'units', 'pixels',...
'position', [650 - 10, 250 - 50, n, m] );
hRightPaddleImage = imshow( img );
set(hRightPaddleImage, 'parent', hRightPaddle, 'visible', 'off' );
targetY = 200;
t = timer( 'TimerFcn', @UpdateRightPaddleAI,...
'StartDelay', 10 );
start(t)
hLeftPaddle = axes(...
'parent', hMainWindow,...
'color', 'none',...
'visible', 'off',...
'units', 'pixels',...
'position', [50, 250 - 50, n, m] );
hLeftPaddleImage = imshow( img );
set(hLeftPaddleImage, 'parent', hLeftPaddle, 'visible', 'off' );
hBottomWall = axes(...
'parent', hMainWindow,...
'color', [1 1 1],...
'units', 'pixels',...
'visible', 'off',...
'position', [0 40 700 10] );
patch( [0 700 700 0], [0 0 10 10], 'b' );
hTopWall = axes(...
'parent', hMainWindow,...
'color', [1 1 1],...
'units', 'pixels',...
'visible', 'off',...
'position', [0 450 700 10] );
patch( [0 700 700 0], [0 0 10 10], 'b' );
rightScore = 0;
leftScore = 0;
hRightScore = axes(...
'parent', hMainWindow,...
'color', 'none',...
'visible', 'off',...
'units', 'pixels',...
'position', [650 485 50 10] );
hLeftScore = axes(...
'parent', hMainWindow,...
'color', 'none',...
'visible', 'off',...
'units', 'pixels',...
'position', [30 485 50 10] );
hRightScoreText = text( 0, 0, '0', 'parent', hRightScore,...
'visible', 'on', 'color', [1 1 1] );
hLeftScoreText = text( 0, 0, '0', 'parent', hLeftScore,...
'visible', 'on', 'color', [1 1 1] );
hQuitButton = uicontrol(...
'string', 'Quit',...
'position', [325 475 50 20],...
'Callback', @QuitButton_CallBack );
hStartButton = uicontrol(...
'string', 'Start',...
'position', [325 240 50 20],...
'Callback',@StartButton_CallBack );
playing = true;
while playing == true
UpdateBall()
UpdateLeftPaddle()
UpdateRightPaddle()
CheckForScore()
pause( 0.01 )
end
stop(t)
close( hMainWindow )
function UpdateBall
pos = get( hBall, 'position' );
ballX = pos(1,1);
ballY = pos(1,2);
ballDirection = NormalizeAngle( ballDirection );
% check for collisions with the walls
if ( ballY > 450 - 10 ) && ( ballDirection > 0 ) && ( ballDirection < 180 )
if ( ballDirection > 90 )
ballDirection = ballDirection + 2 * ( 180 - ballDirection );
else
ballDirection = ballDirection - 2 * ballDirection;
end
elseif ( ballY < 50 ) && ( ballDirection > 180 ) && ( ballDirection < 360 )
if ( ballDirection > 270 )
ballDirection = ballDirection + 2 * ( 360 - ballDirection );
else
ballDirection = ballDirection - 2 * ( ballDirection - 180 );
end
end
% check for collisions with the paddles
if ( ballDirection > 90 && ballDirection < 270 )
leftPaddlePos = get( hLeftPaddle, 'position' );
leftX = leftPaddlePos(1,1);
leftY = leftPaddlePos(1,2);
if( (ballX < leftX + 10)...
&& (ballX > leftX + 5)...
&& (ballY + 10 > leftY)...
&& (ballY < leftY + 100) )
if ( ballDirection < 180 )
ballDirection = 180 - ballDirection;
elseif( ballDirection > 180 )
ballDirection = 180 - ballDirection;
end
end
else
rightPaddlePos = get( hRightPaddle, 'position' );
rightX = rightPaddlePos(1,1);
rightY = rightPaddlePos(1,2);
if( (ballX + 10 > rightX)...
&& (ballX + 10 < rightX + 5)...
&& (ballY > rightY)...
&& (ballY < rightY + 100) )
if ( ballDirection < 90 )
ballDirection = 180 - ballDirection;
elseif( ballDirection > 270 )
ballDirection = 180 - ballDirection;
end
end
end
MoveObject( hBall, ballSpeed, ballDirection );
end
function UpdateRightPaddle()
speed = 5;
pos = get( hRightPaddle, 'position' );
rightY = pos(1,2);
if( rightY + 5 < targetY - 50 && rightY < 400 - 50 )
MoveObject( hRightPaddle, speed, 90 )
elseif( rightY - 5 > targetY - 50 && rightY > 50 )
MoveObject( hRightPaddle, speed, 270 )
end
pos = get( hRightPaddle, 'position' );
rightY = pos( 1,2);
if( rightY > 400 - 50 )
rightY = 350;
elseif( rightY < 50 )
rightY = 50;
end
if( strcmp( get( t, 'Running' ), 'off' ) )
start(t)
end
end
function UpdateRightPaddleAI( ob, data )
% calculate where the ball will colide.
tempBallDirection = NormalizeAngle( ballDirection );
if( tempBallDirection < 90 || tempBallDirection > 270 && ballSpeed > 0 )
ballPos = get( hBall, 'position' );
set( hTempBall, 'position', ballPos );
ballX = ballPos(1,1);
while( ballX < 650 - 10 )
ballPos = get( hTempBall, 'position' );
ballX = ballPos(1,1);
ballY = ballPos(1,2);
MoveObject( hTempBall, 20, tempBallDirection )
% check for temp ball collision with walls.
if ( ballY > 450 - 10 )
if ( tempBallDirection > 0 )
if ( tempBallDirection < 180 )
tempBallDirection = 360 - tempBallDirection;
end
end
elseif ( ballY < 60 )
if( tempBallDirection > 180 )
if( tempBallDirection < 360 )
tempBallDirection = 360 - tempBallDirection;
end
end
end
% line( 0, 0, 'marker', '*', 'parent', hTempBall )
% pause( 0.0005 )
end
pos = get( hTempBall, 'position' );
ballY = pos(1,2);
targetY = ballY + ( rand * 150 ) - 75;
end
end
function UpdateLeftPaddle()
scr = get( hMainWindow, 'position' );
screenX = scr(1,1);
screenY = scr(1,2);
screenH = scr(1,4);
mouse = get(0, 'PointerLocation' );
y = mouse(1,2) - screenY;
if( y > 100 && y < 400 )
paddlePos = get( hLeftPaddle, 'position' );
paddlePos(1,2) = y - 50;
set( hLeftPaddle, 'position', paddlePos );
elseif( y > 400 )
paddlePos = get( hLeftPaddle, 'position' );
paddlePos(1,2) = 400 - 50;
set( hLeftPaddle, 'position', paddlePos );
elseif( y < 100 )
paddlePos = get( hLeftPaddle, 'position' );
paddlePos(1,2) = 100 - 50;
set( hLeftPaddle, 'position', paddlePos );
end
end
function CheckForScore()
pos = get( hBall, 'position' );
xpos = pos(1,1);
ypos = pos(1,2);
if ( xpos < 5 )
set( hBallImage, 'visible', 'off' )
rightScore = rightScore + 1;
set ( hRightScoreText, 'string', num2str( rightScore ) )
pause( .5 )
ResetBall()
elseif ( xpos + 10 > 695 )
set( hBallImage, 'visible', 'off' )
leftScore = leftScore + 1;
set ( hLeftScoreText, 'string', num2str( leftScore ) )
pause( .5 )
ResetBall()
end
end
function ResetBall
pos = get( hBall, 'position' );
pos(1,1) = 345;
pos(1,2) = 255 + floor( rand*100 ) - 50;
set( hBall, 'position', pos )
ballSpeed = 4;
ballDirection = ( (rand(1) < 0.5) * 180 ) ... % 0 or 180
+ ( 45 + (rand(1) < 0.5) * -90 ) ... % + 45 or - 45
+ ( floor( rand * 40 ) - 20 ); % + -20 to 20
set( hBallImage, 'visible', 'on' )
pause(1)
end
function MoveObject( hInstance, speed, direction )
p = get( hInstance, 'position' );
x = p( 1, 1 );
y = p( 1, 2 );
x = x + cosd( direction ) * speed;
y = y + sind( direction ) * speed;
p( 1, 1 ) = x;
p( 1, 2 ) = y;
set( hInstance, 'position', p )
end
function SetObjectPosition( hObject, x, y )
pos = get( hObject, 'position' );
pos(1,1) = x;
pos(1,2) = y;
set( hObject, 'position', pos )
end
function a = NormalizeAngle( angle )
while angle > 360
angle = angle - 360;
end
while angle < 0
angle = angle + 360;
end
a = angle;
end
function QuitButton_CallBack( hObject, eventData )
playing = false;
end
function StartButton_CallBack( hObject, eventData )
set( hObject, 'visible', 'off' );
set( hLeftPaddleImage, 'visible', 'on' )
set( hRightPaddleImage, 'visible', 'on' )
ResetBall();
end
end
Passive direction finding
clc
clear all
close all
fs=20e7;
T=1/fs;
t=0:T:0.0000002;
f=10e6;
scanagle_deg=60;
step_deg=6;
theta=-deg2rad(scanagle_deg):deg2rad(step_deg):deg2rad(scanagle_deg);
for i=1:length(theta);
ant1=2*sin(2*pi*f*t);
ant2=2*sin(2*pi*f*t+theta(i));
[my,mx]=max(ant1);
sum_ant(i)=ant1(mx)+ant2(mx);
diff_ant(i)=ant1(mx)-ant2(mx);
ratio_ant(i)=diff_ant(i)/sum_ant(i);
% if diff_ant(i)==0
% diff_ant(i)=0.1;
% end
% ratio1_ant(i)=sum_ant(i)/diff_ant(i);
end
% subplot(311)
% plot(t,ant1,t,ant2)
subplot(211)
plot(rad2deg(theta),sum_ant,rad2deg(theta),diff_ant)
subplot(212)
plot(rad2deg(theta),ratio_ant)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
sim_ant1=2*sin(2*pi*f*t);
sim_ant2=2*sin(2*pi*f*t+deg2rad(30));
[smy,smx]=max(sim_ant1);
%%%%also take for same sample value of data
sim_sum_ant=sim_ant1(mx)+sim_ant2(mx);
sim_diff_ant=sim_ant1(mx)-sim_ant2(mx);
sim_ratio_ant=sim_diff_ant/sim_sum_ant