/* aec_test.cpp
 *
 * Copyright (C) DFS Deutsche Flugsicherung (2004). All Rights Reserved.
 *
 * Test stub for Acoustic Echo Cancellation NLMS-pw algorithm
 * Author: Andre Adrian, DFS Deutsche Flugsicherung
 * <Andre.Adrian@dfs.de>
 *
 * fortune says:
 * It's never as good as it feels, and it's never as bad as it seems.
 *
 * compile
c++ -DWIDEB=2 -O2 -o aec_test aec_test.cpp aec.cpp tcp.cpp -lm
 *
 * Version 1.3 set/get ambient in dB
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

#include "tcp.h"
#include "aec.h"

#define TAPS  	(40*WIDEB*8)

typedef signed short MONO;

float dB2q(float dB)
{
  /* Dezibel to Ratio */
  return powf(10.0f, dB / 20.0f);
}

float q2dB(float q)
{
  /* Ratio to Dezibel */
  return 20.0f * log10f(q);
}

/* Read a raw audio files (8KHz sample frequency, 16bit PCM, mono)
 * from stdin, echo cancel it and write it to stdout
 */
int main(int argc, char *argv[])
{
  MONO inbuf_speaker[TAPS], inbuf_mic[TAPS], outbuf[TAPS];
  float visualize;

  fprintf(stderr, "usage: aec_test [ambient in dB] speaker.raw mic.raw out.raw\n");

  AEC aec;

  // ambient in dB
  aec.setambient(MAXPCM*dB2q(0.0));    

  FILE *fspeaker = fopen("speaker.raw", "rb");
  if (!fspeaker) {
    fprintf(stderr, "Failed to open 'speaker.raw', exit.\n");
    exit(EXIT_FAILURE);
  }
  
  FILE *fmic = fopen("mic.raw", "rb");
  if (!fmic) {
    fprintf(stderr, "Failed to open 'mic.raw', exit.\n");
    exit(EXIT_FAILURE);
  }

  FILE *fout = fopen("out.raw", "wb");      
  if (!fout) {
    fprintf(stderr, "Failed to open 'out.raw', exit.\n");
    exit(EXIT_FAILURE);
  }

  int taps_speaker, taps_mic;
  float ambient;
  while (true) {
    int i;
    
    taps_speaker = fread(inbuf_speaker, sizeof(MONO), TAPS, fspeaker);
    taps_mic = fread(inbuf_mic, sizeof(MONO), TAPS, fmic);    
    
    if (taps_speaker != TAPS || taps_mic != TAPS)
      break;
    
    
    for (i = 0; i < TAPS; ++i) {
      int s0 = inbuf_mic[i];      /* left channel microphone */
      int s1 = inbuf_speaker[i];      /* right channel speaker */

      /* and do NLMS */
      s0 = aec.doAEC(s0, s1);
      
      /* output one internal variable */
      // visualize = 16 * aec.hangover;
      visualize = 32000 * aec.stepsize;
      
      outbuf[i] = s0;         /* right channel echo cancelled mic */
    }

    fwrite(outbuf, sizeof(MONO), TAPS, fout);
  }
  ambient = aec.getambient();
  float ambientdB = q2dB(ambient / 32767.0f);
  fprintf(stderr, "Ambient = %2.0f dB\n", ambientdB);

  return EXIT_SUCCESS;
}
