git-svn-id: http://moon:8086/svn/matlab/trunk@153 801c6759-fa7c-4059-a304-17956f83a07c
212 lines
7.2 KiB
Matlab
Executable File
212 lines
7.2 KiB
Matlab
Executable File
% Partitioned Frequency LMS Adaptive Filter -PFLMS-
|
|
% -------------------------------------------------
|
|
% Aufruf:
|
|
% Function [ys,ee,wf,fpo]=pflms(x,d,alpha,N,C,P,S,L,wi)
|
|
%
|
|
% Parameter:
|
|
% x : Eingangsvektor
|
|
% d : Referenzvektor
|
|
% alpha: konstante Schrittweite 0 < alpha <= 1.0
|
|
% N : Anzahl Filterkoeffizienten (Hinweis: N = P*S*L)
|
|
% C : FFT-Länge, idealerweise eine Zweier-Potenz (0=Auto)
|
|
% P : Anzahl der Filterpartitionen
|
|
% S : Anzahl der Filtersegmente
|
|
% L : Länge eines Verarbeitungsblocks (idealerweise C=L+N/P=2N/P)
|
|
% wi : Startwerte der Filterkoeffizienten im Zeitbereich
|
|
%
|
|
% Rückgabewerte:
|
|
% ee : Adaptitionsfehler
|
|
% ys : Filterausgang
|
|
% wf : Filterkoeffizienten am Ende der Adaption im Zeitbereich
|
|
% fpo : Anzahl benötigten der Floating-Point Operationen
|
|
|
|
% -------------------------------------------------------------------------
|
|
% Datum : 20.7.2001
|
|
% Autor : Jens Ahrensfeld
|
|
% Thema : Diplomarbeit
|
|
% Datei : pflms.m
|
|
% Benötigte Dateien: dspfft.m, dspifft.m
|
|
%
|
|
% -------------------------------------------------------------------------
|
|
function [ys,ee,wf,fpo]=pflms(x,d,alpha,N,C,P,S,L,wi)
|
|
|
|
% -------------------------------------------------------------------------
|
|
% Überprüfen der Parameter
|
|
% -------------------------------------------------------------------------
|
|
if (N ~= fix(N)),
|
|
error('Fehler: N muss eine ganze Zahl sein!');
|
|
end;
|
|
|
|
if (C ~= fix(C)),
|
|
error('Fehler: C muss eine ganze Zahl sein!');
|
|
end;
|
|
|
|
if (P ~= fix(P)),
|
|
error('Fehler: P muss eine ganze Zahl sein!');
|
|
end;
|
|
|
|
if (S ~= fix(S)),
|
|
error('Fehler: S muss eine ganze Zahl sein!');
|
|
end;
|
|
|
|
if (L ~= fix(L)),
|
|
error('Fehler: L muss eine ganze Zahl sein!');
|
|
end;
|
|
|
|
% -------------------------------------------------------------------------
|
|
% Automatik-Auswahl
|
|
% -------------------------------------------------------------------------
|
|
% Falls P=0 => Automatische Wahl von P
|
|
% Anahme: L+N/P = 2N/P
|
|
if (P==0),
|
|
P = N/L;
|
|
if (rem(N,L) ~= 0)
|
|
error('Fehler: Quotient aus N und L muss eine ganze Zahl sein! (N = P*S*L)');
|
|
end;
|
|
end;
|
|
|
|
% Falls C=0 => Automatische Wahl von C=2^r
|
|
% Anahme: C = L + N/P
|
|
if (C==0)
|
|
C = 2^ceil(log2(L+N/P-1));
|
|
end;
|
|
|
|
% -------------------------------------------------------------------------
|
|
% FLMS Parameter
|
|
% -------------------------------------------------------------------------
|
|
gamma = 1.0/C; % Sicherheitskonstante vermeidet Division durch Null
|
|
lambda = 0.6; % Vergessensfaktor
|
|
|
|
% -------------------------------------------------------------------------
|
|
% Initialisierungen
|
|
% -------------------------------------------------------------------------
|
|
Lx = length(x); % Länge des Eingangsvektors
|
|
Np = S*L; % Teilfilter hat die Länge Np = S*L = N/P
|
|
K = Lx/L; % Anzahl Verarbeitungsblöcke
|
|
|
|
ee=zeros(Lx,1); % Fehlervektor
|
|
ys=zeros(Lx,1); % Filterausgang, Schaetzung von d
|
|
wp = zeros(Np,P); % P Teilfilter im Zeitbereich
|
|
PX = zeros(C,1); % Schaetzung des Leistungsdichtespektrums
|
|
|
|
WSp = zeros(C,P); % P Teilfilter im Frequenzbereich
|
|
X = zeros(C,S*P); % Eingangsvektor im Frequenzbereich
|
|
mu = zeros(C,P*S); % Variable Schrittweite
|
|
yy = zeros(C,1); % Filterausgang im Zeitbereich
|
|
YS = zeros(C,1); % Filterausgang im Frequenzbereich
|
|
xzp = zeros(Lx+S*L,1); % Eingangsvektor mit S*L führenden Nullen
|
|
|
|
|
|
% -------------------------------------------------------------------------
|
|
% Tabellen zur effizienten MatLab-Implementierung
|
|
% -------------------------------------------------------------------------
|
|
pidTbl = [2:P*S]; % Index auf P*S vergangene Eingangsvektoren
|
|
pidTbl(P*S) = 1; % Reihenfolge: x(k-1),x(k-2),..,x(k-P*S-1),x(k)
|
|
|
|
pStbl = [0:P*S-1]; % Tabelle zur korrekten Adressierung der Eingangsvektoren...
|
|
pStbl(1) = P*S; % ...bei der Filterung und Update der Koeffizienten.
|
|
|
|
pjiTbl = [2:P]; % Index auf Teilfilter, welches bei der effizienten...
|
|
pjiTbl(P) = 1; % ...Projektion bearbeitet wird
|
|
|
|
xzp(C-L+1:Lx+C-L) = x; % Einfügen von Np führenden Nullen an den Eingangsvektor
|
|
|
|
pid = 1; % Aktueller Index zeigt auf Eingangsvektor x(0)
|
|
pji = 1; % Aktueller Index zeigt auf Teilfilter w_0
|
|
|
|
|
|
% -------------------------------------------------------------------------
|
|
% Anfangswerte der Filterkoeffienten partitionieren
|
|
% und in den Frequenzbereich transformieren wi_p(k) => WS_p(k)
|
|
% -------------------------------------------------------------------------
|
|
for p=1:P,
|
|
SLp = (p-1)*N/P;
|
|
wp(1:Np,p) = wi(SLp+1:SLp+N/P);
|
|
WSp(1:C,p) = 1/C*fft(wp(1:Np,p),C);
|
|
end;
|
|
|
|
% -------------------------------------------------------------------------
|
|
% Algorithmus Start
|
|
% -------------------------------------------------------------------------
|
|
flops(0);
|
|
|
|
for k=1:K,
|
|
|
|
kL = (k-1)*L;
|
|
|
|
% Transformation des aktuellen Eingangsvektors in den Frequenzbereich
|
|
X(1:C,pid) = 1/C*fft(xzp(kL+1:kL+C),C);
|
|
|
|
% Partitioned FFT-Faltung
|
|
% Faltung des ersten Teilfilters mit aktuellem Eingangsvektor
|
|
pS = pid;
|
|
YS = WSp(1:C,1).*X(1:C,pid) *C;
|
|
|
|
% Faltung der restlichen Teilfilters mit vergangenen Eingangsvektoren
|
|
for p=2:P,
|
|
% Ermittlung des korrekten Index 'pS' aus Tabelle
|
|
for i = 1:S,
|
|
pS = pStbl(pS);
|
|
end;
|
|
% Summation der einzelnen Filterausgänge
|
|
YS = YS + WSp(1:C,p).*X(1:C,pS) *C;
|
|
end;
|
|
|
|
|
|
% Transformation des Filterausgangs in den Zeitbereich
|
|
yy = real(ifft(YS,C))*C;
|
|
|
|
% Abspeichern der letzten L Werte des Filterausgangs
|
|
ys(kL+1:kL+L) = yy(C-L+1:C);
|
|
|
|
% Berechnung des Fehlers e(k)
|
|
ee(kL+1:kL+L) = d(kL+1:kL+L) - ys(kL+1:kL+L);
|
|
|
|
% Transformation des Fehlers in den Frequenzbereich
|
|
E = 1/C*fft([zeros(C-L,1); ee(kL+1:kL+L)],C);
|
|
|
|
% Schätzung der mittleren Eingangsleistung Px(k) aus x(k)
|
|
PX = abs((1-lambda)*conj(X(1:C,pid)).*X(1:C,pid) *C + lambda*PX);
|
|
|
|
|
|
% Berechnung der variablen Schrittweite mu(k)
|
|
% mu(k) wird niemals grösser als eins
|
|
mu(1:C,pid) = (alpha*gamma/P) ./(PX+gamma);
|
|
|
|
% Filterkoeffizenten-Update
|
|
pS = pid;
|
|
for p=1:P,
|
|
% Aktualisierung des p-ten Teilfilters
|
|
WSp(1:C,p) = WSp(1:C,p) + mu(1:C,pS) .* conj(X(1:C,pS)) .* E *C;
|
|
% Ermittlung des korrekten Index 'pS' aus Tabelle
|
|
for i = 1:S,
|
|
pS = pStbl(pS);
|
|
end;
|
|
end;
|
|
|
|
% Aufwändig: Projektion jeden p-ten Teilfilters wp pro k-ter Iteration
|
|
% for p=1:P,
|
|
% wp(1:C,p) = real(dspifft(WSp(1:C,p),C));
|
|
% WSp(1:C,p) = dspfft(wp(1:Np,p),C);
|
|
% end;
|
|
|
|
% Effizient: Projektion eines Teilfilters alternierend pro k-ter Iteration
|
|
wp(1:C,pji) = C*real(ifft(WSp(1:C,pji),C));
|
|
WSp(1:C,pji) = 1/C*fft(wp(1:Np,pji),C);
|
|
|
|
pji = pjiTbl(pji); % Nächster Index auf Eingangsvektor aus Tabelle
|
|
pid = pidTbl(pid); % Nächster Index auf Teilfilter aus Tabelle
|
|
|
|
end;
|
|
|
|
% Komposition des Gesamtfilters aus den P Teilfiltern
|
|
for p=1:P,
|
|
wf((p-1)*Np+1:p*Np) = wp(1:Np,p);
|
|
end;
|
|
|
|
fpo=flops;
|
|
|
|
% -------------------------------------------------------------------------
|
|
% Ende PFLMS.M
|
|
% -------------------------------------------------------------------------
|