
#include "ssc_quant.h"
#include "copy.h"
#include "basic_op.h"
#include "math_op.h"
#include "ssc_pulsealloc.h"
#include "laplace.h"
#include "rc_encode.h"
#include "rc_decode.h"


//extern int count;

#ifndef HW_CODESIZE
static const unsigned char e_prob_model[2][32] = {
	{
		61,  90,  93,  60, 105,  42, 107,  41, 110,  45, 116,  38, 113,  38,
		112,  38, 124,  26, 132,  27, 136,  19, 140,  20, 155,  14, 159,  16,
		158,  18, 170, 13
	},
	/*Intra*/
	{
		21, 178,  59, 110,  71,  86,  75,  85,  84,  83,  91,  66,  88,  73,
		87,  72,  92,  75,  98,  72, 105,  58, 107,  54, 115,  52, 114,  55,
		112,  56, 129,  51
	}
};
#else
static const unsigned char e_prob_model[32] = {
	61,  90,  93,  60, 105,  42, 107,  41, 110,  45, 116,  38, 113,  38,
	112,  38, 124,  26, 132,  27, 136,  19, 140,  20, 155,  14, 159,  16,
	158,  18, 170, 13
};
#endif



#ifndef HW_CODESIZE
static short loss_distortion(const short *eBands, short *oldEBands, short end)
{
	short i;
	int dist = 0;
	for(i=0;i<end;i++)
	{
		short d = SSC_SUB(SHR(eBands[i], 3), SHR(oldEBands[i], 3));
		dist += SSC_MULT16x16(d, d);
	}

/*
	if(dist>8388608)
	{
		printf("xx");
	}
*/
	return SPEECH_MIN(200,SHR(dist,14));
}

#endif






#ifndef HW_CODESIZE
static int quant_coarse_energy_impl(const SpeechMode *m, int end,
		const short *eBands, short *oldEBands,
		short budget, short tell,
		const unsigned char *prob_model, short *error, ec_enc *enc,
		short intra, short max_decay)
#else

#ifndef HW_CODESIZE
static int quant_coarse_energy_impl(const SpeechMode *m, int end,
		const short *eBands, short *oldEBands,
		short budget, short tell,
		const unsigned char *prob_model, short *error, ec_enc *enc, short max_decay)
#else
void quant_coarse_energy(const SpeechMode *m, short end,
		const short *eBands, short *oldEBands,
		unsigned short budget, short *error, ec_enc *enc, short max_decay)
#endif

