1 /* this file is a part of amp software, (C) tomislav uzelac 1996,1997
2 */
3 
4 /* getbits.c  bit level routines, input buffer
5  *
6  * Created by: tomislav uzelac  Apr 1996
7  * better synchronization, tomislav uzelac, Apr 23 1997
8  */
9 #include "amp.h"
10 #include "audio.h"
11 
12 #define	GETBITS
13 #include "getbits.h"
14 
15 #include <string.h>
16 
17 /*
18  * buffer and bit manipulation functions ***************************************
19  */
_fillbfr(unsigned int size)20 static inline int _fillbfr(unsigned int size)
21 {
22 	_bptr=0;
23         return get_input(_buffer, size);
24 }
25 
readsync()26 static inline int readsync()
27 {
28 	_bptr=0;
29 	_buffer[0]=_buffer[1];
30 	_buffer[1]=_buffer[2];
31 	_buffer[2]=_buffer[3];
32 	return get_input(&_buffer[3],1);
33 }
34 
_getbits(int n)35 static inline unsigned int _getbits(int n)
36 {
37 unsigned int pos,ret_value;
38 
39         pos = _bptr >> 3;
40 	ret_value = _buffer[pos] << 24 |
41 		    _buffer[pos+1] << 16 |
42 		    _buffer[pos+2] << 8 |
43 		    _buffer[pos+3];
44         ret_value <<= _bptr & 7;
45         ret_value >>= 32 - n;
46         _bptr += n;
47         return ret_value;
48 }
49 
fillbfr(unsigned int advance)50 int fillbfr(unsigned int advance)
51 {
52 int overflow,retval;
53 
54         retval=get_input(&buffer[append], advance);
55 
56 	if ( append + advance >= BUFFER_SIZE) {
57 		overflow = append + advance - BUFFER_SIZE;
58 		memcpy (buffer,&buffer[BUFFER_SIZE], overflow);
59 		if (overflow < 4) memcpy(&buffer[BUFFER_SIZE],buffer,4);
60 		append = overflow;
61 	} else {
62 		if (append==0) memcpy(&buffer[BUFFER_SIZE],buffer,4);
63 		append+=advance;
64 	}
65 	return retval;
66 }
67 
getbits(int n)68 unsigned int getbits(int n)
69 {
70         if (n) {
71         unsigned int pos,ret_value;
72 
73                 pos = data >> 3;
74                 ret_value = buffer[pos] << 24 |
75                         buffer[pos+1] << 16 |
76                         buffer[pos+2] << 8 |
77                         buffer[pos+3];
78                 ret_value <<= data & 7;
79                 ret_value >>= 32 - n;
80 
81                 data += n;
82                 data &= (8*BUFFER_SIZE)-1;
83 
84                 return ret_value;
85         } else
86                 return 0;
87 }
88 
89 /*
90  * header and side info parsing stuff ******************************************
91  */
parse_header(struct AUDIO_HEADER * header)92 static inline void parse_header(struct AUDIO_HEADER *header)
93 {
94         header->ID=_getbits(1);
95         header->layer=_getbits(2);
96         header->protection_bit=_getbits(1);
97         header->bitrate_index=_getbits(4);
98         header->sampling_frequency=_getbits(2);
99         header->padding_bit=_getbits(1);
100         header->private_bit=_getbits(1);
101         header->mode=_getbits(2);
102         header->mode_extension=_getbits(2);
103         if (!header->mode) header->mode_extension=0;
104         header->copyright=_getbits(1);
105         header->original=_getbits(1);
106         header->emphasis=_getbits(2);
107 }
108 
header_sanity_check(struct AUDIO_HEADER * header)109 static inline int header_sanity_check(struct AUDIO_HEADER *header)
110 {
111 	if ( 	header->layer==0 ||
112 		header->bitrate_index==15 ||
113 		header->sampling_frequency==3) return -1;
114 
115 	/* an additional check to make shure that stuffing never gets mistaken
116  	 * for a syncword. This rules out some legal layer1 streams, but who
117  	 * cares about layer1 anyway :-). I must get this right sometime.
118 	 */
119 	if ( header->ID==1 && header->layer==3 && header->protection_bit==1) return -1;
120 	return 0;
121 }
122 
123 
gethdr(struct AUDIO_HEADER * header)124 int gethdr(struct AUDIO_HEADER *header)
125 {
126 int s,retval;
127 struct AUDIO_HEADER tmp;
128 
129 	/* TODO: add a simple byte counter to check only first, say, 1024
130 	 * bytes for a new header and then return GETHDR_SYN
131 	 */
132 	if ((retval=_fillbfr(4))!=0) return retval;
133 
134 	for(;;) {
135 		while ((s=_getbits(12)) != 0xfff) {
136 			if (s==0xffe) {
137 				parse_header(&tmp);
138 				if (header_sanity_check(&tmp)==0) return GETHDR_NS;
139 			}
140 			if ((retval=readsync())!=0) return retval;
141 		}
142 
143 		parse_header(&tmp);
144 		if (header_sanity_check(&tmp)!=0) {
145 			if ((retval=readsync())!=0) return retval;
146 		} else break;
147 	}
148 
149 	if (tmp.layer==3) return GETHDR_FL1;
150 	/* if (tmp.layer==2) return GETHDR_FL2; */
151 	if (tmp.bitrate_index==0) return GETHDR_FF;
152 
153 	memcpy(header,&tmp,sizeof(tmp));
154 	return 0;
155 }
156 
157 /* dummy function, to get crc out of the way
158 */
getcrc()159 void getcrc()
160 {
161 	_fillbfr(2);
162 	_getbits(16);
163 }
164 
165 /* sizes of side_info:
166  * MPEG1   1ch 17    2ch 32
167  * MPEG2   1ch  9    2ch 17
168  */
getinfo(struct AUDIO_HEADER * header,struct SIDE_INFO * info)169 void getinfo(struct AUDIO_HEADER *header,struct SIDE_INFO *info)
170 {
171 int gr,ch,scfsi_band,region,window;
172 int nch;
173 	if (header->mode==3) {
174 		nch=1;
175 		if (header->ID) {
176 			_fillbfr(17);
177 			info->main_data_begin=_getbits(9);
178 			_getbits(5);
179 		} else {
180 			_fillbfr(9);
181 			info->main_data_begin=_getbits(8);
182 			_getbits(1);
183 		}
184 	} else {
185 		nch=2;
186                 if (header->ID) {
187 			_fillbfr(32);
188                         info->main_data_begin=_getbits(9);
189                         _getbits(3);
190                 } else {
191 			_fillbfr(17);
192                         info->main_data_begin=_getbits(8);
193                         _getbits(2);
194                 }
195 	}
196 
197 	if (header->ID) for (ch=0;ch<nch;ch++)
198 		for (scfsi_band=0;scfsi_band<4;scfsi_band++)
199 			info->scfsi[ch][scfsi_band]=_getbits(1);
200 
201 	for (gr=0;gr<(header->ID ? 2:1);gr++)
202 		for (ch=0;ch<nch;ch++) {
203 			info->part2_3_length[gr][ch]=_getbits(12);
204 			info->big_values[gr][ch]=_getbits(9);
205 			info->global_gain[gr][ch]=_getbits(8);
206 			if (header->ID) info->scalefac_compress[gr][ch]=_getbits(4);
207 			else info->scalefac_compress[gr][ch]=_getbits(9);
208 			info->window_switching_flag[gr][ch]=_getbits(1);
209 
210 			if (info->window_switching_flag[gr][ch]) {
211 				info->block_type[gr][ch]=_getbits(2);
212 				info->mixed_block_flag[gr][ch]=_getbits(1);
213 
214 				for (region=0;region<2;region++)
215 					info->table_select[gr][ch][region]=_getbits(5);
216 				info->table_select[gr][ch][2]=0;
217 
218 				for (window=0;window<3;window++)
219 					info->subblock_gain[gr][ch][window]=_getbits(3);
220 			} else {
221 				for (region=0;region<3;region++)
222 					info->table_select[gr][ch][region]=_getbits(5);
223 
224 				info->region0_count[gr][ch]=_getbits(4);
225 				info->region1_count[gr][ch]=_getbits(3);
226 				info->block_type[gr][ch]=0;
227 			}
228 
229 			if (header->ID) info->preflag[gr][ch]=_getbits(1);
230 			info->scalefac_scale[gr][ch]=_getbits(1);
231 			info->count1table_select[gr][ch]=_getbits(1);
232 		}
233 	return;
234 }
235 
dummy_getinfo(int n)236 int dummy_getinfo(int n)
237 {
238 	n-=4;
239         if ( fseek(in_file,n,SEEK_CUR) != 0)
240 	{
241                 if (feof(in_file))
242                 	return GETHDR_EOF;
243                 else
244                 	return GETHDR_ERR;
245 	}
246 	return 0;
247 }
248 
rewind_stream(int nbytes)249 int rewind_stream(int nbytes)
250 {
251 	nbytes+=5;
252 	if (fseek(in_file, -nbytes, SEEK_CUR) != 0)
253 	{
254 		/* what if we need to be at the very beginning? */
255 		nbytes--;
256 		if (fseek(in_file, -nbytes, SEEK_CUR) != 0)
257 			return GETHDR_ERR;
258 	}
259 	return 0;
260 }
261 
get_input(unsigned char * bp,unsigned int size)262 static inline int get_input(unsigned char* bp, unsigned int size)
263 {
264 #ifdef LINUX_REALTIME
265         return prefetch_get_input(bp,size);
266 #else /* LINUX_REALTIME */
267 	if ( fread( bp , 1, size, in_file) != size)
268 	{
269                 if (feof(in_file))
270                 	return GETHDR_EOF;
271                 else
272                 	return GETHDR_ERR;
273 	}
274 	return 0;
275 #endif /* LINUX_REALTIME */
276 }
277