/**********************************************************************
MPEG-4 Audio VM

This software module was originally developed by
  Y.B. Thomas Kim and S.H. Park (Samsung AIT)
and edited by
  Y.B. Thomas Kim (Samsung AIT) on 1997-11-06

in the course of development of the MPEG-2 NBC/MPEG-4 Audio standard
ISO/IEC 13818-7, 14496-1,2 and 3. This software module is an
implementation of a part of one or more MPEG-2 NBC/MPEG-4 Audio tools
as specified by the MPEG-2 NBC/MPEG-4 Audio standard. ISO/IEC gives
users of the MPEG-2 NBC/MPEG-4 Audio standards free license to this
software module or modifications thereof for use in hardware or
software products claiming conformance to the MPEG-2 NBC/ MPEG-4 Audio
standards. Those intending to use this software module in hardware or
software products are advised that this use may infringe existing
patents. The original developer of this software module and his/her
company, the subsequent editors and their companies, and ISO/IEC have
no liability for use of this software module or modifications thereof
in an implementation. Copyright is not released for non MPEG-2
NBC/MPEG-4 Audio conforming products. The original developer retains
full right to use the code for his/her own purpose, assign or donate
the code to a third party and to inhibit third party from using the
code for non MPEG-2 NBC/MPEG-4 Audio conforming products. This
copyright notice must be included in all copies or derivative works.

Copyright (c) 1997.

**********************************************************************/

/* HP 980211   adapted to new sam_scale.h by BG */

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <math.h>
#include "sam_encode.h"
#include "sam_scale.h"
#include "sam_model.h"
#include "sam_scf_coding.h"

static int	sam_scale_bits_enc[64];
static int *scale_index_long;
static int *scale_index_short;
static int *scale_qbw_long;
static int *scale_qbw_short;


#ifdef __cplusplus
extern "C" {
#endif

static int *select_scf_model(int scalefactor_model);
static int *select_Ar_model(int ArModel_model);
static int *select_model(int model_no, int cur_snf, int m0cnt, int pre_state);

#ifdef __cplusplus
}
#endif

void
sam_scale_bits_init_enc(int sampling_rate, int block_size_samples)
{
  int i, layer, layer_bit_rate;
  int average_layer_bits;

  /* calculate the avaerage amount of bits available
     for the scalability layer of one block per channel */
  for (layer=0; layer<=48; layer++) {
    layer_bit_rate = (layer+16) * 1000;
    average_layer_bits = (int)((double)layer_bit_rate*(double)block_size_samples/(double)sampling_rate);
    sam_scale_bits_enc[layer] = average_layer_bits;
  }
  for(i = 0; i < 10; i++) {
    if(sampling_rate == sam_scale_info_bsac[i].sampling_frequency) {
      scale_index_short = (int *)sam_scale_info_bsac[i].scale_index_short;
      scale_qbw_short   = (int *)sam_scale_info_bsac[i].scale_qbw_short;
      scale_index_long = (int *)sam_scale_info_bsac[i].scale_index_long;
      scale_qbw_long   = (int *)sam_scale_info_bsac[i].scale_qbw_long;
      break;
    }
  }
}

