/***************************************************************************
 *
 *  FILE NAME:  decoder.c
 *
 *         Usage : decoder  bitstream_file  synth_file
 *
 *         Format for bitstream_file:
 *           One word (2-byte) for bad frame indication (BFI) flag bit
 *               0x0000 -> good frame;  0x0001 -> bad frame
 *           244  words (2-byte) containing 244 bits.
 *               Bit 0 = 0x0000 and Bit 1 = 0x0001
 *           One word (2-byte) for ternary Silence Descriptor (SID) flag
 *               0x0000 -> inactive (no detected speech activity);
 *               0x0001 -> active
 *           One word (2-byte) for Time Alignment Flag (TAF) bit
 *               0x0000 -> inactive (no transmission of speech frames);
 *               0x0001 -> active
 *
 *         Format for synth_file:
 *           Synthesis is written to a binary file of 16 bits data.
 *
 ***************************************************************************/

#include "typedef.h"
#include "sig_proc.h"
#include "codec.h"
#include "cnst.h"
#include "d_homing.h"


extern unsigned int
	*GSM2file,
	GSM2size;


extern void
	DMAfromROM( unsigned char *src, unsigned char *dst, signed int size );


Word16 synth_buf[L_FRAME + M];

/* L_FRAME, M, PRM_SIZE, AZ_SIZE, SERIAL_SIZE: defined in "cnst.h" */

/*-----------------------------------------------------------------*
 *             Global variables                                    *
 *-----------------------------------------------------------------*/

Word32
	Filtering = 0;


// Locals...

static Word32
	PlayPtr,
	ReadPtr;


/*-----------------------------------------------------------------*
 *            Main decoder routines                                *
 *-----------------------------------------------------------------*/

void GSM2_Init()
{
    /*-----------------------------------------------------------------*
     *           Initialization of decoder                             *
     *-----------------------------------------------------------------*/

	decoder_reset(); /* Bring the decoder to the initial state */

	PlayPtr = L_FRAME;
	ReadPtr = 0;
}


int GSM2_Play( Word32 *buffer, Word32 size, Word32 lvol, Word32 rvol )
{
    Word16 *synth;              /* Synthesis                  */
static    Word16 parm[PRM_SIZE];  /* Synthesis parameters       */
//    Word16 serial[SERIAL_SIZE+2];/* Serial stream              */
    Word16 Az_dec[AZ_SIZE];     /* Decoded Az for post-filter */
                                /* in 4 subframes, length= 44 */
    Word16 i, temp;

	unsigned int
		bits[8];
	static Word32
		sl_old = 0,
		sr_old = 0;
	Word32
		s,
		sl_mid,
		sr_mid,
		sl_new,
		sr_new;

	lvol <<= 7;
	rvol <<= 7;

	synth = synth_buf + M;

	while (size > 0)
	{
		if (PlayPtr == L_FRAME)
		{
			if (GSM2file == 0 || ReadPtr >= (GSM2size*8))
			{
				return( -1 );
//				GSM2_Init();
//				Filtering = !Filtering;
			}

#if 1

			DMAfromROM( &GSM2file[ReadPtr], bits, 8*4 );
			ReadPtr += 8;

#else

			for (i=0; i<8; i++)
			{
				bits[i] = GSM2file[ReadPtr];
				ReadPtr++;
			}

#endif

			PlayPtr = 0;


			/*-----------------------------------------------------------------*
			 *            Loop for each "L_FRAME" speech data                  *
			 *-----------------------------------------------------------------*/

//        SID_flag = serial[245];         /* Receive SID flag */
//        TAF = serial[246];              /* Receive TAF flag */

			Bits2prm_12k2 (bits, parm);   /* serial to parameters   */

			Decoder_12k2 (parm, synth, Az_dec);/* Synthesis */

			if (Filtering)
				Post_FilterGSM2 (synth, Az_dec);                      /* Post-filter */

#if 0
			for (i = 0; i < L_FRAME; i++) 
					/* Upscale the 15 bit linear PCM to 16 bits,
						 then truncate to 13 bits */
			{
					temp = synth[i] << 1;
					synth[i] = temp & 0xfff8;
			}
#endif
		}


		temp = L_FRAME - PlayPtr;
		temp *= 2;
		if (temp > size)
			temp = size;

		for (i=0; i<temp/2; i++)
		{
			s = synth[PlayPtr];
			PlayPtr++;

			sl_new = (s * lvol) >> 14;
			sr_new = (s * rvol) >> 14;

			sl_mid = (sl_old + sl_new) >> 1;
			sr_mid = (sr_old + sr_new) >> 1;

			sl_old = sl_new;
			sr_old = sr_new;

			*buffer++ += (Word16)sl_mid;
			*buffer++ += (Word16)sr_mid;
			*buffer++ += (Word16)sl_new;
			*buffer++ += (Word16)sr_new;
		}

		size -= temp;
	}

	return( 0 );
}