#endif
{
#ifndef HW_CODESIZE
	int badness = 0;
#endif
	short i;
	int prev = 0;

#ifndef HW_CODESIZE
	short coef, beta;
	if (tell+3 <= budget) rc_enc_bit_logp_1(enc, intra, 3);
	if (intra)
	{
		coef = 0;
		beta = 4915;
	} else {
		beta = 12124;
		coef = 21248;
	}
#else
	short coef = 21248, beta=12124;
	short tell = ec_tell(enc);
	const unsigned char *prob_model = e_prob_model;


	if (tell+3 <= budget) rc_enc_bit_logp_1(enc, 0, 3);   // ¾µµ¥¾ø´Â bit »ç¿ë.
#endif


	/* Encode at a fixed coarse resolution */
	for (i=0;i<end;i++)
	{
		short bits_left;
		short x, qi, qi0;
		int q, f, tmp;
		short oldE;
		short decay_bound;


//		int test;

		x = eBands[i];
		oldE = SPEECH_MAX(-9216, oldEBands[i]);

#ifndef HW_CODESIZE
		f = SHL(EXTEND32(x),7) - SSC_PSHR(SSC_MULT16x16(coef,oldE), 8) - prev;
#else


#ifndef VC_PROJ
		f = SHL(EXTEND32(x),7) - SRAImmediate(SSC_MULT16x16(coef,oldE)+128, 8) - prev;
#else
		f = SHL(EXTEND32(x),7) - SHR(SSC_MULT16x16(coef,oldE)+128, 8) - prev;
#endif
#endif


		/* Rounding to nearest integer here is really important! */
		qi = (short)((f+65536)>>(17));
		decay_bound = EXTRACT16(SPEECH_MAX(-3670016, SSC_SUB((int)oldEBands[i],max_decay)));

		if (qi < 0 && x < decay_bound)
		{
			qi += (int)SHR(SSC_SUB(decay_bound,x), DB_SHIFT);
			if (qi > 0) qi = 0;
		}
		qi0 = qi;

		tell = ec_tell(enc);
#ifndef HW_HIFI3
		bits_left = budget-tell-3*(end-i);
#else
		bits_left = budget-tell-SSC_MULT16x16(3,(end-i));
#endif
		if (i!=0 && bits_left < 30)
		{
			if (bits_left < 24) qi = SPEECH_MIN(1, qi);
			if (bits_left < 16) qi = SPEECH_MAX(-1, qi);
		}


		if (budget-tell >= 15)
		{
			short pi = i<<1;
			rc_laplace_encode(enc, &qi, prob_model[pi]<<7, prob_model[pi+1]<<6);
		} else{
			qi = -1;
		}

#ifndef HW_CODESIZE
		error[i] = SSC_PSHR(f,7) - SHL(qi,DB_SHIFT);
		badness += ABS(qi0-qi);
#else
	//	error[i] = SHR(f+64,7) - SHL(qi,DB_SHIFT);

#ifndef VC_PROJ
		error[i] = SRAImmediate(f+64,7) - SHL(qi,DB_SHIFT);
#else
		error[i] = SHR(f+64,7) - SHL(qi,DB_SHIFT);
#endif
	//	badness += ABS(qi0-qi);
#endif

		q = (int)SHL(EXTEND32(qi),DB_SHIFT);
#ifndef HW_CODESIZE
		tmp = SSC_PSHR(SSC_MULT16x16(coef,oldE),8) + prev + SHL(q,7);
#else
#ifndef VC_PROJ
		tmp = SRAImmediate(SSC_MULT16x16(coef,oldE)+128,8) + prev + SHL(q,7);
#else
		tmp = SSC_PSHR(SSC_MULT16x16(coef,oldE),8) + prev + SHL(q,7);
#endif
#endif
		tmp = SPEECH_MAX(-3670016, tmp);

#ifndef HW_CODESIZE
		oldEBands[i] = SSC_PSHR(tmp, 7);
		prev = prev + SHL(q,7) - SSC_MULT16x16(beta,SSC_PSHR(q,8));
#else
#ifndef VC_PROJ
		oldEBands[i] = SRAImmediate(tmp+64, 7);
		prev = prev + SHL(q,7) - SSC_MULT16x16(beta,SRAImmediate(q+128,8));
#else
		oldEBands[i] = SSC_PSHR(tmp, 7);
		prev = prev + SHL(q,7) - SSC_MULT16x16(beta,SSC_PSHR(q,8));
#endif
#endif
	}

#ifndef HW_CODESIZE
	return badness;
#endif

}

void amp2Log2(const SpeechMode *m, short effEnd, int *bandE, short *bandLogE)
{
	short i;

	int rMAC;

	for (i=0;i<effEnd;i++)
	{
		rMAC = bandE[i];
		if(bandE[i] != EPSILON)
		{
			rMAC = rMAC<<8;
		}

		bandLogE[i] =speech_log2(rMAC)- SHL((short)eMeans[i],6);
	}
}



void quant_fine_energy(const SpeechMode *m, short end, short *oldEBands, short *error, short *fine_quant, ec_enc *enc)
{
	short i;
	/* Encode finer resolution */




	for (i=0;i<end;i++)
	{
		short frac = 1<<fine_quant[i];

		if (fine_quant[i] <= 0) continue;
		{
			short q2, offset;
			/* Has to be without rounding */
			q2 = (error[i]+512)>>(DB_SHIFT-fine_quant[i]);
			if (q2 > frac-1) q2 = frac-1;
			if (q2<0) q2 = 0;
			rc_enc_bits_1(enc, q2, fine_quant[i]);
			offset = SSC_SUB(SHR(SHL(EXTEND32(q2),DB_SHIFT)+512,fine_quant[i]),512);
			oldEBands[i] += offset;
			error[i] -= offset;
		}
	}
}

