2014-01-29 75 views
2

我正在尋求在C中實現歸一化最小均方(NLMS)。我的問題是在權重更新(我認爲)當我運行它對一個標準的MATLAB庫。這是MATLAB代碼(這工作):歸一化最小均方 - C實現

function [e,w,y]=nlmsFunc(mu,M,u,d,a); 
% Normalized LMS 
% Call: 
% [e,w]=nlms(mu,M,u,d,a); 
% 
% Input arguments: 
% mu = step size, dim 1x1 
% M = filter length, dim 1x1 
% u = input signal, dim Nx1 
% d = desired signal, dim Nx1 
% a = constant, dim 1x1 
% 
% Output arguments: 
% e = estimation error, dim Nx1 
% w = final filter coefficients, dim Mx1 
%intial value 0 

w=zeros(M,1); %This is a vertical column 

%input signal length 
N=length(u); 
%make sure that u and d are colon vectors 
u=u(:); 
d=d(:); 
%NLMS 
for n=M:N %Start at M (Filter Length) and Loop to N (Length of Sample) 
uvec=u(n:-1:n-M+1); %Array, start at n, decrement to n-m+1 
e(n)=d(n)-w'*uvec; 
w=w+mu/(a+uvec'*uvec)*uvec*conj(e(n)); 
y(n) = w'*uvec; %In ALE, this will be the narrowband noise. 
end 

我的問題是要將這種到C,這是我到目前爲止有:

float mu = 0.05; //Set up mu 
    int a = 1; //Constant 

    int inputSigSize = numSamples; 
    float outputYSignal[inputSigSize]; 
    float desiredSignal[inputSigSize]; 
    float error[inputSigSize]; 


    float inputSignal[inputSigSize]; 

    //Initialise Weights to Zero 
    if (weights[0] == 0) { 

     for (int k = 0; k<=filterLength; k++) { 
      weights[k]=0; 
     } 
    } 

    float X[filterLength+1]; 
    float Y = 0; 
    float E = 0; 

    //Start NLMS Loop 
    for (int t = 0; t<numSamples; t++) { 

     X[0] = inputSignal[t]; 

     for (int i = 0; i<=filterLength; i++) { 
      Y += (weights[i]*X[i]); 
     } 

     E = desiredSignal[t] - Y; 

     for (int i = filterLength; i>=0; i--) { 
      weights[i] = weights[i] + (mu*E*X[i]); 

      if (i!=0) { 
       X[i]=X[i-1]; 
      } 
     } 

     outputYSignal[t] = Y; 
     error[t] = E; 
    } 
    //END NLMS Loop 

我有一種感覺它的方式我」 m處理重量更新。

+0

什麼問題? –

+0

你能讓matlab自動生成c代碼嗎? – bph

+2

你沒有初始化你的數組;不要假設數組(在C函數中定義時)會像許多其他語言一樣被隱式初始化。他們可能包含隨機垃圾。 –

回答

1

NLMS C代碼實現:

#define inputSize 800 

#define N 64 // filter size 

double stepsize = 0.0; //Set up mu 
double x[inputSize]; 
double d[inputSize]; 
double y[inputSize]; 
double h[N]; 
double e[inputSize]; 
int M = inputSize; 

void nlmsFilter() { 

//Initialise Weights to Zero 
memset(y, 0, inputSize); 
memset(e, 0, inputSize); 
memset(h, 0, N); 

double X1[N]; 
int t, j, i; 

for (t = N; t <= M; t++) { 
    for (j = (t - 1); j >= (t - N); j--) { 
     X1[t-j-1] = x[j]; 
     printf("%d %lf %lf \n", (t-j-1), X1[t-j-1], x[j]); 
    } 

    for (i = 0; i < N; i++) { 
     y[t-1] += (h[i] * X1[i]); 
    } 

    e[t-1] = d[t-1] - y[t-1]; 

    for (i = 0; i < N; i++) { 
     stepsize += (X1[i] * X1[i]); 
    } 

    stepsize = 1/stepsize; 

    for (i = 0; i < N; i++) { 
     h[i] = h[i] + (stepsize * e[t-1] * X1[i]); 
    } 
} 
return; 
} 
0

你似乎已經忘記了由輸入的方差導致的mu的歸一化。另外,請注意,您的過濾技術與參考代碼不匹配:係數權重[j]應該乘以輸入樣本X [FilterLength - j]。輸入數組在uvec中相反(保持水龍頭(不像我們預期的那樣水龍頭+ 1)樣本)。

在原來的代碼,他們似乎添加小的一定的情況下,方差爲0(對於FilterLength + 1個抽頭恆定輸入),但我認爲你可以只通過之前做的波動的檢查得到更準確的結果。

避免在for循環中移動這樣的數據:X [i] = X [i-1]。