int
sam_encode_bsac(
	int target_bitrate,
	int common_window,
	int	windowSequence[],
	int	sample[][1024],
	int	band_snf[][200],
	int	scalefactors[][MAX_SCFAC_BANDS],
	int	maxSfb[],
	int	num_window_group[],
	int	swb_offset[][MAX_SCFAC_BANDS],
	int	which_model[][200],
	int	stereo_mode,
	int	stereo_info[],
	int pns_sfb_start,
	int pns_sfb_flag[][SFB_NUM_MAX],
	int pns_sfb_nrg[][SFB_NUM_MAX],
	int pns_sfb_mode[],
	int block_size_samples,
	int ubits,
	int abits,
	int i_ch,
	int nch,
	int wflag)
{
	int		i, ch, k, m, w;
	int		band_bal;
	int     target;
	int		sfb, qband, cband;
	int		last_cband;
	int		last_index;
	int		layer_sfb[2][64];
	int		layer_index[2][64];
	int		exit_flag;
	int		symlen;
	int		max, min;
	int		layer;
	int		num_ch;
	int		scf_coding[2];
	int		prev_scf[2];
	int		maxhalf, snf;
	int		maxsnf;
	int		used_bits;
	int		pns_data_present;
	int		noise_pcm_flag[2];
	int		cur_snf[2][256];
	int		scalefactor_model[2], ArModel_model[2];
	int		maxScalefactors[2], min_ArModel[2];
	int		prestate[2][1024];
	int		*p_freq0, *p_freq1;
	int		m1, m0, m1cnt, m0cnt;
	int		encode_cband[2][200];
	int		escale_bits[64];
	static int AModelNoiseNrg[512];
	static int is_start=1;
	double	estimated_bits;

	if(is_start) {
		int prob = 16384 - 32;
		for(i = 0; i < 512; i++) {
			AModelNoiseNrg[i] = prob;
			prob -= 32;
		}
		is_start = 0;
	}

	target = (target_bitrate / 1000) - 16;

	num_ch = nch - i_ch;
	used_bits = ubits;
	if(maxSfb[i_ch] == 0) {
		if(nch == 1) return used_bits;
		if(nch == 2 && maxSfb[i_ch] == 0) return used_bits;
	}

	/* ***************************************************** */
	/* #                  Initialization					 */
	/* ***************************************************** */

	for(ch = i_ch; ch < nch; ch++) {
	   	layer_sfb[ch][0] = 0;
		layer_index[ch][0] = 0;
		noise_pcm_flag[ch] = 1;
		for (layer = 0; layer <= target; layer++) {
			int scaleqbw;

			if(windowSequence[ch] == EIGHT_SHORT_SEQUENCE) {
				layer_index[ch][layer+1] = scale_index_short[layer] * 8;
				scaleqbw = scale_qbw_short[layer];
			} else {
				layer_index[ch][layer+1] = scale_index_long[layer];
				scaleqbw = scale_qbw_long[layer];
			}

	    	if (scaleqbw < maxSfb[ch])
				layer_sfb[ch][layer+1] = scaleqbw;
	    	else
				layer_sfb[ch][layer+1] = maxSfb[ch];

			qband = layer_sfb[ch][layer+1] * num_window_group[ch];

			if(layer_index[ch][layer+1] > block_size_samples)
				layer_index[ch][layer+1] = block_size_samples;

        	if (swb_offset[ch][qband] < layer_index[ch][layer+1])
               	layer_index[ch][layer+1] = swb_offset[ch][qband];
		}
	}

	if(wflag) {
		for (i = 0; i < target; i++)
			escale_bits[i] = sam_scale_bits_enc[i] * nch;
	} else {
		for (i = 0; i < target; i++)
			escale_bits[i] = sam_scale_bits_enc[i];
	}

	escale_bits[target] = abits;

	/*** Clear variables ***/
	for(ch = i_ch; ch < nch; ch++) {
		for (i=0; i<1024; i++) 
			prestate[ch][i] = 0;

		for(i = 0; i < 200; i++)
			encode_cband[ch][i] = 0;

		/* model_assign */
		if(windowSequence[ch] == EIGHT_SHORT_SEQUENCE) {
			for(i = 0; i < 1024; i += 4) {
				cband = sam_i2cb(ch, i);
				if(cband == -1) continue;
				if(encode_cband[ch][cband]) continue;
				which_model[ch][cband] += (band_snf[ch][cband]*2);
				encode_cband[ch][cband] = 1;
			}
		} else {
			last_cband = (swb_offset[ch][maxSfb[ch]]+31) / 32;
			for(cband = 0; cband < last_cband; cband++) {
				which_model[ch][cband] += (band_snf[ch][cband]*2);
			}
		}
		for(i = 0; i < 200; i++)
			encode_cband[ch][i] = 0;
	}

	/* ***************************************************** */
	/*                  BSAC_general_info()                  */
	/* ***************************************************** */
	for(ch = i_ch; ch < nch; ch++) {

    	/* scalefactor model selection */
		max = 0;
		min = 1000;
		for(sfb = 0; sfb < maxSfb[ch]*num_window_group[ch]; sfb++) {
			if (scalefactors[ch][sfb] < 0) continue; 
			if (max < scalefactors[ch][sfb]) max = scalefactors[ch][sfb];
			if (min > scalefactors[ch][sfb]) min = scalefactors[ch][sfb];
		}

		maxScalefactors[ch] = max;
		if(wflag) {
			sam_putbits2bs(maxScalefactors[ch], 8);
		}
		used_bits += 8;

		if (min ==1000 || min<0) min = 0;

		m = max - min;
    	if (m>31) 		scalefactor_model[ch] = 3;
    	else if (m>15)  scalefactor_model[ch] = 2;
    	else if (m>7)   scalefactor_model[ch] = 1;
    	else       		scalefactor_model[ch] = 0;
 
		if(wflag) {
			sam_putbits2bs((unsigned int)scalefactor_model[ch], 2);
		}
		used_bits += 2;

    	/* minimum ArModel */
		max = 0;
		min = 100;
		if(windowSequence[ch] == EIGHT_SHORT_SEQUENCE) {
			for(i = 0; i < 1024; i += 4) {
				cband = sam_i2cb(ch, i);
				if(cband == -1) continue;
				if (max < which_model[ch][cband])
					max = which_model[ch][cband];
				if (min > which_model[ch][cband])
					min = which_model[ch][cband];
			}
		} else {
			last_cband = (swb_offset[ch][maxSfb[ch]]+31) / 32;
			for(cband = 0; cband < last_cband; cband++) {
				if (max < which_model[ch][cband])
					max = which_model[ch][cband];
				if (min > which_model[ch][cband])
					min = which_model[ch][cband];
			}
		}
		if (min==100 || min<0 ) 	min = 0;
		min_ArModel[ch] = min;

		if(min_ArModel[ch] > 31) {
			min_ArModel[ch] = 31;
			min = 31;
		}
		if(wflag) {
			sam_putbits2bs((unsigned int)min_ArModel[ch], 5);
		}
		used_bits += 5;

    	/* ArModel selection */
		m = max - min;
		if( m> 15 )	    	ArModel_model[ch] = 3;
		else if( m> 7 )	    ArModel_model[ch] = 2;
		else if( m> 3 )	    ArModel_model[ch] = 1;
		else 		    	ArModel_model[ch] = 0;

		if(wflag) {
			sam_putbits2bs((unsigned int)ArModel_model[ch], 2);
		}
		used_bits += 2;

		scf_coding[ch] = 0;
		if(wflag) {
			sam_putbits2bs((unsigned int)scf_coding[ch], 1);
		}
		used_bits += 1;
	}

	pns_data_present = 1;
	if(pns_sfb_start == -1)
		pns_data_present = 0;

	if(wflag) {
		sam_putbits2bs(pns_data_present, 1);
	}
	used_bits += 1;

	if(pns_data_present) {
		if(wflag) sam_putbits2bs(pns_sfb_start, 6);
		used_bits += 6;
	}

	/* ##################################################### */
	/* 	                BSAC MAIN ROUTINE                    */
	/* ##################################################### */

	/* ***************************************************** */
	/*                  BSAC_layer_stream()                  */
	/* ***************************************************** */

	estimated_bits = used_bits;

	sam_start_encoding(used_bits, escale_bits[target]);

	/* side infomation : istep*/
	for(ch = i_ch; ch < nch; ch++)
		prev_scf[ch] = maxScalefactors[ch];

	symlen = 0;
	for (layer = 0; layer <= target; layer++) {

	/* ***************************************************** */
	/*                  BSAC_side_info()                     */
	/* ***************************************************** */

		/* ***************************************************** */
		/* #              Stereo/PNS Information                 */
		/* ***************************************************** */
		if(nch == 1) {
		  if(pns_data_present) {
			  for(w = 0; w < num_window_group[i_ch]; w++) {
				for(sfb = layer_sfb[i_ch][layer]; sfb < layer_sfb[i_ch][layer+1]; sfb++)
					if(sfb >= pns_sfb_start) {
						qband = (w * maxSfb[i_ch]) + sfb;
						m = pns_sfb_flag[0][qband];
		    			symlen = sam_encode_symbol(m, AModelNoiseFlag, &estimated_bits, wflag);
					}
			}
		  }
		} else if(stereo_mode != 2) {
			for(w = 0; w < num_window_group[1]; w++) {
				for(sfb = layer_sfb[1][layer]; sfb < layer_sfb[1][layer+1]; sfb++) {
					qband = (w * maxSfb[i_ch]) + sfb;
					m = stereo_info[qband];
					if(stereo_mode == 1) {
		    			symlen = sam_encode_symbol(m, AModelMsUsed, &estimated_bits, wflag);
					} else if(stereo_mode == 3) {
		    			symlen = sam_encode_symbol(m, AModelStereoInfo, &estimated_bits, wflag);
					}
					if(symlen < 0) break;
					if(pns_data_present && sfb >= pns_sfb_start) {
						m = pns_sfb_flag[0][qband];
		    			symlen = sam_encode_symbol(m, AModelNoiseFlag, &estimated_bits, wflag);
						m = pns_sfb_flag[1][qband];
		    			symlen = sam_encode_symbol(m, AModelNoiseFlag, &estimated_bits, wflag);
						if(stereo_mode == 3 && stereo_info[qband] == 3)
							if(pns_sfb_flag[0][qband] && pns_sfb_flag[1][qband]) {
								m = pns_sfb_mode[qband];
		    					symlen = sam_encode_symbol(m, AModelNoiseMode, &estimated_bits, wflag);
							}
					}
				}
				if(symlen < 0) break;
			}
		}

		/* ***************************************************** */
		/* #                  PNS    Information                 */
		/* ***************************************************** */
		if(symlen < 0) break;

		/* ***************************************************** */
		/* #             Scalefactor Information                 */
		/* ***************************************************** */
		for(ch = i_ch; ch < nch; ch++) for(w = 0; w < num_window_group[ch]; w++) {
			for(sfb = layer_sfb[ch][layer]; sfb < layer_sfb[ch][layer+1]; sfb++) {

				qband = (w * maxSfb[ch]) + sfb;
				if(scf_coding[ch] == 1) {
					int *pModel;

					pModel = select_scf_model(scalefactor_model[ch]);

					m = maxScalefactors[ch] - scalefactors[ch][qband];
					symlen = sam_encode_symbol(m, pModel, &estimated_bits, wflag);
				} else {
					if(ch == 1 && stereo_info[qband] > 1) {
						m = scalefactors[ch][qband];
					} else {
						m = prev_scf[ch] - scalefactors[ch][qband] + 60;
					}
					if(pns_data_present && noise_pcm_flag[ch] && sfb >= pns_sfb_start) {
						m = scalefactors[ch][qband];
						symlen = sam_encode_symbol(m, AModelNoiseNrg, &estimated_bits, wflag);
						noise_pcm_flag[ch] = 0;
					} else {
					m1 = scf2index[m];
					if(m1 > 54) m1 = 54;

					symlen = sam_encode_symbol(m1, AModelDifScf0, &estimated_bits, wflag);

					if(m1 == 54) {
						m1 = scf2index[m] - 54;
						symlen = sam_encode_symbol(m1, AModelDifScf1, &estimated_bits, wflag);
					}
					}

					if(!wflag || ch == 0 || stereo_info[qband] < 2)
						prev_scf[ch] = scalefactors[ch][qband];
				}
				if(symlen < 0) break;
			}
			if(symlen < 0) break;
		}
		if(symlen < 0) break;


		/* ***************************************************** */
		/* #                  Model  Information                 */
		/* ***************************************************** */
		for(ch = i_ch; ch < nch; ch++) {
			int	*pModel;
			for(sfb = layer_sfb[ch][layer]; sfb < layer_sfb[ch][layer+1]; sfb++) {
				for(w = 0; w < num_window_group[ch]; w++) {
					qband = (sfb * num_window_group[ch]) + w;
					for(i = swb_offset[ch][qband]; i < swb_offset[ch][qband+1]; i+=4) {
						if(windowSequence[ch] == EIGHT_SHORT_SEQUENCE) {
							cband = sam_i2cb(ch, i);
							if(cband == -1) continue;
						} else {
							cband = i / 32;
						}
						if(encode_cband[ch][cband]) continue;

						pModel = select_Ar_model(ArModel_model[ch]);

		    			m = which_model[ch][cband] - min_ArModel[ch];
		    			symlen = sam_encode_symbol(m, pModel, &estimated_bits, wflag);

						encode_cband[ch][cband] = 1;
						if(symlen < 0) break;
					}
					if(symlen < 0) break;
				}
				if(symlen < 0) break;
			}
			if(symlen < 0) break;
		}
		if(symlen < 0) break;


		/* ***************************************************** */
		/* #               Layer  Initialization                 */
		/* ***************************************************** */

		/*
		  set current snf
		*/
		for(ch = i_ch; ch < nch; ch++) {
			for(sfb = layer_sfb[ch][layer]; sfb < layer_sfb[ch][layer+1]; sfb++) {
				for(w = 0; w < num_window_group[ch]; w++) {
					qband = (sfb * num_window_group[ch]) + w;
					for (i = swb_offset[ch][qband]; i < swb_offset[ch][qband+1]; i+=4) {
						if(windowSequence[ch] == EIGHT_SHORT_SEQUENCE) {
							cband = sam_i2cb(ch, i);
						} else {
							cband = i / 32;
						}
						if(cband < 0)
							cur_snf[ch][i/4] = 0;
						else
		   					cur_snf[ch][i/4] = band_snf[ch][cband];
					}
				}
			}
		}

		/*
		  find maximum snf
		*/
		maxsnf = 0;
		for(ch = i_ch; ch < nch; ch++) {
			qband = layer_sfb[ch][layer+1] * num_window_group[ch];
			for(i = 0; i< swb_offset[ch][qband]/4; i++) 
				if (maxsnf < cur_snf[ch][i]) maxsnf = cur_snf[ch][i];
		}

		/*
		  find last index
		*/
		qband = layer_sfb[i_ch][layer+1] * num_window_group[i_ch];
		last_index = swb_offset[i_ch][qband];
		if(i_ch == 0 && nch == 2) {
			qband = layer_sfb[1][layer+1] * num_window_group[1];
			if(last_index < swb_offset[1][qband])
				last_index = swb_offset[1][qband];
		}

	/* ***************************************************** */
	/*                  BSAC_spectral_info()                 */
	/* ***************************************************** */

		exit_flag = 0;
		for (snf = maxsnf; snf > 0 && !exit_flag; snf--) {

			for (i = 0; i < last_index && !exit_flag; i+=4) {
				int tmpsnf;

				for(ch = i_ch; ch < nch && !exit_flag; ch++) {

					if (i >= layer_index[ch][layer+1]) break;

		  			if ( cur_snf[ch][i/4] < snf || cur_snf[ch][i/4] <= 0)
						continue;

			    	maxhalf = 1<<(cur_snf[ch][i/4]-1);

		     		/* The new vector is formed by the samples 
						whose sign bit was not encoded previously.
						And the size of the new vector is counted. */
                    m0 = 0; m1=0;
                    m0cnt = 0;  m1cnt = 0;
                    for(k = 0; k < 4; k++) {
                    	if (prestate[ch][i+k]==0) {
                    		if( abs(sample[ch][i+k]) & maxhalf)
                    			m0 |= 0x01<<m0cnt;
                    		m0cnt++;
                     	}
						else {
                    		if( abs(sample[ch][i+k]) & maxhalf)
                    			m1 |= 0x01<<m1cnt;
                    		m1cnt++;
						}
                    }

		     		/* select the model for arithmetic coding 
		 				as the function of band snf & current vector snf */	

					if(windowSequence[ch] == EIGHT_SHORT_SEQUENCE) {
						cband = sam_i2cb(ch, i);
						if(cband == -1) band_bal = 0;
						else band_bal = band_snf[ch][cband];
					} else {
						cband = i / 32;
						band_bal = band_snf[ch][cband];
					}

		     		tmpsnf = band_bal - cur_snf[ch][i/4];
					p_freq0 = select_model(which_model[ch][cband], tmpsnf, m0cnt, 0);
					p_freq1 = select_model(which_model[ch][cband], tmpsnf, m1cnt, 1);

		     		/* encoding of the vector */
		     		if (m1cnt>0) {
		          		symlen = sam_encode_symbol(m1, p_freq1, &estimated_bits, wflag);
		     		}
					if(symlen < 0) {
						exit_flag = 1;
						break;
					}
				
		     		if (m0cnt>0) {
		          		symlen = sam_encode_symbol(m0, p_freq0, &estimated_bits, wflag);
		     		}
					if(symlen < 0) {
						exit_flag = 1;
						break;
					}

		     		/* encoding of the sign bit when it is needed */ 
		     		for(k = 0; k < 4 && !exit_flag; k++) {
			  			int signlen = 0;
			  			if( abs(sample[ch][i+k]) & maxhalf) { 
							if ( abs(sample[ch][i+k]) < (maxhalf<<1) ) 
								signlen++;
			  			}
			  			if (signlen!=0) {/* if the sign bit is needed */
							if (sample[ch][i+k] < 0)
								m = 1;
							else
								m = 0;
							symlen = sam_encode_symbol(m, AModelSign, &estimated_bits, wflag);
							if(symlen < 0) {
								exit_flag = 1;
								break;
							}

							/* save snf where the sign bit is encoded */ 
							prestate[ch][i+k] = cur_snf[ch][i/4];
			  			}
		     		}
		     		cur_snf[ch][i/4]--;

		     		/* if the total bits are larger than 
						the available bits of each scale (bitrate),
						exit the loop.  */ 
		     		if (estimated_bits >= escale_bits[layer]) {
						exit_flag = 1;
						break;
		     		}
				}
			}	/* for (i = 0; i < last_index && !exit_flag; i+=4) */

 
	       	/* if the total bits are larger than 
		  		the available bits of each scale (bitrate),
		  		exit the loop.  */ 
	       	if (estimated_bits >= escale_bits[layer])  break;

		}
		if(symlen < 0) break;

	} /* for (layer = 0; layer <= target; layer++) */

	used_bits = sam_done_encoding(wflag);

	return used_bits;
}

