瀏覽代碼

cmProc5.h/c : Added parameter setters to cmNlmsEc.

master
kevin 9 年之前
父節點
當前提交
2d1f53c3d0
共有 2 個文件被更改,包括 84 次插入31 次删除
  1. 75
    28
      cmProc5.c
  2. 9
    3
      cmProc5.h

+ 75
- 28
cmProc5.c 查看文件

@@ -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
+

+ 9
- 3
cmProc5.h 查看文件

@@ -234,6 +234,9 @@ extern "C" {
234 234
     float          mu;          // LMS step rate
235 235
     unsigned       hN;          // filter length
236 236
     unsigned       delayN;      // fixed delay to apply to align xV with fV.
237
+    unsigned       dN;          // max length of the fixed delay
238
+    cmSample_t*    delayV;      // delayV[ dN ] fixed delay buffer[]
239
+    unsigned       di;          // delay index
237 240
     double*        wV;          // wV[hN] filter weights
238 241
     double*        hV;          // hV[hN] filter delay line    
239 242
     unsigned       w0i;         // The index into hV[] of the start of the delay line.
@@ -243,9 +246,9 @@ extern "C" {
243 246
     cmVectArray_t* eVa;
244 247
   } cmNlmsEc_t;
245 248
 
246
-  cmNlmsEc_t* cmNlmsEcAlloc( cmCtx* ctx, cmNlmsEc_t* p, float mu, unsigned hN, unsigned delayN );
249
+  cmNlmsEc_t* cmNlmsEcAlloc( cmCtx* ctx, cmNlmsEc_t* p, double srate, float mu, unsigned hN, unsigned delayN );
247 250
   cmRC_t      cmNlmsEcFree( cmNlmsEc_t** pp );
248
-  cmRC_t      cmNlmsEcInit( cmNlmsEc_t* p, float mu, unsigned hN, unsigned delayN );
251
+  cmRC_t      cmNlmsEcInit( cmNlmsEc_t* p, double srate, float mu, unsigned hN, unsigned delayN );
249 252
   cmRC_t      cmNlmsEcFinal( cmNlmsEc_t* p );
250 253
   
251 254
   // xV[] unfiltered reference signal  (direct from xform output)
@@ -253,7 +256,10 @@ extern "C" {
253 256
   // yV[] echo-canelled signal 
254 257
   cmRC_t      cmNlmsEcExec( cmNlmsEc_t* p, const cmSample_t* xV, const cmSample_t* fV, cmSample_t* yV, unsigned xyN );
255 258
   cmRC_t      cmNlmsEcWrite( cmNlmsEc_t* p, const cmChar_t* dir );
256
-  
259
+
260
+  void        cmNlmsEcSetMu(     cmNlmsEc_t* p, float mu );
261
+  void        cmNlmsEcSetDelayN( cmNlmsEc_t* p, unsigned delayN );
262
+  void        cmNlmsEcSetIrN(    cmNlmsEc_t* p, unsigned irN );
257 263
   
258 264
   
259 265
 #ifdef __cplusplus

Loading…
取消
儲存