|
@@ -959,9 +959,8 @@ cmRC_t cmNlmsEcInit( cmNlmsEc_t* p, float mu, unsigned hN, unsigned delayN
|
959
|
959
|
p->mu = mu;
|
960
|
960
|
p->hN = hN;
|
961
|
961
|
p->delayN = delayN;
|
962
|
|
- p->wV = cmMemResizeZ(cmSample_t,p->wV,hN);
|
963
|
|
- p->hV = cmMemResizeZ(cmSample_t,p->hV,hN);
|
964
|
|
- p->dV = cmMemResizeZ(cmSample_t,p->dV,delayN);
|
|
962
|
+ p->wV = cmMemResizeZ(double,p->wV,hN);
|
|
963
|
+ p->hV = cmMemResizeZ(double,p->hV,hN);
|
965
|
964
|
p->w0i = 0;
|
966
|
965
|
|
967
|
966
|
return rc;
|
|
@@ -982,37 +981,53 @@ cmRC_t cmNlmsEcFinal( cmNlmsEc_t* p )
|
982
|
981
|
|
983
|
982
|
cmRC_t cmNlmsEcExec( cmNlmsEc_t* p, const cmSample_t* xV, const cmSample_t* fV, cmSample_t* yV, unsigned xyN )
|
984
|
983
|
{
|
|
984
|
+ // See: http://www.eit.lth.se/fileadmin/eit/courses/ett042/CE/CE2e.pdf
|
|
985
|
+ // and http://www.eit.lth.se/fileadmin/eit/courses/ett042/CE/CE3e.pdf
|
985
|
986
|
unsigned i;
|
986
|
987
|
for(i=0; i<xyN; ++i)
|
987
|
988
|
{
|
988
|
|
- cmSample_t y = 0;
|
989
|
|
- unsigned j;
|
990
|
|
- unsigned k = 0;
|
991
|
|
- float a = 0.00001;
|
992
|
|
-
|
993
|
|
- p->hV[p->w0i] = xV[i];
|
994
|
|
-
|
|
989
|
+ double y = 0;
|
|
990
|
+ unsigned k = 0;
|
|
991
|
+ double a = 0.001;
|
|
992
|
+ unsigned j;
|
|
993
|
+
|
|
994
|
+ // insert the next sample into the filter delay line
|
|
995
|
+ p->hV[p->w0i] = xV[i];
|
|
996
|
+
|
|
997
|
+ // calculate the output of the delay w0i:hN
|
995
|
998
|
for(j=p->w0i,k=0; j<p->hN; ++j,++k)
|
996
|
999
|
y += p->hV[j] * p->wV[k];
|
997
|
1000
|
|
|
1001
|
+ // calcuate the output of the delay 0:w0i
|
998
|
1002
|
for(j=0; j<p->w0i; ++j,++k)
|
999
|
1003
|
y += p->hV[j] * p->wV[k];
|
1000
|
1004
|
|
1001
|
|
- p->w0i = (p->w0i+1) % p->hN;
|
1002
|
|
-
|
1003
|
|
- float e = fV[i] - y;
|
|
1005
|
+ // calculate the error
|
|
1006
|
+ double e = fV[i] - y;
|
|
1007
|
+ yV[i] = e;
|
1004
|
1008
|
|
1005
|
|
- cmSample_t z = 0;
|
|
1009
|
+ //
|
|
1010
|
+ double z = 0;
|
1006
|
1011
|
for(j=0; j<p->hN; ++j)
|
1007
|
1012
|
z += p->hV[j] * p->hV[j];
|
1008
|
1013
|
|
1009
|
|
- for(j=0; j<p->hN; ++j)
|
1010
|
|
- p->wV[j] += p->mu/(a + z) * p->hV[j] * e;
|
|
1014
|
+ // update weights 0 through w0i
|
|
1015
|
+ for(j=p->w0i,k=0; j<p->hN; ++j,++k)
|
|
1016
|
+ p->wV[k] += (p->mu/(a + z)) * p->hV[j] * e;
|
|
1017
|
+
|
|
1018
|
+ // update weights w0i through hN
|
|
1019
|
+ for(j=0; j<p->w0i; ++j,++k)
|
|
1020
|
+ p->wV[k] += (p->mu/(a + z)) * p->hV[j] * e;
|
|
1021
|
+
|
|
1022
|
+ // advance the delay
|
|
1023
|
+ p->w0i = (p->w0i+1) % p->hN;
|
|
1024
|
+
|
1011
|
1025
|
}
|
1012
|
1026
|
|
1013
|
1027
|
return cmOkRC;
|
1014
|
1028
|
}
|
1015
|
1029
|
|
|
1030
|
+
|
1016
|
1031
|
cmRC_t cmNlmsEcWrite( cmNlmsEc_t* p, const cmChar_t* dirStr )
|
1017
|
1032
|
{
|
1018
|
1033
|
if( p->eVa != NULL )
|