diff options
Diffstat (limited to 'setedit/mp3/libamp/getbits.c')
-rw-r--r-- | setedit/mp3/libamp/getbits.c | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/setedit/mp3/libamp/getbits.c b/setedit/mp3/libamp/getbits.c new file mode 100644 index 0000000..6a1577e --- /dev/null +++ b/setedit/mp3/libamp/getbits.c @@ -0,0 +1,274 @@ +/* this file is a part of amp software, (C) tomislav uzelac 1996,1997 +*/ + +/* getbits.c bit level routines, input buffer + * + * Created by: tomislav uzelac Apr 1996 + * better synchronization, tomislav uzelac, Apr 23 1997 + */ +#include "amp.h" +#include "audio.h" +#include "formats.h" +#include "rtbuf.h" + +#define GETBITS +#include "getbits.h" + +/* + * buffer and bit manipulation functions *************************************** + */ +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; +} + +/* + * header and side info parsing stuff ****************************************** + */ +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; + + /* an additional check to make shure that stuffing never gets mistaken + * for a syncword. This rules out some legal layer1 streams, but who + * cares about layer1 anyway :-). I must get this right sometime. + */ + 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; + + /* TODO: add a simple byte counter to check only first, say, 1024 + * bytes for a new header and then return GETHDR_SYN + */ + 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.layer==2) return GETHDR_FL2; */ + if (tmp.bitrate_index==0) return GETHDR_FF; + + memcpy(header,&tmp,sizeof(tmp)); + return 0; +} + +/* dummy function, to get crc out of the way +*/ +void getcrc() +{ + _fillbfr(2); + _getbits(16); +} + +/* sizes of side_info: + * MPEG1 1ch 17 2ch 32 + * MPEG2 1ch 9 2ch 17 + */ +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) { + /* what if we need to be at the very beginning? */ + 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 /* LINUX_REALTIME */ + if ( fread( bp , 1, size, in_file) != size) + { + if (feof(in_file)) + return GETHDR_EOF; + else + return GETHDR_ERR; + } + return 0; +#endif /* LINUX_REALTIME */ +} |