static int *select_scf_model(int scalefactor_model)
{
	int	*pModel;

	pModel = NULL;
	switch(scalefactor_model) {
		case 0:
			pModel = (int *)AModelDifScf2;
			break;
		case 1:
			pModel = (int *)AModelDifScf3;
			break;
		case 2:
			pModel = (int *)AModelDifScf4;
			break;
		case 3:
			pModel = (int *)AModelDifScf5;
			break;
	}

	return pModel;
}

static int *select_Ar_model(int ArModel_model)
{
	int	*pModel;

	pModel = NULL;
	switch(ArModel_model) {
		case 0:
			pModel = (int *)AModelDiffAModel0;
			break;
		case 1:
			pModel = (int *)AModelDiffAModel1;
			break;
		case 2:
			pModel = (int *)AModelDiffAModel2;
			break;
		case 3:
			pModel = (int *)AModelDiffAModel3;
			break;
	}

	return pModel;
}

static int *select_model(int model_no,
		int cur_snf,
		int m0cnt,
		int pre_state)
{
	static int	position4[17]={0, 0,
	0, 1, 2, 5, 8, 13, 18, 25, 32, 41, 50, 61, 72, 85};
	static int	positions[16]={0, 0, 0, 0,
	0, 2, 4, 8, 12, 18, 24, 32, 40, 50, 60, 72};
	static int	alloc_bit[]={0, 0, 1, 1,
	2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16};
	int	*ptr;
	int	model;
	int	snf;
	int	i, offset;


	snf = cur_snf;
	model = model_no;
	if(model_no > 11) {
		if(model_no % 2)
			model = 11;
		else
			model = 10;
	}
	if(snf < 0) snf = 0;
	if(snf > 4) snf = 4;


	offset = 0;
	if(snf != 0) {
		if(m0cnt == 4)
			offset = 1;
		for(i = 1; i < alloc_bit[model]; i++) {
			if(snf == i) break;
			offset += 2;
		}
		if(pre_state == 1)
			offset += 1;
	}

	ptr = NULL;
	switch(m0cnt) {
	case 4:
		ptr = (int *)AModelDim4[position4[model]+offset];
		break;
	case 3:
		ptr = (int *)AModelDim3[positions[model]+offset];
		break;
	case 2:
		ptr = (int *)AModelDim2[positions[model]+offset];
		break;
	case 1:
		ptr = (int *)AModelDim1[positions[model]+offset];
		break;
	default:
		break;
	}

	return ptr;
}
