#include <speex/speex.h>
#include <speex/speex_preprocess.h>
#include <stdio.h>
#include <inttypes.h>

/*The frame size in hardcoded for this sample code but it doesn't have to be*/
#define FRAME_SIZE 160

int main(int argc, char **argv)
{
   char *outFile;
   FILE *fout;
   /*Holds the audio that will be written to file (16 bits per sample)*/
   short out[FRAME_SIZE];
   /*Speex handle samples as float, so we need an array of floats*/
   float output[FRAME_SIZE];
   char cbits[200];
   uint8_t nbBytes;
   uint8_t flag;
   /*Holds the state of the decoder*/
   void *state;
   /*Holds bits so they can be read and written to by the Speex routines*/
   SpeexBits bits;
   int i, tmp;
   int frame_size, sample_rate;
   /*Holds the preprocessor state */
   SpeexPreprocessState *preprocess_state;

   /*Create a new decoder state in narrowband mode*/
   state = speex_decoder_init(&speex_nb_mode);

   tmp=20;
   speex_decoder_ctl(state, SPEEX_GET_FRAME_SIZE, &tmp);

   /*Set the perceptual enhancement on*/
   tmp=1;
   speex_decoder_ctl(state, SPEEX_SET_ENH, &tmp);

   tmp=8000;
   speex_decoder_ctl(state, SPEEX_SET_SAMPLING_RATE, &tmp);

   tmp=0; 
   speex_decoder_ctl(state, SPEEX_SET_HIGHPASS, &tmp);

   /** Speex preprocessor initialization */
   frame_size = 20; /* Frame lenght 20 ms */
   sample_rate = 8000;
   preprocess_state = speex_preprocess_state_init(frame_size, sample_rate);

   tmp = 1;
   speex_preprocess_ctl(preprocess_state, SPEEX_PREPROCESS_SET_DENOISE, &tmp);

   /* don't write to file */
   if (argc==1)
	fout=NULL;
   else {
   	outFile = argv[1];
   	fout = fopen(outFile, "w");
   }

   /*Initialization of the structure that holds the bits*/
   speex_bits_init(&bits);
   while (1)
   {

#ifdef WITH_PKT_FRAMING
      fread(&flag, sizeof(uint8_t), 1, stdin);

      if (flag==0xFF) {

      fread(&flag, sizeof(uint8_t), 1, stdin);

	      if (flag==0x55) {

	              /*Read the sequence number provided by the audio program on the source mote*/
		      fread(&flag, sizeof(uint8_t), 1, stdin);
#endif

		      fread(&nbBytes, sizeof(uint8_t), 1, stdin);
		      fprintf (stderr, "nbBytes: %d\n", nbBytes);

		      if (feof(stdin))
			 break;

		      // XBeeSendFile would need to fill lost packet with 0x00
		      // so that we could conclude of a packet loss
		      if (nbBytes==0) {
			      // we hardcoded the value for speex at 8000bps
			      nbBytes=0x14;

			      /*Read the "packet" encoded by sampleenc*/
			      fread(cbits, 1, nbBytes, stdin);
			      /*Copy the data into the bit-stream struct*/
			      speex_bits_read_from(&bits, cbits, nbBytes);
				
                              speex_decode_int(state, NULL, out);
		      } else {
			      /*Read the "packet" encoded by sampleenc*/
			      fread(cbits, 1, nbBytes, stdin);
			      /*Copy the data into the bit-stream struct*/
			      speex_bits_read_from(&bits, cbits, nbBytes);

			      /*Decode the data*/
			      //speex_decode(state, &bits, output);
			      speex_decode_int(state, &bits, out);

			      /*
			      //Copy from float to short (16 bits) for output
			      for (i=0;i<FRAME_SIZE;i++) {
				 out[i]=output[i];

			      }
			      */
		      }

		      /*Write the decoded audio to file*/
		      if (argc>1)
		      	fwrite(out, sizeof(short), FRAME_SIZE, fout);

		      //also write to stdout
		      fwrite(out, sizeof(short), FRAME_SIZE, stdout);
#ifdef WITH_PKT_FRAMING
		}
	}
#endif
   }
   
   /*Destroy the decoder state*/
   speex_decoder_destroy(state);
   /*Destroy the bit-stream truct*/
   speex_bits_destroy(&bits);
   fclose(fout);
   return 0;
}
