
#include "speech_cwrs.h"
#include "basic_op.h"
#include "rc_encode.h"
#include "rc_decode.h"


#ifndef HW_CWRS
static const unsigned int BLE_PVQ_U_DATA[278]=
#else
static const unsigned int BLE_PVQ_U_DATA[228]=
#endif
{
#ifndef HW_CWRS
	/////////////////////////  [0]  25°³ //////////////////////////////// BLE_PVQ_U_DATA
	1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
	///////////////////////// [1] 25°³//////////////////////////////  BLE_PVQ_U_DATA+25
	0,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
#endif
	///////////////////////// [2] 25°³//////////////////////////////   BLE_PVQ_U_DATA+50
	1, 1,3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41,43, 45, 47,
	///////////////////////// [3] 25°³//////////////////////////////    BLE_PVQ_U_DATA+75
	347, 349, 351,13, 25, 41, 61, 85, 113, 145, 181, 221, 265, 313, 365, 421, 481, 545, 613,
	685, 761, 841, 925, 1013, 1105,
	//////////////////////////// [4] 25°³ ///////////////////////////////BLE_PVQ_U_DATA+100
	59513, 60205, 60901, 61601,63,   129,  231,  377,  575,  833,
	1159,  1561,  2047,  2625, 3303, 4089, 4991, 6017, 7175, 8473,
	9919, 11521, 13287, 15225, 17343, //19649, 22151, 24857, 27775,

	///////////////////////// [5] 25°³//////////////////////////////  BLE_PVQ_U_DATA+125
	6725887, 6844225, 6963943, 7085049, 7207551,321, 681, 1289, 2241, 3649,
	5641, 8361, 11969, 16641, 22569, 29961, 39041, 50049, 63241, 78889,
	97281, 118721, 143529, 172041, 204609, //241601, 283401,330409, 383041,

	///////////////////////// [6] 25°³////////////////////////////// BLE_PVQ_U_DATA+150
	563454121, 576788929, 590359041, 604167209, 618216201, 632508801, 1683, 3653, 7183, 13073,
	22363, 36365, 56695, 85305, 124515, 177045, 246047, 335137, 448427, 590557,
	766727, 982729, 1244979, 1560549, 1937199, // 2383409,2908411, 3522221, 4235671,

	///////////////////////// [7] 19°³////////////////////////////// BLE_PVQ_U_DATA+175
	1532817275, 1620351277, 1711839767, 1807415257, 1907213187,2011371957, 2120032959,8989, 19825, 40081,
	75517, 134245, 227305, 369305, 579125, 880685, 1303777,1884961, 2668525,
	//	3707509, 5064793, 6814249, 9041957, 11847485, 15345233,19665841, 24957661, 31388293, 39146185,


	///////////////////////// [8] 19°³//////////////////////////////  BLE_PVQ_U_DATA+194
	904317037, 1027188385, 1163673953, 1314955181, 1482288821,1667010073, 1870535785, 2094367717, 48639, 108545,
	224143, 433905, 795455, 1392065, 2340495, 3800305, 5984767, 9173505, 13726991,
	//	20103025, 28875327, 40754369, 56610575, 77500017,104692735, 139703809, 184327311, 240673265, 311207743,

	///////////////////////// [9] 19°³//////////////////////////////   BLE_PVQ_U_DATA+213
	398796225, 506750351,638878193, 799538175, 993696769, 1226990095, 1505789553, 1837271615, 2229491905U,265729,
	598417, 1256465, 2485825, 4673345, 8405905, 14546705, 24331777,39490049, 62390545,
	///////////////////////// [10] 14°³//////////////////////////////    BLE_PVQ_U_DATA+232
	96220561, 145198913, 214828609, 312193553, 446304145,
	628496897, 872893441, 1196924561, 1621925137, 2173806145U,
	1462563, 3317445, 7059735, 14218905,
	///////////////////////// [11] 8°³//////////////////////////////   BLE_PVQ_U_DATA+246
	27298155, 50250765, 89129247, 152951073,
	254831667, 413442773, 654862247, 1014889769,
	///////////////////////// [12] 6°³ //////////////////////////////  BLE_PVQ_U_DATA+254
	1541911931, 2300409629U,
	3375210671U,
	8097453, 18474633, 39753273,
	///////////////////////// [13] 3°³//////////////////////////////   BLE_PVQ_U_DATA+260
	81270333, 158819253, 298199265,
	///////////////////////// [14] 15°³////////////////////////////// BLE_PVQ_U_DATA+263
	540279585,
	948062325, 1616336765,
	45046719, 103274625, 224298231, 464387817, 921406335, 1759885185,
	3248227095U,
	251595969, 579168825, 1267854873, 2653649025U,
	1409933619,
};

#ifndef HW_CWRS
static const unsigned int *const BLE_PVQ_U_ROW[15]={
	BLE_PVQ_U_DATA,BLE_PVQ_U_DATA+25,BLE_PVQ_U_DATA+ 50,
	BLE_PVQ_U_DATA+ 75,BLE_PVQ_U_DATA+ 100,BLE_PVQ_U_DATA+125,
	BLE_PVQ_U_DATA+150,BLE_PVQ_U_DATA+175,BLE_PVQ_U_DATA+194,
	BLE_PVQ_U_DATA+213,BLE_PVQ_U_DATA+232,BLE_PVQ_U_DATA+246,
	BLE_PVQ_U_DATA+254,BLE_PVQ_U_DATA+260,BLE_PVQ_U_DATA+263
};
#else
static const unsigned int *const BLE_PVQ_U_ROW[15]={
	BLE_PVQ_U_DATA,BLE_PVQ_U_DATA,BLE_PVQ_U_DATA,
	BLE_PVQ_U_DATA+ 25,BLE_PVQ_U_DATA+ 50,BLE_PVQ_U_DATA+75,
	BLE_PVQ_U_DATA+100,BLE_PVQ_U_DATA+125,BLE_PVQ_U_DATA+144,
	BLE_PVQ_U_DATA+163,BLE_PVQ_U_DATA+182,BLE_PVQ_U_DATA+196,
	BLE_PVQ_U_DATA+204,BLE_PVQ_U_DATA+210,BLE_PVQ_U_DATA+213
};

