|
@@ -914,18 +914,20 @@ cmRC_t cmReflectCalcWrite( cmReflectCalc_t* p, const char* dirStr )
|
914
|
914
|
//=======================================================================================================================
|
915
|
915
|
//
|
916
|
916
|
//
|
917
|
|
-cmNlmsEc_t* cmNlmsEcAlloc( cmCtx* ctx, cmNlmsEc_t* ap, float mu, unsigned hN, unsigned delayN )
|
|
917
|
+cmNlmsEc_t* cmNlmsEcAlloc( cmCtx* ctx, cmNlmsEc_t* ap, double srate, float mu, unsigned hN, unsigned delayN )
|
918
|
918
|
{
|
919
|
919
|
cmNlmsEc_t* p = cmObjAlloc(cmNlmsEc_t,ctx,ap);
|
920
|
920
|
|
|
921
|
+ bool debugFl = false;
|
|
922
|
+
|
921
|
923
|
// allocate the vect array's
|
922
|
|
- p->uVa = cmVectArrayAlloc(ctx, kFloatVaFl );
|
923
|
|
- p->fVa = cmVectArrayAlloc(ctx, kFloatVaFl );
|
924
|
|
- p->eVa = cmVectArrayAlloc(ctx, kFloatVaFl );
|
|
924
|
+ p->uVa = debugFl ? cmVectArrayAlloc(ctx, kFloatVaFl ) : NULL;
|
|
925
|
+ p->fVa = debugFl ? cmVectArrayAlloc(ctx, kFloatVaFl ) : NULL;
|
|
926
|
+ p->eVa = debugFl ? cmVectArrayAlloc(ctx, kFloatVaFl ) : NULL;
|
925
|
927
|
|
926
|
928
|
|
927
|
|
- if( mu != 0 )
|
928
|
|
- if( cmNlmsEcInit(p,mu,hN,delayN) != cmOkRC )
|
|
929
|
+ if( srate != 0 )
|
|
930
|
+ if( cmNlmsEcInit(p,srate,mu,hN,delayN) != cmOkRC )
|
929
|
931
|
cmNlmsEcFree(&p);
|
930
|
932
|
|
931
|
933
|
return p;
|
|
@@ -952,18 +954,24 @@ cmRC_t cmNlmsEcFree( cmNlmsEc_t** pp )
|
952
|
954
|
|
953
|
955
|
}
|
954
|
956
|
|
955
|
|
-cmRC_t cmNlmsEcInit( cmNlmsEc_t* p, float mu, unsigned hN, unsigned delayN )
|
|
957
|
+cmRC_t cmNlmsEcInit( cmNlmsEc_t* p, double srate, float mu, unsigned hN, unsigned delayN )
|
956
|
958
|
{
|
957
|
959
|
cmRC_t rc = cmOkRC;
|
958
|
960
|
|
959
|
961
|
if((rc = cmNlmsEcFinal(p)) != cmOkRC )
|
960
|
962
|
return rc;
|
|
963
|
+
|
|
964
|
+ assert( srate >= hN );
|
|
965
|
+ assert( srate >= delayN );
|
961
|
966
|
|
962
|
967
|
p->mu = mu;
|
963
|
968
|
p->hN = hN;
|
964
|
|
- p->delayN = delayN;
|
965
|
|
- p->wV = cmMemResizeZ(double,p->wV,hN);
|
966
|
|
- p->hV = cmMemResizeZ(double,p->hV,hN);
|
|
969
|
+ p->delayN = cmMax(1,delayN);
|
|
970
|
+ p->dN = srate;
|
|
971
|
+ p->delayV = cmMemResizeZ(cmSample_t, p->delayV, srate );
|
|
972
|
+ p->di = 0;
|
|
973
|
+ p->wV = cmMemResizeZ(double,p->wV,srate);
|
|
974
|
+ p->hV = cmMemResizeZ(double,p->hV,srate);
|
967
|
975
|
p->w0i = 0;
|
968
|
976
|
|
969
|
977
|
return rc;
|
|
@@ -972,16 +980,6 @@ cmRC_t cmNlmsEcInit( cmNlmsEc_t* p, float mu, unsigned hN, unsigned delayN
|
972
|
980
|
cmRC_t cmNlmsEcFinal( cmNlmsEc_t* p )
|
973
|
981
|
{ return cmOkRC; }
|
974
|
982
|
|
975
|
|
-/*
|
976
|
|
- for n=M:N
|
977
|
|
- uv = u(n:-1:n-M+1);
|
978
|
|
- e(n) = d(n)-w'*uv;
|
979
|
|
- w=w+mu/(a + uv'*uv ) * uv * conj(e(n));
|
980
|
|
- endfor
|
981
|
|
-
|
982
|
|
- e = e(:).^2;
|
983
|
|
-*/
|
984
|
|
-
|
985
|
983
|
cmRC_t cmNlmsEcExec( cmNlmsEc_t* p, const cmSample_t* xV, const cmSample_t* fV, cmSample_t* yV, unsigned xyN )
|
986
|
984
|
{
|
987
|
985
|
// See: http://www.eit.lth.se/fileadmin/eit/courses/ett042/CE/CE2e.pdf
|
|
@@ -994,10 +992,17 @@ cmRC_t cmNlmsEcExec( cmNlmsEc_t* p, const cmSample_t* xV, const cmSample_t*
|
994
|
992
|
double a = 0.001;
|
995
|
993
|
unsigned j;
|
996
|
994
|
|
997
|
|
- // insert the next sample into the filter delay line
|
998
|
|
- p->hV[p->w0i] = xV[i];
|
|
995
|
+ // Insert the next sample into the filter delay line.
|
|
996
|
+ // Note that rather than shifting the delay line on each iteration we
|
|
997
|
+ // increment the input location and then align it with the zeroth
|
|
998
|
+ // weight below.
|
|
999
|
+ p->hV[p->w0i] = p->delayV[ p->di ];
|
|
1000
|
+
|
|
1001
|
+ p->delayV[ p->di ] = xV[i];
|
|
1002
|
+
|
|
1003
|
+ p->di = (p->di + 1) % p->delayN;
|
999
|
1004
|
|
1000
|
|
- // calculate the output of the delay w0i:hN
|
|
1005
|
+ // calculate the output of the delay w0i:hN
|
1001
|
1006
|
for(j=p->w0i,k=0; j<p->hN; ++j,++k)
|
1002
|
1007
|
y += p->hV[j] * p->wV[k];
|
1003
|
1008
|
|
|
@@ -1005,7 +1010,7 @@ cmRC_t cmNlmsEcExec( cmNlmsEc_t* p, const cmSample_t* xV, const cmSample_t*
|
1005
|
1010
|
for(j=0; j<p->w0i; ++j,++k)
|
1006
|
1011
|
y += p->hV[j] * p->wV[k];
|
1007
|
1012
|
|
1008
|
|
- // calculate the error
|
|
1013
|
+ // calculate the error which is also the filter output
|
1009
|
1014
|
double e = fV[i] - y;
|
1010
|
1015
|
yV[i] = e;
|
1011
|
1016
|
|
|
@@ -1027,9 +1032,14 @@ cmRC_t cmNlmsEcExec( cmNlmsEc_t* p, const cmSample_t* xV, const cmSample_t*
|
1027
|
1032
|
|
1028
|
1033
|
}
|
1029
|
1034
|
|
1030
|
|
- cmVectArrayAppendS(p->uVa,xV,xyN);
|
1031
|
|
- cmVectArrayAppendS(p->fVa,fV,xyN);
|
1032
|
|
- cmVectArrayAppendS(p->eVa,yV,xyN);
|
|
1035
|
+ if( p->uVa != NULL )
|
|
1036
|
+ cmVectArrayAppendS(p->uVa,xV,xyN);
|
|
1037
|
+
|
|
1038
|
+ if( p->fVa != NULL )
|
|
1039
|
+ cmVectArrayAppendS(p->fVa,fV,xyN);
|
|
1040
|
+
|
|
1041
|
+ if( p->eVa != NULL )
|
|
1042
|
+ cmVectArrayAppendS(p->eVa,yV,xyN);
|
1033
|
1043
|
|
1034
|
1044
|
|
1035
|
1045
|
return cmOkRC;
|
|
@@ -1047,7 +1057,44 @@ cmRC_t cmNlmsEcWrite( cmNlmsEc_t* p, const cmChar_t* dirStr )
|
1047
|
1057
|
|
1048
|
1058
|
if( p->eVa != NULL )
|
1049
|
1059
|
cmVectArrayWriteDirFn(p->eVa, dirStr, "nlms_out.va");
|
1050
|
|
-
|
1051
|
1060
|
|
1052
|
1061
|
return cmOkRC;
|
1053
|
1062
|
}
|
|
1063
|
+
|
|
1064
|
+
|
|
1065
|
+void cmNlmsEcSetMu( cmNlmsEc_t* p, float mu )
|
|
1066
|
+{
|
|
1067
|
+ if( mu < 0 )
|
|
1068
|
+ p->mu = 0.0001;
|
|
1069
|
+ else
|
|
1070
|
+ if( mu >= 1 )
|
|
1071
|
+ p->mu = 0.99;
|
|
1072
|
+ else
|
|
1073
|
+ p->mu = mu;
|
|
1074
|
+}
|
|
1075
|
+
|
|
1076
|
+void cmNlmsEcSetDelayN( cmNlmsEc_t* p, unsigned delayN )
|
|
1077
|
+{
|
|
1078
|
+ if( delayN > p->dN)
|
|
1079
|
+ delayN = p->dN;
|
|
1080
|
+ else
|
|
1081
|
+ if( delayN < 1 )
|
|
1082
|
+ delayN = 1;
|
|
1083
|
+
|
|
1084
|
+ cmVOS_Zero(p->delayV,p->delayN);
|
|
1085
|
+ p->delayN = delayN;
|
|
1086
|
+}
|
|
1087
|
+
|
|
1088
|
+void cmNlmsEcSetIrN( cmNlmsEc_t* p, unsigned hN )
|
|
1089
|
+{
|
|
1090
|
+ if( hN > p->dN )
|
|
1091
|
+ hN = p->dN;
|
|
1092
|
+ else
|
|
1093
|
+ if( hN < 1 )
|
|
1094
|
+ hN = 1;
|
|
1095
|
+
|
|
1096
|
+ cmVOD_Zero(p->wV,p->hN);
|
|
1097
|
+ cmVOD_Zero(p->hV,p->hN);
|
|
1098
|
+ p->hN = hN;
|
|
1099
|
+}
|
|
1100
|
+
|