/*====================================================================*/
/*         MPEG-4 Audio (ISO/IEC 14496-3) Copyright Header            */
/*====================================================================*/
/*
This software module was originally developed by Rakesh Taori and Andy
Gerrits (Philips Research Laboratories, Eindhoven, The Netherlands) in
the course of development of the MPEG-4 Audio (ISO/IEC 14496-3). This
software module is an implementation of a part of one or more MPEG-4
Audio (ISO/IEC 14496-3) tools as specified by the MPEG-4 Audio
(ISO/IEC 14496-3). ISO/IEC gives users of the MPEG-4 Audio (ISO/IEC
14496-3) free license to this software module or modifications thereof
for use in hardware or software products claiming conformance to the
MPEG-4 Audio (ISO/IEC 14496-3). Those intending to use this software
module in hardware or software products are advised that its 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-4 Audio (ISO/IEC 14496-3) conforming products.
CN1 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 parties from
using the code for non MPEG-4 Audio (ISO/IEC 14496-3) conforming
products.  This copyright notice must be included in all copies or
derivative works. Copyright 1996.
*/
/* 	Module: vlc_enc
	Rene van der Vleuten *** 1-JUL-1997 
	Adaptive Huffman coding for Wideband Coder
	Features: 1. Don't use Rice code
	          2. Don't combine tables
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <assert.h>
#include "phi_cons.h"

#define	RICE_PARAM_BITS	4		/* #bits for transmitting param "m" of Rice code */
#define	NLEVELS			30		/* number of possible indices */
#define	MAX_VLC_LEN		16		/* max length in bits of a VLC code */
#define	MIN(x,y)	(((x) < (y)) ? (x) : (y))
#define	log2(x)		(log(x)/log(2.0))


/* On-the-fly encoder */
/* WARNING: This routine does not write a sign bit! */
/*          This should be done by calling function, if necessary */

/* ENCODER */
/* In: value, table length, table spec*/
/* Out:codeword, length */
void a_tab_encode(int value,int K, int ltbl[], long *cw, short *length)
{
int abv,l,done,nb;
long codeword;

abv=abs(value); l=0; codeword=0; done=0;
while (done==0)
        {while (ltbl[l]==0)
                {l++; codeword <<= 1;
                 if (l >= K)	
                 	{fprintf(stderr,"ERROR:h_tab_encode:this can't happen!\n");
                 	 fprintf(stderr,"value=%d, K=%d, l=%d\n",value,K,l);
                 	 for (l=0;l<K;l++)
                 	 	fprintf(stderr,"ltbl[%d]=%d\n",l,ltbl[l]);
                 	 exit(1);
                 	}
                }
         nb=ltbl[l];
         if (abv<nb)
                {codeword += abv; done=1;}
         else
                {codeword +=nb; codeword <<= 1; abv -= nb; l++;}
        }
*length=l+1;
*cw =codeword;
} /* a_tab_encode */

/* On-the-fly decoder */
/* WARNING: This routine does not read sign bits! */
/*          This should be done by calling function, if necessary */
/* DECODER */
/* In: bits, table spec */
/* Out: value */
int a_tab_decode(int K, int ltbl[], long bits, short length)
{
int mincod,l,codeword,abv,done,nb,value;
int len = length;

mincod=0; l=0; abv=0; done=0; codeword=((bits >> (len-1)) & 1); len--; assert(len >= 0);
while (done==0)
        {while (ltbl[l]==0)
                {l++; codeword <<= 1;
                 codeword |= ((bits >> (len-1)) & 1); len--; mincod <<= 1;
                 assert(len >= 0);
                 if (l >= K) fprintf(stderr,"ERROR: this can't happen!\n"),exit(1);
                }
         nb=ltbl[l];
         if (codeword-mincod < nb)
                {value=abv+codeword-mincod; done=1;}
         else
                {abv += nb; mincod += nb; mincod <<= 1; l++;
                 codeword <<= 1; codeword |= ((bits >> (len-1)) & 1); len--;
                 assert(len >= 0);
               }
         }
return(value);
} /* a_tab_decode */

