/*
 * Project 25 IMBE Encoder/Decoder Fixed-Point implementation
 * Developed by Pavel Yazev E-mail: pyazev@gmail.com
 * Version 1.0 (c) Copyright 2009
 * 
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 * 
 * The software is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this; see the file COPYING.  If not, write to the Free
 * Software Foundation, Inc., 51 Franklin Street, Boston, MA
 * 02110-1301, USA.
 */

#include "typedef.h"
#include "globals.h"
#include "imbe.h"
#include "basic_op.h"
#include "ch_decode.h"
#include "aux_sub.h"


void decode_frame_vector(IMBE_PARAM *imbe_param, Word16 *frame_vector)
{
	Word16 bit_stream[BIT_STREAM_LEN];
	Word16 i, vec_num, tmp, tmp1, tmp2, bit_thr, shift;
	Word16 *b_ptr, *ba_ptr, index0;
	Word32 L_tmp;

	imbe_param->b_vec[0] = (shr(frame_vector[0], 4) & 0xFC) | (shr(frame_vector[7], 1) & 0x3);	

	if (imbe_param->b_vec[0] < 0 || imbe_param->b_vec[0] > 207)
		return; // If we return here IMBE parameters from previous frame will be used (frame repeating)

	tmp = ((imbe_param->b_vec[0] & 0xFF) << 1) + 0x4F;                                      // Convert b_vec[0] to unsigned Q15.1 format and add 39.5

	//imbe_param->ff = 4./((double)imbe_param->b_vec[0] + 39.5);

	// Calculate fundamental frequency with higher precession
	shift = norm_s(tmp);
	tmp1  = tmp << shift;

	tmp2 = div_s(0x4000, tmp1);
	imbe_param->fund_freq = L_shr(L_deposit_h(tmp2), 11 - shift);    

	L_tmp = L_sub(0x40000000, L_mult(tmp1, tmp2));
	tmp2  = div_s(extract_l(L_shr(L_tmp, 2)), tmp1);
	L_tmp = L_shr(L_deposit_l(tmp2), 11 - shift - 2);
	imbe_param->fund_freq = L_add(imbe_param->fund_freq, L_tmp);

	//printf("%X %X \n", imbe_param->fund_freq, (Word32)(imbe_param->ff * (double)((UWord32)1<<31)));

	tmp = (tmp + 0x2) >> 3;                                                                 // Calculate (b0 + 39.5 + 1)/4
	imbe_param->num_harms   = ((UWord32)CNST_0_9254_Q0_16 * tmp) >> 16;

	if(imbe_param->num_harms <= 36)
		imbe_param->num_bands = extract_h((UWord32)(imbe_param->num_harms + 2) * CNST_0_33_Q0_16);   // fix((L+2)/3)
	else
		imbe_param->num_bands = NUM_BANDS_MAX;
	
	// Convert input vector (from b_3 to b_L+1) to bit stream
	bit_stream[0] = (frame_vector[0] & 0x4)?1:0;
	bit_stream[1] = (frame_vector[0] & 0x2)?1:0;
	bit_stream[2] = (frame_vector[0] & 0x1)?1:0;

	bit_stream[BIT_STREAM_LEN - 3] = (frame_vector[7] & 0x40)?1:0;
	bit_stream[BIT_STREAM_LEN - 2] = (frame_vector[7] & 0x20)?1:0;
	bit_stream[BIT_STREAM_LEN - 1] = (frame_vector[7] & 0x10)?1:0;


	index0 = 3 + 3 * 12 - 1;
	for(vec_num = 3; vec_num >= 1;  vec_num--)
	{	
		tmp = frame_vector[vec_num];
		for(i = 0; i < 12; i++)
		{
			bit_stream[index0] = (tmp & 0x1)?1:0;
			tmp >>= 1;
			index0--;
		}
	}
	
	index0 = 3 + 3 * 12 + 3 * 11 - 1;
	for(vec_num = 6; vec_num >= 4;  vec_num--)
	{	
		tmp = frame_vector[vec_num];
		for(i = 0; i < 11; i++)
		{
			bit_stream[index0] = (tmp & 0x1)?1:0;
			tmp >>= 1;
			index0--;
		}
	}

	// Rebuild b1
	index0 = 3 + 3 * 12;
	tmp = 0;
	for(i = 0; i < imbe_param->num_bands; i++)
		tmp = (tmp << 1) | bit_stream[index0++];		

	imbe_param->b_vec[1] = tmp;

	// Rebuild b2
	tmp = 0;
	tmp |= bit_stream[index0++] << 1;			
	tmp |= bit_stream[index0++];				
	imbe_param->b_vec[2] = (frame_vector[0] & 0x38) | (tmp << 1) | (shr(frame_vector[7], 3) & 0x01);

	// Shift the rest of sequence
	tmp = imbe_param->num_bands + 2;            // shift
	for(; index0 < BIT_STREAM_LEN; index0++)
		bit_stream[index0 - tmp] = bit_stream[index0];

    // Priority ReScanning
	b_ptr = &imbe_param->b_vec[3];
	ba_ptr = imbe_param->bit_alloc;
	for(i = 0; i < B_NUM; i++)
		ba_ptr[i] = b_ptr[i] = 0;


	// Unpack bit allocation table's item
	get_bit_allocation(imbe_param->num_harms, imbe_param->bit_alloc);

	index0 = 0;
	bit_thr = (imbe_param->num_harms == 0xb)?9:ba_ptr[0];

	while(index0 < BIT_STREAM_LEN - imbe_param->num_bands - 2)
	{	
		for(i = 0; i < imbe_param->num_harms - 1; i++)
			if(bit_thr && bit_thr <= ba_ptr[i])
				b_ptr[i] = (b_ptr[i] << 1) | bit_stream[index0++];		
		bit_thr--;
	}

	// Synchronization Bit Decoding
	imbe_param->b_vec[imbe_param->num_harms + 2] = frame_vector[7] & 1;
}


void v_uv_decode(IMBE_PARAM *imbe_param)
{
	Word16 num_harms;
	Word16 num_bands;
	Word16 vu_vec, *p_v_uv_dsn, mask, i, uv_cnt;

	num_harms = imbe_param->num_harms;
    num_bands = imbe_param->num_bands;
	vu_vec    = imbe_param->b_vec[1];

	p_v_uv_dsn = imbe_param->v_uv_dsn;

	mask = 1 << (num_bands - 1); 

	v_zap(p_v_uv_dsn, NUM_HARMS_MAX);

	i = 0; uv_cnt = 0;
	while(num_harms--)
	{
		if(vu_vec & mask)
			*p_v_uv_dsn++ = 1;
		else
		{
			*p_v_uv_dsn++ = 0;
			uv_cnt++;
		}

		if(++i == 3)
		{
			if(num_bands > 1)
			{
				num_bands--;
				mask >>= 1;
			}
			i = 0;
		}
	}
	imbe_param->l_uv = uv_cnt;
}