#endif





static unsigned int icwrs(short _n,const short *_y)
//unsigned int icwrs(short _n,const short *_y)
{
	unsigned int i;
	short j, k;
	short tmp = 2;
	j=_n-1;

	if(_y[j]<0)
	{
		i = 1;
		k = -_y[j];
	}
	else
	{
		i = 0;
		k = _y[j];
	}

	do{
		j--;
		if(k>tmp)
			i = i+BLE_PVQ_U_ROW[tmp][k];
		else
#ifndef HW_CWRS
			i = i+BLE_PVQ_U_ROW[k][tmp];
#else
			i+=((k<2)?k:BLE_PVQ_U_ROW[k][tmp]);
#endif


#ifndef HW_HIFI3
		k+=ABS(_y[j]);
#else
		k+=(short)(ABS(_y[j]));
#endif
		if(_y[j]<0)
		{
			if((k+1)>tmp)
				i = i+BLE_PVQ_U_ROW[tmp][k+1];
			else
#ifndef HW_CWRS
				i = i+BLE_PVQ_U_ROW[k+1][tmp];
#else
				i+=((k==0)?1:BLE_PVQ_U_ROW[k+1][tmp]);
#endif
		}
		tmp++;
	}while(j);

	return i;
}



static void cwrsi(short _n,short _k,unsigned int _i,short *_y)
{
	unsigned int p;
	int s, k0;

	while(_n>2)
	{
		unsigned int q;
		/*Lots of pulses case:*/
		if(_k>=_n)
		{
			const unsigned int *row;
			row=BLE_PVQ_U_ROW[_n];
			/*Are the pulses in this dimension negative?*/
			p=row[_k+1];
			s=-(_i>=p);
			_i-=p&s;
			/*Count how many pulses were placed in this dimension.*/
			k0=_k;
			q=row[_n];

			if(q>_i){
			_k=_n;
#ifndef HW_CWRS
			do p=BLE_PVQ_U_ROW[--_k][_n];
			while(p>_i);
#else
			do
			{
				_k--;
				p = (_k<2)?_k:BLE_PVQ_U_ROW[_k][_n];
			}	while(p>_i);

#endif
			}


			else
#ifndef HW_CWRS
				for(p=row[_k];p>_i;p=row[_k])_k--;
#else
			{
					p=row[_k];
					while(p>_i)
					{
						p = row[--_k];
					}
			}
#endif
			_i-=p;
			*_y++=(k0-_k+s)^s;
		}
		/*Lots of dimensions case:*/
		else{
			/*Are there any pulses in this dimension at all?*/

#ifndef HW_CWRS
			p=BLE_PVQ_U_ROW[_k][_n];
			q=BLE_PVQ_U_ROW[_k+1][_n];
#else
			if(_k==0)
			{
				p=0;
				q=1;
			}
			else
			{
				p=(_k==1)?_k:BLE_PVQ_U_ROW[_k][_n];
				q=BLE_PVQ_U_ROW[_k+1][_n];
			}
#endif
			if(p<=_i&&_i<q)
			{
				_i-=p;
				*_y++=0;
			}else{
				/*Are the pulses in this dimension negative?*/
				s=-(_i>=q);
				_i-=q&s;
				/*Count how many pulses were placed in this dimension.*/
				k0=_k;
				do
#ifndef HW_CWRS
					p=BLE_PVQ_U_ROW[--_k][_n];
#else
				{
					_k--;
					p=(_k<2)?_k:BLE_PVQ_U_ROW[_k][_n];
				}
#endif
				while(p>_i);
				_i-=p;
				*_y++=(k0-_k+s)^s;
			}
		}
		_n--;
	}
	/*_n==2*/
	p=(_k<<1)+1;
	s=-(_i>=p);
	_i-=p&s;
	k0=_k;
	_k=(_i+1)>>1;
	if(_k)
		_i-= (_k<<1)-1;
	*_y++=(k0-_k+s)^s;
	/*_n==1*/
	s=-(int)_i;
	*_y=(_k+s)^s;
}



unsigned int code_pulses(short _n,short _k)
{
	unsigned int audio_pvq;

	if(_k>=_n)
	{
		audio_pvq = BLE_PVQ_U_ROW[_n][_k]+ BLE_PVQ_U_ROW[_n][_k+1];
	}
	else
	{
#ifndef HW_CWRS
		audio_pvq = BLE_PVQ_U_ROW[_k][_n]+ BLE_PVQ_U_ROW[_k+1][_n];
#else
		if(_k==0)
		{
			audio_pvq = 1;
		}
		else
		{
			audio_pvq = BLE_PVQ_U_ROW[_k+1][_n] + ((_k==1)?1:BLE_PVQ_U_ROW[_k][_n]);
		}
#endif
	}
	return audio_pvq;
}



void encode_pulses(const short *_y, short _n, short _k, ec_enc *_enc)
{
	rc_enc_uint_1(_enc, icwrs(_n,_y), code_pulses(_n, _k));
}




void decode_pulses(short *_y,short _n,short _k,ec_dec *_dec)
{
	cwrsi(_n,_k,rc_dec_uint(_dec,code_pulses(_n, _k)),_y);
}