void get_huffman_bits(int n, long *val, short *codesize, long *codeword, long bits, short length){
        int     i, code_len, ready;
        long    samplecode = 0;
int len = length;

        code_len = 0; ready = 0; samplecode = 0;
        while(!ready){
                samplecode <<= 1;
                samplecode |= ((bits >> (len-1)) & 1); len--;
                 assert(len >= 0);
                code_len++;
                for (i = 0; i < n; i++){
                        if ((code_len == codesize[i]) && (samplecode == codeword[i])){
                                *val  = i;
                                ready = 1;
                                break;
                        }
                }
        }
}

/* generate Huffman codewords from lengths */
/* Rene van der Vleuten *** 10-OCT-1996 */
/* Typical use: call hufflen() before calling huff_len_to_cwrds() */
/* In: n: table size */
/* In: codesize[n]: Huffman codeword length for each symbol */
/* Out: codesize[n]: maximum codeword length is limited to MAX_LEN */
/* Out: cwrds[n]: Huffman codeword for each symbol */
void huff_len_to_cwrds(int n, short codesize[], long cwrds[])
{
int	i;
int	mv;
int	*nrcw,*minpos,*nrcwrds,*spos;

if ((n-1) >> MAX_VLC_LEN) fprintf(stderr,"ERROR:huff_len_to_cwrds: MAX_LEN too small!!\n"),exit(1);

mv=0;
for (i=0; i<n; i++)
   if (codesize[i]>mv) mv=codesize[i];

if ((spos = (int *) malloc(n * sizeof(int))) == NULL) fprintf(stderr,"malloc failure\n"),exit(1);
if ((nrcw = (int *) calloc(mv , sizeof(int))) == NULL) fprintf(stderr,"malloc failure\n"),exit(1);
if ((minpos = (int *) malloc(mv * sizeof(int))) == NULL) fprintf(stderr,"malloc failure\n"),exit(1);
if ((nrcwrds = (int *) calloc(mv , sizeof(int))) == NULL) fprintf(stderr,"malloc failure\n"),exit(1);

for (i=0; i<n; i++)
	nrcw[codesize[i]-1]++;
minpos[0]=0;
for (i=1; i<mv; i++)
   minpos[i]=minpos[i-1]+nrcw[i-1];
for (i=0; i<n; i++)
	{spos[i]=minpos[codesize[i]-1]+nrcwrds[codesize[i]-1];
   	 nrcwrds[codesize[i]-1]++;
	}
while (mv > MAX_VLC_LEN)
	{while (nrcw[mv-1]>0)
		{i=mv-2;
		 while (nrcw[i-1]==0) i--;
		 nrcw[mv-1]-= 2;
		 nrcw[mv-2]++;
		 nrcw[i]+= 2;
		 nrcw[i-1]--;
		}
   	 mv--;
	}
for (i=0; i<n; i++)
	a_tab_encode(spos[i],mv,nrcw,cwrds+i,codesize+i);

free(nrcwrds);free(minpos);free(nrcw);free(spos);
}

/* HUFFMAN-LENGTHS PROCEDURE */
/* gets lengths only of Huffman codewords */
/* Adapted from JPEG standard, Annex K, Figure K.1 */
/* n: alphabet size */
/* freq[n]: histogram */
/* codesize[n]: length of Huffman codeword */
void hufflen(int n,short freq[],short codesize[])
{	short	h,hh,mv;
	int	*others,i,v1,v2;
	if ((others = (int *) malloc(n * sizeof(int))) == NULL) fprintf(stderr,"malloc failure in hufflen\n"),exit(1);
/* determine escape value */
	mv=0;
	
	for (i=0; i<n; i++) mv+= freq[i];
	mv++;
	if (mv<0) fprintf(stderr,"ERROR:hufflen:overflow!!\n"),exit(1);
/* init */
	for (i=0; i<n; i++)
		{codesize[i]=0;
		 others[i]= -1;
		}
/* loop */
	for (;;)
		{
/* find lowest pair */
/*		 if (freq[1]<freq[0]) {v1=1;v2=0;}
		 else {v1=0;v2=1;}
		 h=freq[v1]; hh=freq[v2];
		 for (i=2; i<n; i++)
		 	if (freq[i]<h) {hh=h; h=freq[i]; v2=v1; v1=i;}
		 	else if (freq[i]<hh) {hh=freq[i]; v2=i;}*/
		 if (freq[n-2]<freq[n-1]) {v1=n-2;v2=n-1;}
		 else {v1=n-1;v2=n-2;}
		 h=freq[v1]; hh=freq[v2];
		 for (i=n-3; i>=0; i--)
		 	if (freq[i]<h) {hh=h; h=freq[i]; v2=v1; v1=i;}
		 	else if (freq[i]<hh) {hh=freq[i]; v2=i;}
		 if (hh==mv) break;
/* join pair and adjust tables */
		 freq[v1]=h+hh;
		 freq[v2]=mv;
		 codesize[v1]++;
		 while (others[v1] != -1)
		 	{v1=others[v1];
		 	 codesize[v1]++;
		 	}
		 others[v1]=v2;
		 codesize[v2]++;
		 while (others[v2] != -1)
		 	{v2=others[v2];
		 	 codesize[v2]++;
		 	}
		}
	free(others); 
}

