Digital Comb Filter
% Usage: [B,A] = COMB(order, scalar);
%
% ORDER is the number of samples delayed prior to add
% SCALAR is the coefficient that will be applied to
% the delayed signal path at the final summation block.
%
% Note, there are two types of comb filters. A DC-blocker and a DC-passer.
% To get a DC-Blocker (tooth at DC), pass in a -1 for the scalar.
% To get a DC-Passer (+6dB at DC), pass in a +1 for the scalar.
%
% By default, if the scalar is not passed, a DC-Passer is assumed.
%
% Author: sparafucile17 03/16/04
% Validate that the proper argument count was supplied
error(nargchk(1, 2, nargin));
% Use scalar is passed as an argument, otherwise assume scalar=1;
if (nargin == 1)
scalar = 1;
else
scalar = varargin{1};
end
% Input has zeros to simulate a single delay of N samples
a = [ 1 ];
b = [ 1 zeros(1, N-1) scalar*1];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);High accuracy FFT interpolation
function DemoProposed
% Author: J. Selva.
% First version: Sept. 2007.
%
% This m file contains the code for generating Fig. 2 in Sec. IV.A of paper
% "Convolution-based trigonometric interpolation of band-limited signals", IEEE
% Transactions on Signal Processing, vol. 56, n. 11, pp. 5465-5477, Nov. 2008. The
% equation numbers and references in this m file refer to this publication.
%
% Some comments:
%
% -The function 'KnabAPPeriodicApprox' computes the coefficients G(k/NT) in Sec. IV. This
% function takes several minutes, given that it involves a large number of numerical
% integrals which are performed in function KnabAPSpectrum. However, this must be done
% only once for fixed T, B, P and N, given that the G(k/NT) are independent of the sample
% values.
%
% 'RealTestSignal' implements a band-limited signal which consists of a sum of sinc pulses
% with arbitrary amplitudes and delays.
%
% 'FraserFFTUpsampling' implements the well-known zero-padding FFT
% algorithm. 'ProposedFFTUpsampling' implements the upsampling method in Sec. IV. It is
% worth comparing the code of both functions below.
warning off
T = 1; %Sampling period.
B = 0.5; %Two-sided bandwidth.
P = 18; %Pulse semi-length.
N = 1024; %Number of samples.
%Test signal composed of N+200 sinc pulses with random amplitudes and delays.
Sig = @(t)RealTestSignal(t,B,T,[-100,N+100],N+200);
%Compute coefficients Gn. This takes a while (5 minutes) because it is necessary to
%compute a large number of numerical integrals. However, since this step does not depend
%on the signal samples, it can be performed off-line and once ever.
disp(['Computing spectral coefficients. This takes a few minutes (7 or less), but ', ...
'must be done only',sprintf('\n'),'once ever for fixed T, B, P, and N.'])
% 'KnabAPPeriodicApprox' returns the frequency grid, specified by the first frequency fo
% and the frequency increment Df, the coefficients Gn, one for each grid frequency, and
% the truncation index kg.
[fo,Df,Gn,kg] = KnabAPPeriodicApprox(T,B,P,N);
sRef = Sig((0:N-1)*T); %Vector of signal samples with spacing T.
a = 10; %Oversampling factor.
sUpExact = Sig((0:a*N-1)*T/a); %Exact signal samples with oversampling a.
sUpFraser = FraserFFTUpsampling(sRef,a); %Interpolated samples using a zero-padded FFT.
sUpProposed = ProposedFFTUpsampling(sRef,T,B,12,a,Gn,kg); %Interpolated samples using
%the proposed method.
to = 0; %First instant in time grid.
Dt = T/a; %Grid time increment.
%Plot the interpolation error in dB for the zero-padding FFT method and for the proposed
%method.
plot(to+(0:a*N-1)*Dt,20*log10(abs([sUpExact - sUpFraser;sUpExact - sUpProposed])))
xlabel('Time t/T')
ylabel('Interpolation error (dB)')
annotation(gcf,'textarrow',[0.2911 0.2536],[0.8119 0.7429],...
'String',{'This is the zero-padding','FFT error'});
annotation(gcf,'arrow',[0.3321 0.06964],[0.4833 0.6333]);
annotation(gcf,'textarrow',[0.3446 0.2643],[0.419 0.3548],...
'String',{'This is the error of the','proposed FFT method. Note',...
'that the scale is in dB !!'});
warning on
%=====================================================================
%
% Conventional zero-padding FFT algorithm
function sUp = FraserFFTUpsampling(s,a)
N = length(s);
sF = a * fftshift(fft(s)); %Compute the FFT of the signal samples.
if mod(N,2) == 0 %Pad with zeros to obtain over-sampling factor a.
sF(end) = 0.5*sF(end);
sF = [zeros(1,N*(a-1)/2),sF,zeros(1,N*(a-1)/2)];
else
sF = [zeros(1,(N*(a-1)+1)/2),sF,zeros(1,(N*(a-1)-1)/2)];
end
sUp = ifft(ifftshift(sF)); %Compute the inverse FFT.
%=====================================================================
%
% Proposed FFT algorithm
function sUp = ProposedFFTUpsampling(s,T,B,P,a,Gn,kg)
N = length(s);
sF = fft(s); %Compute the FFT of the signal samples.
sF = sF(1+mod(-kg:kg,N)) .* Gn * (N*a); %Repeat some of the spectral samples periodically,
%and apply the window specified by the vector Gn.
sF = sF(:).';
if mod(N,2) == 0 %Pad with zeros to obtain over-sampling factor a.
sF = [zeros(1,N*a/2-kg),sF,zeros(1,N*a/2-kg-1)];
else
sF = [zeros(1,(N*a-2*kg-1)/2),sF,zeros(1,(N*a-2*kg-1)/2)];
end
sUp = ifft(ifftshift(sF)); %Compute the inverse FFT.
%=====================================================================
%
% Returns the spectral coefficients Gn and the frequency grid specification f0, Df, Gn.
function [f0,Df,Gn,n0] = KnabAPPeriodicApprox(T,B,P,N)
Df = 1/(N*T);
n0 = floor((1/T-B/2)/Df);
f0 = -Df*n0;
Bg = 2/T-B;
Gn = KnabAPSpectrum(f0+Df*(0:2*n0),B,Bg,(P+1/2)*T)/N;
%=====================================================================
%
% Auxiliary function that computes the spectral coefficients Gn.
function G = KnabAPSpectrum(f,B,Bg,TL)
% B: Two-sided signal bandwidth.
% Bg: Two-sided bandwidth of output pulse.
% Be: Two-sided bandwidth of fast-decay pulse.
% TL: Window's width between zeros in time domain.
%
% The two-sided bandwidth of the output pulse is Bg = B+2*Be.
Nf = numel(f);
G = zeros(size(f));
Be = (Bg-B)/2;
Ba = (Bg+B)/2;
Int = @(x)ConvWindow(x,Be,2*TL);
for k = 1:Nf
if f(k)-Ba/2 <= -Be/2 && Be/2 <= f(k)+Ba/2
G(k) = 1;
else
IInt = IntervalIntersection([-Be/2,Be/2],f(k)+[-Ba/2,Ba/2]);
if ~isempty(IInt)
G(k) = quad(Int,IInt(1),IInt(2),1e-16);
end
end
end
% Auxiliary function. It computes samples of the continuous convolution of a square pulse
% with the Kaiser window.
function W = ConvWindow(f,B,TL)
%Kaiser window.
%B: Two-sided window width.
%TL: Width between zeros in time domain.
W = zeros(size(f));
I = abs(f) < B/2;
W(I) = besseli(0,pi*B*(TL/2)*sqrt(1-(2*f(I)/B).^2))/(B*sinc(j*B*TL/2));
function [IInt,RelAInd,RelBInd] = IntervalIntersection(IA,IB)
if IA(2) < IB(1) || IB(2) < IA(1) %No overlap case.
IInt = [];
RelAInd = [];
RelBInd = [];
return
end
SwapIntervals = diff(IA) > diff(IB);
if SwapIntervals %Force IA to be the sorter interval.
Ipr = IA;
IA = IB;
IB = Ipr;
end
if IA(1) < IB(1)
IInt = [IB(1),IA(2)]; %There is intersection to the left.
RelAInd = IB(1)-IA(1);
RelBInd = 0;
if SwapIntervals
Relpr = RelAInd;
RelAInd = RelBInd;
RelBInd = Relpr;
end
return
end
if IA(2) <= IB(2)
IInt = IA; %IA lies inside IB.
RelAInd = 0;
RelBInd = IA(1)-IB(1);
if SwapIntervals
Relpr = RelAInd;
RelAInd = RelBInd;
RelBInd = Relpr;
end
return
end
IInt = [IA(1),IB(2)]; %There is intersection to the right.
RelAInd = 0;
RelBInd = IA(1)-IB(1);
if SwapIntervals
Relpr = RelAInd;
RelAInd = RelBInd;
RelBInd = Relpr;
end
%=====================================================================
%
% Computes samples of a signal formed by sincs with random amplitudes and delays.
function s = RealTestSignal(t,B,T,I,Np)
Sr = rand('seed');
rand('seed',0); %Always select the same random numbers in the sequel.
M = numel(t);
Ap = (rand(Np,1)-0.5)*2 ; %Random amplitudes.
tp = I(1)+rand(Np,1)*diff(I); %Random delays.
rand('seed',Sr)
st = size(t);
t = t(:);
s = zeros(numel(t),1);
for r = 1:Np
s = s + sinc(B*(t-tp(r)))*Ap(r); %Compute sum of sincs
end
s = reshape(s,st);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
enddouble2cfloat.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);
returnImage 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) / 24getsincdwt.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 = 7TMX 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
endgetsinc.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
enddouble2cfloat.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);
returnThis 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
endPassive 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





