/**********************************************************************
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.

**********************************************************************/
#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	escale_bits[64];

#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

int
sam_encode_bsac(int common_window,
	int	windowSequence[],
	int	sample[][1024],
	int	band_snf[][200],
	int	scalefactors[][112],
	int	maxSfb[],
	int	num_window_group[],
	int	swb_offset[][112],
	int	which_model[][200],
	int	stereo_mode,
	int	stereo_info[],
	int ubits,
	int abits,
	int i_ch,
	int nch,
	int wflag)
{
	int		i, ch, k, m, w;
	int		target;
	int		band_bal;
	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		scf_coding[2];
	int		prev_scf[2];
	int		maxhalf, snf;
	int		maxsnf;
	int		used_bits;
	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		scaleqbw[2][114];
	double	estimated_bits;

	target = 48;

	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++) {
		if(windowSequence[ch] == EIGHT_SHORT_SEQUENCE) {
			for(i = 0; i <= target; i++)
				scaleqbw[ch][i] = scale_qbws[i];

		} else {
			for(i = 0; i <= target; i++)
				scaleqbw[ch][i] = scale_qbw[i];
		}
	}

	for(ch = i_ch; ch < nch; ch++) {
	   	layer_sfb[ch][0] = 0;
		layer_index[ch][0] = 0;
	}

	for (layer = 0; layer <= target; layer++) {
		for(ch = i_ch; ch < nch; ch++) {
	    	if (scaleqbw[ch][layer] < maxSfb[ch])
				layer_sfb[ch][layer+1] = scaleqbw[ch][layer];
	    	else
				layer_sfb[ch][layer+1] = maxSfb[ch];

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

			if(windowSequence[ch] == EIGHT_SHORT_SEQUENCE) {
				layer_index[ch][layer+1] = scale_findex_s[layer] * 8;
			} else {
				layer_index[ch][layer+1] = scale_findex_l[layer];
			}
        	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] = scale_bits[i] * nch;
	} else {
		for (i = 0; i < target; i++)
			escale_bits[i] = scale_bits[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;
	}


	/* ***************************************************** */
	/* # 			the main audio bitstream			   # */
	/* ***************************************************** */

	/* ***************************************************** */
	/* 	  		the common side info for all bitrates  	     */
	/* ***************************************************** */

	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 (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;
	}

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

	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++) {

		/* ***************************************************** */
		/* #                  Stereo Information                 */
		/* ***************************************************** */
		if(stereo_mode > 1) {
			for(w = 0; w < num_window_group[1]; w++) {
				for(sfb = layer_sfb[1][layer]; sfb < layer_sfb[1][layer+1]; sfb++) {
					m = stereo_info[(w*maxSfb[1])+sfb];
					if(stereo_mode == 2)
		    			symlen = sam_encode_symbol(m, AModelMsUsed, &estimated_bits, wflag);
					else
		    			symlen = sam_encode_symbol(m, AModelStereoInfo, &estimated_bits, wflag);
					if(symlen < 0) break;
				}
				if(symlen < 0) break;
			}
		}
		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;
					}
					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];
		}

		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;
}