/* determine #bits (data + overhead) from histogram and codeword lengths */
/* m: actual maximum length of VLC codeword */
/* cwrds[m]: number of codewords of each length */
/* lbits: #bits needed for maxvlclen */
static int count_bits(short freq[],int m,int cwrds[],int lbits)
{
	int		i,j,p,tb;
	short	h;

/* count data bits */
	h=freq[0]; freq[0]=0; /* don't count zero level */
	tb=0; p=0;
	for (i=0; i<m; i++)
		for (j=0; j<cwrds[i]; j++,p++)
			tb+=freq[p]*(i+2); /* take sign bit into account */
	freq[0]=h; /* restore freq */
	i=0; while (cwrds[i]==0) i++;
	tb+=h*(i+1); /* add bits for zero level */

/* count overhead bits */
	tb+=lbits;
	for (i=0; i<m; i++)
		tb+= i+1;
			
	return(tb);
}


/* determine table of codeword lengths from histogram */
/* returns total #bits (for data + overhead) */
/* lvls: number of levels */
/* count[lvls]: two-sided histogram */
/* maxvlclen: maximum allowed length of VLC codeword */
/* lbits: #bits needed for maxvlclen */
/* *m: actual maximum length of VLC codeword */
/* ltbl[m]: number of codewords of each length */
/* *ricep: parameter of Rice code */
/* *cmt: best coding method: 0 -> HiTBL, 1 -> Rice */
static int get_lengths(int lvls,short count[],int maxvlclen,int lbits,int *m,int ltbl[],int *ricep,int *cmt)
{
	short	*freq,*codesize,mv;
	int		i,n,*bits,tb,cb,g,mlen,rb;


if (lvls & 1)
{
	if ((freq = (short *) malloc(((lvls+1)/2) * sizeof(short))) == NULL) {fprintf(stderr,"malloc failure in get_lengths\n");exit(1);}

/* get one-sided histogram for Huffman procedure */
	for (i=0; i<(lvls-1)/2; i++)
	    freq[(lvls-1)/2-i]=count[i]+count[lvls-1-i];
	freq[0]=count[(lvls-1)/2];
	n=(lvls-1)/2;
}
else
{
	if ((freq = (short *) malloc(((lvls)/2) * sizeof(short))) == NULL) {fprintf(stderr,"malloc failure in get_lengths\n");exit(1);}

/* get one-sided histogram for Huffman procedure */
	for (i=0; i<(lvls)/2; i++)
	    freq[(lvls)/2-1-i]=count[i]+count[lvls-1-i];
	n=(lvls)/2 -1;
}

/* get max lvl and eliminate zeros */		 	
	/* while (freq[n]==0) n--; */
	for (i=0; i<=n; i++)
	    if (freq[i]==0) freq[i]=1;
	n++;
	if ((1 << maxvlclen) < n) fprintf(stderr,"ERROR:get_lengths:maxvlclen too small for given number of codewords\n"),exit(1);
/* allocate mem */
	if ((codesize = (short *) malloc(n * sizeof(short))) == NULL) fprintf(stderr,"malloc failure in get_lengths\n"),exit(1);

/* DO HUFFMAN PROCEDURE */

	hufflen(n,freq,codesize);

/* CREATE HISTOGRAM OF CODEWORD LENGTHS */
	mv=0;
	for (i=0; i<n; i++)
		if (codesize[i]>mv) mv=codesize[i];
	if ((bits = (int *) calloc(mv,sizeof(int))) == NULL) fprintf(stderr,"malloc failure in get_lengths\n"),exit(1);
	for (i=0; i<n; i++) bits[codesize[i]-1]++;
/* adjust table so maximum length <= maxvlclen */
/* Adapted from JPEG standard, Annex K, Figure K.3 */
	while (mv > maxvlclen)
		{while (bits[mv-1]>0)
			{i=mv-2;
			 while (bits[i-1]==0) i--;
			 bits[mv-1]-= 2;
			 bits[mv-2]++;
			 bits[i]+= 2;
			 bits[i-1]--;
			}
		 mv--;
		}

/* OPTIMIZE TABLE TO MINIMIZE TOTAL #BITS (FOR DATA + OVERHEAD) */
/* get one-sided histogram for count_bits */
if (lvls & 1)
{	for (i=0; i<(lvls-1)/2; i++)
	    freq[(lvls-1)/2-i]=count[i]+count[lvls-1-i];
	freq[0]=count[(lvls-1)/2];
}
else
{
	for (i=0; i<(lvls)/2; i++)
	    freq[(lvls)/2-1-i]=count[i]+count[lvls-1-i];
}
/* init */
	*m=mv;
	for (i=0; i<mv; i++) ltbl[i]=bits[i];
	tb=count_bits(freq,mv,bits,lbits);
	g=1; mlen=mv-1;
/* loop */
	while (((1 << mlen) > n) && (g>0))
		{
/* adjust table so maximum length <= mlen */
/* Adapted from JPEG standard, Annex K, Figure K.3 */
		 while (mv > mlen)
			 {while (bits[mv-1]>0)
				 {i=mv-2;
				  while (bits[i-1]==0) i--;
				  bits[mv-1]-= 2;
				  bits[mv-2]++;
				  bits[i]+= 2;
				  bits[i-1]--;
				 }
			  mv--;
			 }
		 cb=count_bits(freq,mv,bits,lbits);
		 g=tb-cb;
		 if (g>0)
		 	{tb=cb;
			 *m=mv;
			 for (i=0; i<mv; i++) ltbl[i]=bits[i];
		 	}
		 mlen--;
		} /* while */

	free(bits);free(codesize);free(freq);
		*cmt=0;
	return(tb);
}

