Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
BitchX
GitHub Repository: BitchX/BitchX1.3
Path: blob/master/dll/amp/getbits.c
1072 views
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
*/
20
static inline int _fillbfr(unsigned int size)
21
{
22
_bptr=0;
23
return get_input(_buffer, size);
24
}
25
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
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
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
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
*/
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
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
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
*/
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
*/
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
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
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
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
278