// adaptive filter : noise canceller
//
//  s -------------->(+)-----------+ d
//                    ^            |
//            +---+   |            v +
//       +--->| H +---+      ^    (+)---+---> e
//       |    +---+ ndash    |     ^ -  |
//       |                 +---+   |    |
//  n ---+---------------->| w +---+    |
//                         +---+ y      |
//                           |          |
//                           +----------+

clear;
stacksize('max');

DATLEN=400000;                                     // simulation data length
ADPLEN=30;                                         // adaptive filter length
MU=0.0003;                                         // step size parameter

in_s=loadwave('male.wav');                         // male voice
//in_s=loadwave('female.wav');                     // female voice
DATLEN=min([DATLEN, length(in_s)]);
in_s=in_s(1:DATLEN);
rand('normal');
in_n=rand(1:DATLEN)/4;

out_d=zeros(1:DATLEN);
out_e=zeros(1:DATLEN);
out_d_minus_n=zeros(1:DATLEN);

wbuf=zeros(1:ADPLEN);
w=zeros(1:ADPLEN);
nbuf=zeros(1:10);
zndash=0;
for i=1:DATLEN
    
  s=in_s(i);
  n=in_n(i);
 
  nbuf=[n, nbuf(1:length(nbuf)-1)];
  ndash=0.6*nbuf(3)-0.7*nbuf(4)+nbuf(length(nbuf))-0.3*zndash;
  zndash=ndash;
   
  d=s+ndash;

  wbuf=[n, wbuf(1:ADPLEN-1)];
  y=wbuf*w';
  e=d-y;
  w=w+2*MU*e*wbuf;
  
  out_d(i)=d;
  out_e(i)=e;
  out_d_minus_n(i)=d-n;
  
end

scf(0); clf; plot2d(w);
scf(1); clf; plot2d(out_e);

savewave('in_d_noise_cancel.wav', 0.99*out_d/max(abs(out_d)), 8000);
savewave('out_e_noise_cancel.wav', 0.99*out_e/max(abs(out_e)), 8000);
savewave('out_d_minus_n_noise_cancel.wav', 0.99*out_d_minus_n/max(abs(out_d_minus_n)), 8000);