/* generates VLC tables */
/* tries to minimize total #bits by combining tables for different #s of levels */
/* returns total #bits (for data + overhead) */
/* max_tbls: maximum number of tables */
/* idcs: number of indices */
/* idx_to_lvls[idcs]: conversion from index to #levels */
/* nsamples[idcs]: #samples for each index; WARNING: the table is changed in this procedure */
/* count[idcs][lvls]: two-sided histogram for each index; WARNING: the table is changed in this procedure */
/* maxvlclen: maximum allowed length of VLC codeword */
/* lbits: #bits needed for maxvlclen */
/* tbl_idx[idcs]: which table(idx) to use for each index; needed for combined tables */
/* cwl[idcs]: actual maximum lengths of VLC codewords */
/* ltbl[idcs][maxvlclen]: number of codewords of each length up to cwl */
/* rice[idcs]: parameter "m" of Rice code */
/* cmt[idcs]: coding method: 0 -> HiTBL, 1-> Rice code */
int gen_vlc_tables(int max_tbls,int idcs,int idx_to_lvls[],int nsamples[],short count[ORDER_LPC+1][36],int maxvlclen,int lbits,int tbl_idx[],int cwl[],int ltbl[NLEVELS][MAX_VLC_LEN],int rice[],int cmt[])
{
	int	i,max_tbl,lo_tbl,hi_tbl,max_gain,offset,hi_lvls,lo_lvls,nbts;
	int	ml,tb,ntbls,r,c;
	int	*nr_bits,*hltbl,*gains;
	short *hst;
	float unc;
	
/* INITIALIZE */
/* allocate mem */
	if ((nr_bits = (int *) malloc(idcs * sizeof(int))) == NULL) fprintf(stderr,"malloc failure in gen_vlc_tables\n"),exit(1);
/* get cost for each non-null table */
	tb=0;
	for (i=1; i<idcs; i++)
		if (nsamples[i] != 0)
			{nr_bits[i]=get_lengths(idx_to_lvls[i],count[i],maxvlclen,lbits,&(cwl[i]),ltbl[i],&(rice[i]),&(cmt[i]));
			 tb+=nr_bits[i];
			}

	free(nr_bits);
/* RETURN TOTAL #BITS */
	return(tb);
}


