%function that tries to implement a more or less real time version of the
%GSC
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [output_c,error_c,desired,noise,output_g,error_g] = GSC_rt(signal,vad_on)
%make sure we use the global variabels
global calibrated;global fs;global adapt;global P_ref;
global Wd,global Nd;global mud;
global Wn,global Nn;global mun;
global tic_it;tic_it = 0;

%set a value for the delay incorporated in the GSC
delay = Nd/2;

%initialize an adapt vector that can be used to set the adaptation
%intervals
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
adapt = [0 zeros(1,0.05e5) zeros(1,0.45e5) ones(1,0.65e5) zeros(1,0.45e5) ones(1,0.6e5) zeros(1,0.55e5) ones(1,0.75e5)];

%initialisation/calculation of P_ref
if (vad_on == 1)
   %set a time interval used for the vad detection
   frametime = 0.030; %specify the time a vad frame should last in seconds
   framesize = frametime*fs;
   %first initializations of apt and adapt
   apt = 0;
   adapt = [];
end

%runs a calibration session if required
if (calibrated ~= 1)
    tic
    calibration;
    toc
else
   output_c = [];error_c = [];
end

%initialize different vectors required for correct operation of the GSC
%loop
d_buffer = zeros(1,delay);n_buffer = [];output_g = [];output_delay = [];error_g = [];
desired = [];noise = [];vad_buffer = [];
%initialize a first old vector
old = zeros(Nn,1);
%initialize a first filter coeff. vector Wn
Wn = [zeros(2*Nn,1)];

%start of the while loop performing the operations
k=0;
display('The GSC is doing its job')

tic_it = 1;

tic
while (length(signal)-(k*Nd+Nd) >= 0)
    if (k == 0)
        x = [zeros(Nd,1);signal(1:Nd,2)];
        d = signal(1:Nd,1);
    else
        x = signal((k*Nd-Nd)+1:(k*Nd+Nd),2);
        d = signal((k*Nd+1):(k*Nd+Nd),1);
    end
    %calculate the output of the channel delay filter
    [out,err,a] = fdaf_lms(x,d,Wd,Nd,mud,0);
    output_delay = [output_delay,out'];
    
    %obtain a desired and a noise reference signal (of course they hav to
    %be added block by block
    desired_buf = d + out;desired = [desired desired_buf'];
    noise_buf = d - out;noise = [noise noise_buf'];
    
    %create a sort of buffer for your desired/noise blocks, to make it
    %possible for both filters to work with a different length
    d_buffer = [d_buffer desired_buf'];
    n_buffer = [n_buffer noise_buf'];
    
    %vad if required by the user
    if (vad_on == 1)
       vad_buffer = [vad_buffer  desired_buf'];
       
       %if the buffersize exceeds the frame length, check if there is
       %speech in the frames
       if (length(vad_buffer) >= framesize)
          apt =  vad(vad_buffer(1:framesize)');
          vad_buffer = vad_buffer(framesize+1:end);
          adapt = [adapt apt];
       end
       
    end
    
    if (length(n_buffer) >= Nn)
        x2 = [old;n_buffer(1,1:Nn)'];
        d2 = d_buffer(1,1:Nn)';
        
        %keep the old values of the noise buffer for the next step
        old = n_buffer(1,1:Nn)';
        
        %time to perform the GSC adaptive filtering
        if (vad_on == 1)
            [out1,err1,Wn] = fdaf_lms(x2,d2,Wn,Nn,mun,apt);
        else
            [out1,err1,Wn] = fdaf_lms(x2,d2,Wn,Nn,mun,adapt(Nn/2));
            adapt = adapt(1,Nn+1:end);
        end
        output_g = [output_g out1'];
        error_g = [error_g err1'];
        
        %adapt length of buffers/adapt signal, to show that data where read
        d_buffer = d_buffer(1,Nn+1:end);
        n_buffer = n_buffer(1,Nn+1:end);
        
    end
    k = k+1;
end
toc
