#include "amp.h"
#include "audio.h"
#define GETBITS
#include "getbits.h"
#include <string.h>
static inline int _fillbfr(unsigned int size)
{
_bptr=0;
return get_input(_buffer, size);
}
static inline int readsync()
{
_bptr=0;
_buffer[0]=_buffer[1];
_buffer[1]=_buffer[2];
_buffer[2]=_buffer[3];
return get_input(&_buffer[3],1);
}
static inline unsigned int _getbits(int n)
{
unsigned int pos,ret_value;
pos = _bptr >> 3;
ret_value = _buffer[pos] << 24 |
_buffer[pos+1] << 16 |
_buffer[pos+2] << 8 |
_buffer[pos+3];
ret_value <<= _bptr & 7;
ret_value >>= 32 - n;
_bptr += n;
return ret_value;
}
int fillbfr(unsigned int advance)
{
int overflow,retval;
retval=get_input(&buffer[append], advance);
if ( append + advance >= BUFFER_SIZE) {
overflow = append + advance - BUFFER_SIZE;
memcpy (buffer,&buffer[BUFFER_SIZE], overflow);
if (overflow < 4) memcpy(&buffer[BUFFER_SIZE],buffer,4);
append = overflow;
} else {
if (append==0) memcpy(&buffer[BUFFER_SIZE],buffer,4);
append+=advance;
}
return retval;
}
unsigned int getbits(int n)
{
if (n) {
unsigned int pos,ret_value;
pos = data >> 3;
ret_value = buffer[pos] << 24 |
buffer[pos+1] << 16 |
buffer[pos+2] << 8 |
buffer[pos+3];
ret_value <<= data & 7;
ret_value >>= 32 - n;
data += n;
data &= (8*BUFFER_SIZE)-1;
return ret_value;
} else
return 0;
}
static inline void parse_header(struct AUDIO_HEADER *header)
{
header->ID=_getbits(1);
header->layer=_getbits(2);
header->protection_bit=_getbits(1);
header->bitrate_index=_getbits(4);
header->sampling_frequency=_getbits(2);
header->padding_bit=_getbits(1);
header->private_bit=_getbits(1);
header->mode=_getbits(2);
header->mode_extension=_getbits(2);
if (!header->mode) header->mode_extension=0;
header->copyright=_getbits(1);
header->original=_getbits(1);
header->emphasis=_getbits(2);
}
static inline int header_sanity_check(struct AUDIO_HEADER *header)
{
if ( header->layer==0 ||
header->bitrate_index==15 ||
header->sampling_frequency==3) return -1;
if ( header->ID==1 && header->layer==3 && header->protection_bit==1) return -1;
return 0;
}
int gethdr(struct AUDIO_HEADER *header)
{
int s,retval;
struct AUDIO_HEADER tmp;
if ((retval=_fillbfr(4))!=0) return retval;
for(;;) {
while ((s=_getbits(12)) != 0xfff) {
if (s==0xffe) {
parse_header(&tmp);
if (header_sanity_check(&tmp)==0) return GETHDR_NS;
}
if ((retval=readsync())!=0) return retval;
}
parse_header(&tmp);
if (header_sanity_check(&tmp)!=0) {
if ((retval=readsync())!=0) return retval;
} else break;
}
if (tmp.layer==3) return GETHDR_FL1;
if (tmp.bitrate_index==0) return GETHDR_FF;
memcpy(header,&tmp,sizeof(tmp));
return 0;
}
void getcrc()
{
_fillbfr(2);
_getbits(16);
}
void getinfo(struct AUDIO_HEADER *header,struct SIDE_INFO *info)
{
int gr,ch,scfsi_band,region,window;
int nch;
if (header->mode==3) {
nch=1;
if (header->ID) {
_fillbfr(17);
info->main_data_begin=_getbits(9);
_getbits(5);
} else {
_fillbfr(9);
info->main_data_begin=_getbits(8);
_getbits(1);
}
} else {
nch=2;
if (header->ID) {
_fillbfr(32);
info->main_data_begin=_getbits(9);
_getbits(3);
} else {
_fillbfr(17);
info->main_data_begin=_getbits(8);
_getbits(2);
}
}
if (header->ID) for (ch=0;ch<nch;ch++)
for (scfsi_band=0;scfsi_band<4;scfsi_band++)
info->scfsi[ch][scfsi_band]=_getbits(1);
for (gr=0;gr<(header->ID ? 2:1);gr++)
for (ch=0;ch<nch;ch++) {
info->part2_3_length[gr][ch]=_getbits(12);
info->big_values[gr][ch]=_getbits(9);
info->global_gain[gr][ch]=_getbits(8);
if (header->ID) info->scalefac_compress[gr][ch]=_getbits(4);
else info->scalefac_compress[gr][ch]=_getbits(9);
info->window_switching_flag[gr][ch]=_getbits(1);
if (info->window_switching_flag[gr][ch]) {
info->block_type[gr][ch]=_getbits(2);
info->mixed_block_flag[gr][ch]=_getbits(1);
for (region=0;region<2;region++)
info->table_select[gr][ch][region]=_getbits(5);
info->table_select[gr][ch][2]=0;
for (window=0;window<3;window++)
info->subblock_gain[gr][ch][window]=_getbits(3);
} else {
for (region=0;region<3;region++)
info->table_select[gr][ch][region]=_getbits(5);
info->region0_count[gr][ch]=_getbits(4);
info->region1_count[gr][ch]=_getbits(3);
info->block_type[gr][ch]=0;
}
if (header->ID) info->preflag[gr][ch]=_getbits(1);
info->scalefac_scale[gr][ch]=_getbits(1);
info->count1table_select[gr][ch]=_getbits(1);
}
return;
}
int dummy_getinfo(int n)
{
n-=4;
if ( fseek(in_file,n,SEEK_CUR) != 0)
{
if (feof(in_file))
return GETHDR_EOF;
else
return GETHDR_ERR;
}
return 0;
}
int rewind_stream(int nbytes)
{
nbytes+=5;
if (fseek(in_file, -nbytes, SEEK_CUR) != 0)
{
nbytes--;
if (fseek(in_file, -nbytes, SEEK_CUR) != 0)
return GETHDR_ERR;
}
return 0;
}
static inline int get_input(unsigned char* bp, unsigned int size)
{
#ifdef LINUX_REALTIME
return prefetch_get_input(bp,size);
#else
if ( fread( bp , 1, size, in_file) != size)
{
if (feof(in_file))
return GETHDR_EOF;
else
return GETHDR_ERR;
}
return 0;
#endif
}