void quant_energy_finalise(const SpeechMode *m, short end, short *oldEBands, short *error, short *fine_quant, short *fine_priority, short bits_left, ec_enc *enc)
{
	short i, prio;

//	bits_left = 10;
	/* Use up the remaining bits */
	for (prio=0;prio<2;prio++)
	{
		for (i=0;i<end && bits_left>=1 ;i++)
		{
			if (fine_quant[i] >= MAX_FINE_BITS || fine_priority[i]!=prio) continue;
			{
				short q2, offset;
				q2 = error[i]<0 ? 0 : 1;
				rc_enc_bits_1(enc, q2, 1);
				offset = SHR(SHL(q2,DB_SHIFT)-512,fine_quant[i]+1);
				oldEBands[i] += offset;
				bits_left--;
			}
		}
	}
}

#ifndef HW_CODESIZE
void unquant_coarse_energy(const SpeechMode *m, short end, short *oldEBands, short intra, ec_dec *dec)
#else
void unquant_coarse_energy(const SpeechMode *m, short end, short *oldEBands, ec_dec *dec)
#endif
{
#ifndef HW_CODESIZE
   const unsigned char *prob_model = e_prob_model[intra];
#else
   const unsigned char *prob_model = e_prob_model;
#endif
   short coef, beta, i;
   int prev = 0;
   short budget;
   short tell;
#ifndef HW_CODESIZE
   if (intra)
   {
      coef = 0;
      beta = 4915;
   } else {
	   beta = 12124;
	   coef = 21248;
   }
#else
   beta = 12124;
   coef = 21248;
#endif


   budget = (dec->storage<<3);

   /* Decode at a fixed coarse resolution */
   for (i=0;i<end;i++)
   {
         int qi, q, tmp;
         tell = ec_tell(dec);
		 if(budget-tell>=15)
		 {
			 short pi;
			 pi = i<<1;
			 qi = rc_laplace_decode(dec, prob_model[pi]<<7, prob_model[pi+1]<<6);
		 }
		 else
			 qi = -1;

         q = (int)SHL(EXTEND32(qi),DB_SHIFT);
		 oldEBands[i] = SPEECH_MAX(-9216, oldEBands[i]);
#ifndef HW_CODESIZE
		 tmp = SSC_PSHR(SSC_MULT16x16(coef,oldEBands[i]),8) + prev + SHL(q,7);
#else
#ifndef VC_PROJ
		 tmp = SRAImmediate(SSC_MULT16x16(coef,oldEBands[i])+128,8) + prev + SHL(q,7);
#else
		 tmp = SSC_PSHR(SSC_MULT16x16(coef,oldEBands[i]),8) + prev + SHL(q,7);
#endif
#endif
		 tmp = SPEECH_MAX(-3670016, tmp);
#ifndef HW_CODESIZE
         oldEBands[i] = SSC_PSHR(tmp, 7);
		 prev = prev + SHL(q,7) - SSC_MULT16x16(beta,SSC_PSHR(q,8));
#else
#ifndef VC_PROJ
		 oldEBands[i] = SRAImmediate(tmp+64,7);
		 prev = prev + SHL(q,7) - SSC_MULT16x16(beta,SRAImmediate(q+128,8));
#else
		 oldEBands[i] = SSC_PSHR(tmp, 7);
		 prev = prev + SHL(q,7) - SSC_MULT16x16(beta,SSC_PSHR(q,8));
#endif
#endif
   }
}

void unquant_fine_energy(const SpeechMode *m, short end, short *oldEBands, short *fine_quant, ec_dec *dec)
{
   /* Decode finer resolution */
   short i;
   for (i=0;i<end;i++)
   {
		short q2, offset;
		if (fine_quant[i] <= 0) continue;
		q2 = rc_dec_bits(dec, fine_quant[i]);
		offset = SSC_SUB(SHR(SHL(EXTEND32(q2),DB_SHIFT)+512,fine_quant[i]),512);
		oldEBands[i] += offset;
   }
}




void unquant_energy_finalise(const SpeechMode *m, short end, short *oldEBands, short *fine_quant,  short *fine_priority, short bits_left, ec_dec *dec)
{
   short i, prio;
   /* Use up the remaining bits */
   for (prio=0;prio<2;prio++)
   {
	  for (i=0;i<end && bits_left>=1 ;i++)
      {
         if (fine_quant[i] >= MAX_FINE_BITS || fine_priority[i]!=prio)
            continue;
		 {
            int q2;
            short offset;
            q2 = rc_dec_bits(dec, 1);
			 offset = SHR(SHL(q2,DB_SHIFT)-512,fine_quant[i]+1);
            oldEBands[i] += offset;
            bits_left--;
		 }
      }
   }
}


