Rev 1905 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1905 | serge | 1 | /* |
2 | frame: Heap of routines dealing with the core mpg123 data structure. |
||
3 | |||
3960 | Serge | 4 | copyright 2008-2010 by the mpg123 project - free software under the terms of the LGPL 2.1 |
1905 | serge | 5 | see COPYING and AUTHORS files in distribution or http://mpg123.org |
6 | initially written by Thomas Orgis |
||
7 | */ |
||
8 | |||
9 | #include "mpg123lib_intern.h" |
||
10 | #include "getcpuflags.h" |
||
11 | #include "debug.h" |
||
12 | |||
13 | static void frame_fixed_reset(mpg123_handle *fr); |
||
14 | |||
15 | /* that's doubled in decode_ntom.c */ |
||
16 | #define NTOM_MUL (32768) |
||
3960 | Serge | 17 | |
18 | #define aligned_pointer(p, type, alignment) align_the_pointer(p, alignment) |
||
19 | static void *align_the_pointer(void *base, unsigned int alignment) |
||
1905 | serge | 20 | { |
3960 | Serge | 21 | /* |
22 | Work in unsigned integer realm, explicitly. |
||
23 | Tricking the compiler into integer operations like % by invoking base-NULL is dangerous: It results into ptrdiff_t, which gets negative on big addresses. Big screw up, that. |
||
24 | I try to do it "properly" here: Casting only to uintptr_t and no artihmethic with void*. |
||
25 | */ |
||
26 | uintptr_t baseval = (uintptr_t)(char*)base; |
||
27 | uintptr_t aoff = baseval % alignment; |
||
28 | |||
29 | debug3("align_the_pointer: pointer %p is off by %u from %u", |
||
30 | base, (unsigned int)aoff, alignment); |
||
31 | |||
32 | if(aoff) return (char*)base+alignment-aoff; |
||
33 | else return base; |
||
34 | } |
||
35 | |||
36 | static void frame_default_pars(mpg123_pars *mp) |
||
37 | { |
||
1905 | serge | 38 | mp->outscale = 1.0; |
3960 | Serge | 39 | mp->flags = 0; |
1905 | serge | 40 | #ifdef GAPLESS |
3960 | Serge | 41 | mp->flags |= MPG123_GAPLESS; |
1905 | serge | 42 | #endif |
3960 | Serge | 43 | mp->flags |= MPG123_AUTO_RESAMPLE; |
1905 | serge | 44 | #ifndef NO_NTOM |
45 | mp->force_rate = 0; |
||
46 | #endif |
||
47 | mp->down_sample = 0; |
||
48 | mp->rva = 0; |
||
49 | mp->halfspeed = 0; |
||
50 | mp->doublespeed = 0; |
||
51 | mp->verbose = 0; |
||
52 | #ifndef NO_ICY |
||
53 | mp->icy_interval = 0; |
||
54 | #endif |
||
55 | mp->timeout = 0; |
||
56 | mp->resync_limit = 1024; |
||
57 | #ifdef FRAME_INDEX |
||
58 | mp->index_size = INDEX_SIZE; |
||
59 | #endif |
||
60 | mp->preframes = 4; /* That's good for layer 3 ISO compliance bitstream. */ |
||
61 | mpg123_fmt_all(mp); |
||
3960 | Serge | 62 | /* Default of keeping some 4K buffers at hand, should cover the "usual" use case (using 16K pipe buffers as role model). */ |
63 | #ifndef NO_FEEDER |
||
64 | mp->feedpool = 5; |
||
65 | mp->feedbuffer = 4096; |
||
66 | #endif |
||
1905 | serge | 67 | } |
68 | |||
69 | void frame_init(mpg123_handle *fr) |
||
70 | { |
||
71 | frame_init_par(fr, NULL); |
||
72 | } |
||
73 | |||
74 | void frame_init_par(mpg123_handle *fr, mpg123_pars *mp) |
||
75 | { |
||
3960 | Serge | 76 | fr->own_buffer = TRUE; |
1905 | serge | 77 | fr->buffer.data = NULL; |
3960 | Serge | 78 | fr->buffer.rdata = NULL; |
79 | fr->buffer.fill = 0; |
||
80 | fr->buffer.size = 0; |
||
1905 | serge | 81 | fr->rawbuffs = NULL; |
82 | fr->rawbuffss = 0; |
||
83 | fr->rawdecwin = NULL; |
||
84 | fr->rawdecwins = 0; |
||
85 | #ifndef NO_8BIT |
||
86 | fr->conv16to8_buf = NULL; |
||
87 | #endif |
||
88 | #ifdef OPT_DITHER |
||
89 | fr->dithernoise = NULL; |
||
90 | #endif |
||
3960 | Serge | 91 | fr->layerscratch = NULL; |
1905 | serge | 92 | fr->xing_toc = NULL; |
93 | fr->cpu_opts.type = defdec(); |
||
94 | fr->cpu_opts.class = decclass(fr->cpu_opts.type); |
||
95 | #ifndef NO_NTOM |
||
96 | /* these two look unnecessary, check guarantee for synth_ntom_set_step (in control_generic, even)! */ |
||
97 | fr->ntom_val[0] = NTOM_MUL>>1; |
||
98 | fr->ntom_val[1] = NTOM_MUL>>1; |
||
99 | fr->ntom_step = NTOM_MUL; |
||
100 | #endif |
||
101 | /* unnecessary: fr->buffer.size = fr->buffer.fill = 0; */ |
||
102 | mpg123_reset_eq(fr); |
||
103 | init_icy(&fr->icy); |
||
104 | init_id3(fr); |
||
105 | /* frame_outbuffer is missing... */ |
||
106 | /* frame_buffers is missing... that one needs cpu opt setting! */ |
||
107 | /* after these... frame_reset is needed before starting full decode */ |
||
108 | invalidate_format(&fr->af); |
||
109 | fr->rdat.r_read = NULL; |
||
110 | fr->rdat.r_lseek = NULL; |
||
3960 | Serge | 111 | fr->rdat.iohandle = NULL; |
112 | fr->rdat.r_read_handle = NULL; |
||
113 | fr->rdat.r_lseek_handle = NULL; |
||
114 | fr->rdat.cleanup_handle = NULL; |
||
115 | fr->wrapperdata = NULL; |
||
116 | fr->wrapperclean = NULL; |
||
1905 | serge | 117 | fr->decoder_change = 1; |
118 | fr->err = MPG123_OK; |
||
119 | if(mp == NULL) frame_default_pars(&fr->p); |
||
120 | else memcpy(&fr->p, mp, sizeof(struct mpg123_pars_struct)); |
||
121 | |||
3960 | Serge | 122 | #ifndef NO_FEEDER |
123 | bc_prepare(&fr->rdat.buffer, fr->p.feedpool, fr->p.feedbuffer); |
||
124 | #endif |
||
125 | |||
1905 | serge | 126 | fr->down_sample = 0; /* Initialize to silence harmless errors when debugging. */ |
127 | frame_fixed_reset(fr); /* Reset only the fixed data, dynamic buffers are not there yet! */ |
||
128 | fr->synth = NULL; |
||
129 | fr->synth_mono = NULL; |
||
130 | fr->make_decode_tables = NULL; |
||
131 | #ifdef FRAME_INDEX |
||
132 | fi_init(&fr->index); |
||
133 | frame_index_setup(fr); /* Apply the size setting. */ |
||
134 | #endif |
||
135 | } |
||
136 | |||
137 | #ifdef OPT_DITHER |
||
138 | /* Also, only allocate the memory for the table on demand. |
||
139 | In future, one could create special noise for different sampling frequencies(?). */ |
||
140 | int frame_dither_init(mpg123_handle *fr) |
||
141 | { |
||
142 | /* run-time dither noise table generation */ |
||
143 | if(fr->dithernoise == NULL) |
||
144 | { |
||
145 | fr->dithernoise = malloc(sizeof(float)*DITHERSIZE); |
||
146 | if(fr->dithernoise == NULL) return 0; |
||
147 | |||
148 | dither_table_init(fr->dithernoise); |
||
149 | } |
||
150 | return 1; |
||
151 | } |
||
152 | #endif |
||
153 | |||
154 | mpg123_pars attribute_align_arg *mpg123_new_pars(int *error) |
||
155 | { |
||
156 | mpg123_pars *mp = malloc(sizeof(struct mpg123_pars_struct)); |
||
157 | if(mp != NULL){ frame_default_pars(mp); if(error != NULL) *error = MPG123_OK; } |
||
158 | else if(error != NULL) *error = MPG123_OUT_OF_MEM; |
||
159 | return mp; |
||
160 | } |
||
161 | |||
162 | void attribute_align_arg mpg123_delete_pars(mpg123_pars* mp) |
||
163 | { |
||
164 | if(mp != NULL) free(mp); |
||
165 | } |
||
166 | |||
167 | int attribute_align_arg mpg123_reset_eq(mpg123_handle *mh) |
||
168 | { |
||
169 | int i; |
||
170 | mh->have_eq_settings = 0; |
||
171 | for(i=0; i < 32; ++i) mh->equalizer[0][i] = mh->equalizer[1][i] = DOUBLE_TO_REAL(1.0); |
||
172 | |||
173 | return MPG123_OK; |
||
174 | } |
||
175 | |||
176 | int frame_outbuffer(mpg123_handle *fr) |
||
177 | { |
||
3960 | Serge | 178 | size_t size = fr->outblock; |
179 | if(!fr->own_buffer) |
||
1905 | serge | 180 | { |
3960 | Serge | 181 | if(fr->buffer.size < size) |
182 | { |
||
183 | fr->err = MPG123_BAD_BUFFER; |
||
184 | if(NOQUIET) error2("have external buffer of size %"SIZE_P", need %"SIZE_P, (size_p)fr->buffer.size, size); |
||
185 | |||
186 | return MPG123_ERR; |
||
187 | } |
||
1905 | serge | 188 | } |
3960 | Serge | 189 | |
190 | debug1("need frame buffer of %"SIZE_P, (size_p)size); |
||
191 | if(fr->buffer.rdata != NULL && fr->buffer.size != size) |
||
192 | { |
||
193 | free(fr->buffer.rdata); |
||
194 | fr->buffer.rdata = NULL; |
||
195 | } |
||
1905 | serge | 196 | fr->buffer.size = size; |
3960 | Serge | 197 | fr->buffer.data = NULL; |
198 | /* be generous: use 16 byte alignment */ |
||
199 | if(fr->buffer.rdata == NULL) fr->buffer.rdata = (unsigned char*) malloc(fr->buffer.size+15); |
||
200 | if(fr->buffer.rdata == NULL) |
||
1905 | serge | 201 | { |
202 | fr->err = MPG123_OUT_OF_MEM; |
||
3960 | Serge | 203 | return MPG123_ERR; |
1905 | serge | 204 | } |
3960 | Serge | 205 | fr->buffer.data = aligned_pointer(fr->buffer.rdata, unsigned char*, 16); |
1905 | serge | 206 | fr->own_buffer = TRUE; |
207 | fr->buffer.fill = 0; |
||
3960 | Serge | 208 | return MPG123_OK; |
1905 | serge | 209 | } |
210 | |||
211 | int attribute_align_arg mpg123_replace_buffer(mpg123_handle *mh, unsigned char *data, size_t size) |
||
212 | { |
||
3960 | Serge | 213 | debug2("replace buffer with %p size %"SIZE_P, data, (size_p)size); |
214 | /* Will accept any size, the error comes later... */ |
||
215 | if(data == NULL) |
||
1905 | serge | 216 | { |
217 | mh->err = MPG123_BAD_BUFFER; |
||
218 | return MPG123_ERR; |
||
219 | } |
||
3960 | Serge | 220 | if(mh->buffer.rdata != NULL) free(mh->buffer.rdata); |
1905 | serge | 221 | mh->own_buffer = FALSE; |
3960 | Serge | 222 | mh->buffer.rdata = NULL; |
1905 | serge | 223 | mh->buffer.data = data; |
224 | mh->buffer.size = size; |
||
225 | mh->buffer.fill = 0; |
||
226 | return MPG123_OK; |
||
227 | } |
||
228 | |||
229 | #ifdef FRAME_INDEX |
||
230 | int frame_index_setup(mpg123_handle *fr) |
||
231 | { |
||
232 | int ret = MPG123_ERR; |
||
233 | if(fr->p.index_size >= 0) |
||
234 | { /* Simple fixed index. */ |
||
235 | fr->index.grow_size = 0; |
||
236 | debug1("resizing index to %li", fr->p.index_size); |
||
237 | ret = fi_resize(&fr->index, (size_t)fr->p.index_size); |
||
238 | debug2("index resized... %lu at %p", (unsigned long)fr->index.size, (void*)fr->index.data); |
||
239 | } |
||
240 | else |
||
241 | { /* A growing index. We give it a start, though. */ |
||
242 | fr->index.grow_size = (size_t)(- fr->p.index_size); |
||
243 | if(fr->index.size < fr->index.grow_size) |
||
244 | ret = fi_resize(&fr->index, fr->index.grow_size); |
||
245 | else |
||
246 | ret = MPG123_OK; /* We have minimal size already... and since growing is OK... */ |
||
247 | } |
||
248 | debug2("set up frame index of size %lu (ret=%i)", (unsigned long)fr->index.size, ret); |
||
249 | |||
250 | return ret; |
||
251 | } |
||
252 | #endif |
||
253 | |||
254 | static void frame_decode_buffers_reset(mpg123_handle *fr) |
||
255 | { |
||
256 | memset(fr->rawbuffs, 0, fr->rawbuffss); |
||
257 | } |
||
258 | |||
259 | int frame_buffers(mpg123_handle *fr) |
||
260 | { |
||
261 | int buffssize = 0; |
||
262 | debug1("frame %p buffer", (void*)fr); |
||
263 | /* |
||
264 | the used-to-be-static buffer of the synth functions, has some subtly different types/sizes |
||
265 | |||
266 | 2to1, 4to1, ntom, generic, i386: real[2][2][0x110] |
||
267 | mmx, sse: short[2][2][0x110] |
||
268 | i586(_dither): 4352 bytes; int/long[2][2][0x110] |
||
269 | i486: int[2][2][17*FIR_BUFFER_SIZE] |
||
270 | altivec: static real __attribute__ ((aligned (16))) buffs[4][4][0x110] |
||
271 | |||
272 | Huh, altivec looks like fun. Well, let it be large... then, the 16 byte alignment seems to be implicit on MacOSX malloc anyway. |
||
273 | Let's make a reasonable attempt to allocate enough memory... |
||
274 | Keep in mind: biggest ones are i486 and altivec (mutually exclusive!), then follows i586 and normal real. |
||
275 | mmx/sse use short but also real for resampling. |
||
276 | Thus, minimum is 2*2*0x110*sizeof(real). |
||
277 | */ |
||
278 | if(fr->cpu_opts.type == altivec) buffssize = 4*4*0x110*sizeof(real); |
||
279 | #ifdef OPT_I486 |
||
280 | else if(fr->cpu_opts.type == ivier) buffssize = 2*2*17*FIR_BUFFER_SIZE*sizeof(int); |
||
281 | #endif |
||
282 | else if(fr->cpu_opts.type == ifuenf || fr->cpu_opts.type == ifuenf_dither || fr->cpu_opts.type == dreidnow) |
||
283 | buffssize = 2*2*0x110*4; /* don't rely on type real, we need 4352 bytes */ |
||
284 | |||
285 | if(2*2*0x110*sizeof(real) > buffssize) |
||
286 | buffssize = 2*2*0x110*sizeof(real); |
||
287 | buffssize += 15; /* For 16-byte alignment (SSE likes that). */ |
||
288 | |||
289 | if(fr->rawbuffs != NULL && fr->rawbuffss != buffssize) |
||
290 | { |
||
291 | free(fr->rawbuffs); |
||
292 | fr->rawbuffs = NULL; |
||
293 | } |
||
294 | |||
295 | if(fr->rawbuffs == NULL) fr->rawbuffs = (unsigned char*) malloc(buffssize); |
||
296 | if(fr->rawbuffs == NULL) return -1; |
||
297 | fr->rawbuffss = buffssize; |
||
298 | fr->short_buffs[0][0] = aligned_pointer(fr->rawbuffs,short,16); |
||
299 | fr->short_buffs[0][1] = fr->short_buffs[0][0] + 0x110; |
||
300 | fr->short_buffs[1][0] = fr->short_buffs[0][1] + 0x110; |
||
301 | fr->short_buffs[1][1] = fr->short_buffs[1][0] + 0x110; |
||
302 | fr->real_buffs[0][0] = aligned_pointer(fr->rawbuffs,real,16); |
||
303 | fr->real_buffs[0][1] = fr->real_buffs[0][0] + 0x110; |
||
304 | fr->real_buffs[1][0] = fr->real_buffs[0][1] + 0x110; |
||
305 | fr->real_buffs[1][1] = fr->real_buffs[1][0] + 0x110; |
||
306 | #ifdef OPT_I486 |
||
307 | if(fr->cpu_opts.type == ivier) |
||
308 | { |
||
309 | fr->int_buffs[0][0] = (int*) fr->rawbuffs; |
||
310 | fr->int_buffs[0][1] = fr->int_buffs[0][0] + 17*FIR_BUFFER_SIZE; |
||
311 | fr->int_buffs[1][0] = fr->int_buffs[0][1] + 17*FIR_BUFFER_SIZE; |
||
312 | fr->int_buffs[1][1] = fr->int_buffs[1][0] + 17*FIR_BUFFER_SIZE; |
||
313 | } |
||
314 | #endif |
||
315 | #ifdef OPT_ALTIVEC |
||
316 | if(fr->cpu_opts.type == altivec) |
||
317 | { |
||
318 | int i,j; |
||
319 | fr->areal_buffs[0][0] = (real*) fr->rawbuffs; |
||
320 | for(i=0; i<4; ++i) for(j=0; j<4; ++j) |
||
321 | fr->areal_buffs[i][j] = fr->areal_buffs[0][0] + (i*4+j)*0x110; |
||
322 | } |
||
323 | #endif |
||
324 | /* now the different decwins... all of the same size, actually */ |
||
325 | /* The MMX ones want 32byte alignment, which I'll try to ensure manually */ |
||
326 | { |
||
327 | int decwin_size = (512+32)*sizeof(real); |
||
328 | #ifdef OPT_MMXORSSE |
||
329 | #ifdef OPT_MULTI |
||
330 | if(fr->cpu_opts.class == mmxsse) |
||
331 | { |
||
332 | #endif |
||
333 | /* decwin_mmx will share, decwins will be appended ... sizeof(float)==4 */ |
||
334 | if(decwin_size < (512+32)*4) decwin_size = (512+32)*4; |
||
335 | |||
336 | /* the second window + alignment zone -- we align for 32 bytes for SSE as |
||
337 | requirement, 64 byte for matching cache line size (that matters!) */ |
||
338 | decwin_size += (512+32)*4 + 63; |
||
339 | /* (512+32)*4/32 == 2176/32 == 68, so one decwin block retains alignment for 32 or 64 bytes */ |
||
340 | #ifdef OPT_MULTI |
||
341 | } |
||
342 | #endif |
||
343 | #endif |
||
344 | #if defined(OPT_ALTIVEC) || defined(OPT_ARM) |
||
3960 | Serge | 345 | /* sizeof(real) >= 4 ... yes, it could be 8, for example. |
346 | We got it intialized to at least (512+32)*sizeof(real).*/ |
||
347 | decwin_size += 512*sizeof(real); |
||
1905 | serge | 348 | #endif |
349 | /* Hm, that's basically realloc() ... */ |
||
350 | if(fr->rawdecwin != NULL && fr->rawdecwins != decwin_size) |
||
351 | { |
||
352 | free(fr->rawdecwin); |
||
353 | fr->rawdecwin = NULL; |
||
354 | } |
||
355 | |||
356 | if(fr->rawdecwin == NULL) |
||
357 | fr->rawdecwin = (unsigned char*) malloc(decwin_size); |
||
358 | |||
359 | if(fr->rawdecwin == NULL) return -1; |
||
360 | |||
361 | fr->rawdecwins = decwin_size; |
||
362 | fr->decwin = (real*) fr->rawdecwin; |
||
363 | #ifdef OPT_MMXORSSE |
||
364 | #ifdef OPT_MULTI |
||
365 | if(fr->cpu_opts.class == mmxsse) |
||
366 | { |
||
367 | #endif |
||
368 | /* align decwin, assign that to decwin_mmx, append decwins */ |
||
369 | /* I need to add to decwin what is missing to the next full 64 byte -- also I want to make gcc -pedantic happy... */ |
||
370 | fr->decwin = aligned_pointer(fr->rawdecwin,real,64); |
||
371 | debug1("aligned decwin: %p", (void*)fr->decwin); |
||
372 | fr->decwin_mmx = (float*)fr->decwin; |
||
373 | fr->decwins = fr->decwin_mmx+512+32; |
||
374 | #ifdef OPT_MULTI |
||
375 | } |
||
376 | else debug("no decwins/decwin_mmx for that class"); |
||
377 | #endif |
||
378 | #endif |
||
379 | } |
||
3960 | Serge | 380 | |
381 | /* Layer scratch buffers are of compile-time fixed size, so allocate only once. */ |
||
382 | if(fr->layerscratch == NULL) |
||
383 | { |
||
384 | /* Allocate specific layer1/2/3 buffers, so that we know they'll work for SSE. */ |
||
385 | size_t scratchsize = 0; |
||
386 | real *scratcher; |
||
387 | #ifndef NO_LAYER1 |
||
388 | scratchsize += sizeof(real) * 2 * SBLIMIT; |
||
389 | #endif |
||
390 | #ifndef NO_LAYER2 |
||
391 | scratchsize += sizeof(real) * 2 * 4 * SBLIMIT; |
||
392 | #endif |
||
393 | #ifndef NO_LAYER3 |
||
394 | scratchsize += sizeof(real) * 2 * SBLIMIT * SSLIMIT; /* hybrid_in */ |
||
395 | scratchsize += sizeof(real) * 2 * SSLIMIT * SBLIMIT; /* hybrid_out */ |
||
396 | #endif |
||
397 | /* |
||
398 | Now figure out correct alignment: |
||
399 | We need 16 byte minimum, smallest unit of the blocks is 2*SBLIMIT*sizeof(real), which is 64*4=256. Let's do 64bytes as heuristic for cache line (as proven useful in buffs above). |
||
400 | */ |
||
401 | fr->layerscratch = malloc(scratchsize+63); |
||
402 | if(fr->layerscratch == NULL) return -1; |
||
403 | |||
404 | /* Get aligned part of the memory, then divide it up. */ |
||
405 | scratcher = aligned_pointer(fr->layerscratch,real,64); |
||
406 | /* Those funky pointer casts silence compilers... |
||
407 | One might change the code at hand to really just use 1D arrays, but in practice, that would not make a (positive) difference. */ |
||
408 | #ifndef NO_LAYER1 |
||
409 | fr->layer1.fraction = (real(*)[SBLIMIT])scratcher; |
||
410 | scratcher += 2 * SBLIMIT; |
||
411 | #endif |
||
412 | #ifndef NO_LAYER2 |
||
413 | fr->layer2.fraction = (real(*)[4][SBLIMIT])scratcher; |
||
414 | scratcher += 2 * 4 * SBLIMIT; |
||
415 | #endif |
||
416 | #ifndef NO_LAYER3 |
||
417 | fr->layer3.hybrid_in = (real(*)[SBLIMIT][SSLIMIT])scratcher; |
||
418 | scratcher += 2 * SBLIMIT * SSLIMIT; |
||
419 | fr->layer3.hybrid_out = (real(*)[SSLIMIT][SBLIMIT])scratcher; |
||
420 | scratcher += 2 * SSLIMIT * SBLIMIT; |
||
421 | #endif |
||
422 | /* Note: These buffers don't need resetting here. */ |
||
423 | } |
||
424 | |||
1905 | serge | 425 | /* Only reset the buffers we created just now. */ |
426 | frame_decode_buffers_reset(fr); |
||
427 | |||
428 | debug1("frame %p buffer done", (void*)fr); |
||
429 | return 0; |
||
430 | } |
||
431 | |||
432 | int frame_buffers_reset(mpg123_handle *fr) |
||
433 | { |
||
434 | fr->buffer.fill = 0; /* hm, reset buffer fill... did we do a flush? */ |
||
435 | fr->bsnum = 0; |
||
436 | /* Wondering: could it be actually _wanted_ to retain buffer contents over different files? (special gapless / cut stuff) */ |
||
437 | fr->bsbuf = fr->bsspace[1]; |
||
438 | fr->bsbufold = fr->bsbuf; |
||
3960 | Serge | 439 | fr->bitreservoir = 0; |
1905 | serge | 440 | frame_decode_buffers_reset(fr); |
441 | memset(fr->bsspace, 0, 2*(MAXFRAMESIZE+512)); |
||
442 | memset(fr->ssave, 0, 34); |
||
443 | fr->hybrid_blc[0] = fr->hybrid_blc[1] = 0; |
||
444 | memset(fr->hybrid_block, 0, sizeof(real)*2*2*SBLIMIT*SSLIMIT); |
||
445 | return 0; |
||
446 | } |
||
447 | |||
3960 | Serge | 448 | static void frame_icy_reset(mpg123_handle* fr) |
1905 | serge | 449 | { |
450 | #ifndef NO_ICY |
||
451 | if(fr->icy.data != NULL) free(fr->icy.data); |
||
452 | fr->icy.data = NULL; |
||
453 | fr->icy.interval = 0; |
||
454 | fr->icy.next = 0; |
||
455 | #endif |
||
456 | } |
||
457 | |||
3960 | Serge | 458 | static void frame_free_toc(mpg123_handle *fr) |
1905 | serge | 459 | { |
460 | if(fr->xing_toc != NULL){ free(fr->xing_toc); fr->xing_toc = NULL; } |
||
461 | } |
||
462 | |||
463 | /* Just copy the Xing TOC over... */ |
||
464 | int frame_fill_toc(mpg123_handle *fr, unsigned char* in) |
||
465 | { |
||
466 | if(fr->xing_toc == NULL) fr->xing_toc = malloc(100); |
||
467 | if(fr->xing_toc != NULL) |
||
468 | { |
||
469 | memcpy(fr->xing_toc, in, 100); |
||
470 | #ifdef DEBUG |
||
471 | debug("Got a TOC! Showing the values..."); |
||
472 | { |
||
473 | int i; |
||
474 | for(i=0; i<100; ++i) |
||
475 | debug2("entry %i = %i", i, fr->xing_toc[i]); |
||
476 | } |
||
477 | #endif |
||
478 | return TRUE; |
||
479 | } |
||
480 | return FALSE; |
||
481 | } |
||
482 | |||
483 | /* Prepare the handle for a new track. |
||
484 | Reset variables, buffers... */ |
||
485 | int frame_reset(mpg123_handle* fr) |
||
486 | { |
||
487 | frame_buffers_reset(fr); |
||
488 | frame_fixed_reset(fr); |
||
489 | frame_free_toc(fr); |
||
490 | #ifdef FRAME_INDEX |
||
491 | fi_reset(&fr->index); |
||
492 | #endif |
||
493 | |||
494 | return 0; |
||
495 | } |
||
496 | |||
497 | /* Reset everythign except dynamic memory. */ |
||
498 | static void frame_fixed_reset(mpg123_handle *fr) |
||
499 | { |
||
500 | frame_icy_reset(fr); |
||
501 | open_bad(fr); |
||
502 | fr->to_decode = FALSE; |
||
503 | fr->to_ignore = FALSE; |
||
504 | fr->metaflags = 0; |
||
3960 | Serge | 505 | fr->outblock = 0; /* This will be set before decoding! */ |
1905 | serge | 506 | fr->num = -1; |
3960 | Serge | 507 | fr->input_offset = -1; |
1905 | serge | 508 | fr->playnum = -1; |
3960 | Serge | 509 | fr->state_flags = FRAME_ACCURATE; |
1905 | serge | 510 | fr->silent_resync = 0; |
511 | fr->audio_start = 0; |
||
512 | fr->clip = 0; |
||
513 | fr->oldhead = 0; |
||
514 | fr->firsthead = 0; |
||
515 | fr->vbr = MPG123_CBR; |
||
516 | fr->abr_rate = 0; |
||
517 | fr->track_frames = 0; |
||
518 | fr->track_samples = -1; |
||
519 | fr->framesize=0; |
||
520 | fr->mean_frames = 0; |
||
521 | fr->mean_framesize = 0; |
||
522 | fr->freesize = 0; |
||
523 | fr->lastscale = -1; |
||
524 | fr->rva.level[0] = -1; |
||
525 | fr->rva.level[1] = -1; |
||
526 | fr->rva.gain[0] = 0; |
||
527 | fr->rva.gain[1] = 0; |
||
528 | fr->rva.peak[0] = 0; |
||
529 | fr->rva.peak[1] = 0; |
||
530 | fr->fsizeold = 0; |
||
531 | fr->firstframe = 0; |
||
532 | fr->ignoreframe = fr->firstframe-fr->p.preframes; |
||
533 | fr->lastframe = -1; |
||
534 | fr->fresh = 1; |
||
535 | fr->new_format = 0; |
||
536 | #ifdef GAPLESS |
||
3960 | Serge | 537 | frame_gapless_init(fr,-1,0,0); |
1905 | serge | 538 | fr->lastoff = 0; |
539 | fr->firstoff = 0; |
||
540 | #endif |
||
541 | #ifdef OPT_I486 |
||
542 | fr->i486bo[0] = fr->i486bo[1] = FIR_SIZE-1; |
||
543 | #endif |
||
544 | fr->bo = 1; /* the usual bo */ |
||
545 | #ifdef OPT_DITHER |
||
546 | fr->ditherindex = 0; |
||
547 | #endif |
||
548 | reset_id3(fr); |
||
549 | reset_icy(&fr->icy); |
||
550 | /* ICY stuff should go into icy.c, eh? */ |
||
551 | #ifndef NO_ICY |
||
552 | fr->icy.interval = 0; |
||
553 | fr->icy.next = 0; |
||
554 | #endif |
||
555 | fr->halfphase = 0; /* here or indeed only on first-time init? */ |
||
556 | fr->error_protection = 0; |
||
557 | fr->freeformat_framesize = -1; |
||
558 | } |
||
559 | |||
3960 | Serge | 560 | static void frame_free_buffers(mpg123_handle *fr) |
1905 | serge | 561 | { |
562 | if(fr->rawbuffs != NULL) free(fr->rawbuffs); |
||
563 | fr->rawbuffs = NULL; |
||
564 | fr->rawbuffss = 0; |
||
565 | if(fr->rawdecwin != NULL) free(fr->rawdecwin); |
||
566 | fr->rawdecwin = NULL; |
||
567 | fr->rawdecwins = 0; |
||
568 | #ifndef NO_8BIT |
||
569 | if(fr->conv16to8_buf != NULL) free(fr->conv16to8_buf); |
||
570 | fr->conv16to8_buf = NULL; |
||
571 | #endif |
||
3960 | Serge | 572 | if(fr->layerscratch != NULL) free(fr->layerscratch); |
1905 | serge | 573 | } |
574 | |||
575 | void frame_exit(mpg123_handle *fr) |
||
576 | { |
||
3960 | Serge | 577 | if(fr->buffer.rdata != NULL) |
1905 | serge | 578 | { |
3960 | Serge | 579 | debug1("freeing buffer at %p", (void*)fr->buffer.rdata); |
580 | free(fr->buffer.rdata); |
||
1905 | serge | 581 | } |
3960 | Serge | 582 | fr->buffer.rdata = NULL; |
1905 | serge | 583 | frame_free_buffers(fr); |
584 | frame_free_toc(fr); |
||
585 | #ifdef FRAME_INDEX |
||
586 | fi_exit(&fr->index); |
||
587 | #endif |
||
588 | #ifdef OPT_DITHER |
||
589 | if(fr->dithernoise != NULL) |
||
590 | { |
||
591 | free(fr->dithernoise); |
||
592 | fr->dithernoise = NULL; |
||
593 | } |
||
594 | #endif |
||
595 | exit_id3(fr); |
||
596 | clear_icy(&fr->icy); |
||
3960 | Serge | 597 | /* Clean up possible mess from LFS wrapper. */ |
598 | if(fr->wrapperclean != NULL) |
||
599 | { |
||
600 | fr->wrapperclean(fr->wrapperdata); |
||
601 | fr->wrapperdata = NULL; |
||
602 | } |
||
603 | #ifndef NO_FEEDER |
||
604 | bc_cleanup(&fr->rdat.buffer); |
||
605 | #endif |
||
1905 | serge | 606 | } |
607 | |||
608 | int attribute_align_arg mpg123_info(mpg123_handle *mh, struct mpg123_frameinfo *mi) |
||
609 | { |
||
610 | if(mh == NULL) return MPG123_ERR; |
||
611 | if(mi == NULL) |
||
612 | { |
||
613 | mh->err = MPG123_ERR_NULL; |
||
614 | return MPG123_ERR; |
||
615 | } |
||
616 | mi->version = mh->mpeg25 ? MPG123_2_5 : (mh->lsf ? MPG123_2_0 : MPG123_1_0); |
||
617 | mi->layer = mh->lay; |
||
618 | mi->rate = frame_freq(mh); |
||
619 | switch(mh->mode) |
||
620 | { |
||
621 | case 0: mi->mode = MPG123_M_STEREO; break; |
||
622 | case 1: mi->mode = MPG123_M_JOINT; break; |
||
623 | case 2: mi->mode = MPG123_M_DUAL; break; |
||
624 | case 3: mi->mode = MPG123_M_MONO; break; |
||
625 | default: error("That mode cannot be!"); |
||
626 | } |
||
627 | mi->mode_ext = mh->mode_ext; |
||
628 | mi->framesize = mh->framesize+4; /* Include header. */ |
||
629 | mi->flags = 0; |
||
630 | if(mh->error_protection) mi->flags |= MPG123_CRC; |
||
631 | if(mh->copyright) mi->flags |= MPG123_COPYRIGHT; |
||
632 | if(mh->extension) mi->flags |= MPG123_PRIVATE; |
||
633 | if(mh->original) mi->flags |= MPG123_ORIGINAL; |
||
634 | mi->emphasis = mh->emphasis; |
||
635 | mi->bitrate = frame_bitrate(mh); |
||
636 | mi->abr_rate = mh->abr_rate; |
||
637 | mi->vbr = mh->vbr; |
||
638 | return MPG123_OK; |
||
639 | } |
||
640 | |||
3960 | Serge | 641 | int attribute_align_arg mpg123_framedata(mpg123_handle *mh, unsigned long *header, unsigned char **bodydata, size_t *bodybytes) |
642 | { |
||
643 | if(mh == NULL) return MPG123_ERR; |
||
644 | if(!mh->to_decode) return MPG123_ERR; |
||
1905 | serge | 645 | |
3960 | Serge | 646 | if(header != NULL) *header = mh->oldhead; |
647 | if(bodydata != NULL) *bodydata = mh->bsbuf; |
||
648 | if(bodybytes != NULL) *bodybytes = mh->framesize; |
||
649 | |||
650 | return MPG123_OK; |
||
651 | } |
||
652 | |||
1905 | serge | 653 | /* |
654 | Fuzzy frame offset searching (guessing). |
||
655 | When we don't have an accurate position, we may use an inaccurate one. |
||
656 | Possibilities: |
||
657 | - use approximate positions from Xing TOC (not yet parsed) |
||
658 | - guess wildly from mean framesize and offset of first frame / beginning of file. |
||
659 | */ |
||
660 | |||
3960 | Serge | 661 | static off_t frame_fuzzy_find(mpg123_handle *fr, off_t want_frame, off_t* get_frame) |
1905 | serge | 662 | { |
663 | /* Default is to go to the beginning. */ |
||
664 | off_t ret = fr->audio_start; |
||
665 | *get_frame = 0; |
||
666 | |||
667 | /* But we try to find something better. */ |
||
668 | /* Xing VBR TOC works with relative positions, both in terms of audio frames and stream bytes. |
||
669 | Thus, it only works when whe know the length of things. |
||
670 | Oh... I assume the offsets are relative to the _total_ file length. */ |
||
671 | if(fr->xing_toc != NULL && fr->track_frames > 0 && fr->rdat.filelen > 0) |
||
672 | { |
||
673 | /* One could round... */ |
||
674 | int toc_entry = (int) ((double)want_frame*100./fr->track_frames); |
||
675 | /* It is an index in the 100-entry table. */ |
||
676 | if(toc_entry < 0) toc_entry = 0; |
||
677 | if(toc_entry > 99) toc_entry = 99; |
||
678 | |||
679 | /* Now estimate back what frame we get. */ |
||
680 | *get_frame = (off_t) ((double)toc_entry/100. * fr->track_frames); |
||
3960 | Serge | 681 | fr->state_flags &= ~FRAME_ACCURATE; |
1905 | serge | 682 | fr->silent_resync = 1; |
683 | /* Question: Is the TOC for whole file size (with/without ID3) or the "real" audio data only? |
||
684 | ID3v1 info could also matter. */ |
||
685 | ret = (off_t) ((double)fr->xing_toc[toc_entry]/256.* fr->rdat.filelen); |
||
686 | } |
||
687 | else if(fr->mean_framesize > 0) |
||
688 | { /* Just guess with mean framesize (may be exact with CBR files). */ |
||
689 | /* Query filelen here or not? */ |
||
3960 | Serge | 690 | fr->state_flags &= ~FRAME_ACCURATE; /* Fuzzy! */ |
1905 | serge | 691 | fr->silent_resync = 1; |
692 | *get_frame = want_frame; |
||
693 | ret = (off_t) (fr->audio_start+fr->mean_framesize*want_frame); |
||
694 | } |
||
695 | debug5("fuzzy: want %li of %li, get %li at %li B of %li B", |
||
696 | (long)want_frame, (long)fr->track_frames, (long)*get_frame, (long)ret, (long)(fr->rdat.filelen-fr->audio_start)); |
||
697 | return ret; |
||
698 | } |
||
699 | |||
700 | /* |
||
701 | find the best frame in index just before the wanted one, seek to there |
||
702 | then step to just before wanted one with read_frame |
||
703 | do not care tabout the stuff that was in buffer but not played back |
||
704 | everything that left the decoder is counted as played |
||
705 | |||
706 | Decide if you want low latency reaction and accurate timing info or stable long-time playback with buffer! |
||
707 | */ |
||
708 | |||
709 | off_t frame_index_find(mpg123_handle *fr, off_t want_frame, off_t* get_frame) |
||
710 | { |
||
711 | /* default is file start if no index position */ |
||
712 | off_t gopos = 0; |
||
713 | *get_frame = 0; |
||
714 | #ifdef FRAME_INDEX |
||
715 | /* Possibly use VBRI index, too? I'd need an example for this... */ |
||
716 | if(fr->index.fill) |
||
717 | { |
||
718 | /* find in index */ |
||
719 | size_t fi; |
||
720 | /* at index fi there is frame step*fi... */ |
||
721 | fi = want_frame/fr->index.step; |
||
722 | if(fi >= fr->index.fill) /* If we are beyond the end of frame index...*/ |
||
723 | { |
||
724 | /* When fuzzy seek is allowed, we have some limited tolerance for the frames we want to read rather then jump over. */ |
||
725 | if(fr->p.flags & MPG123_FUZZY && want_frame - (fr->index.fill-1)*fr->index.step > 10) |
||
726 | { |
||
727 | gopos = frame_fuzzy_find(fr, want_frame, get_frame); |
||
728 | if(gopos > fr->audio_start) return gopos; /* Only in that case, we have a useful guess. */ |
||
729 | /* Else... just continue, fuzzyness didn't help. */ |
||
730 | } |
||
731 | /* Use the last available position, slowly advancing from that one. */ |
||
732 | fi = fr->index.fill - 1; |
||
733 | } |
||
734 | /* We have index position, that yields frame and byte offsets. */ |
||
735 | *get_frame = fi*fr->index.step; |
||
736 | gopos = fr->index.data[fi]; |
||
3960 | Serge | 737 | fr->state_flags |= FRAME_ACCURATE; /* When using the frame index, we are accurate. */ |
1905 | serge | 738 | } |
739 | else |
||
740 | { |
||
741 | #endif |
||
742 | if(fr->p.flags & MPG123_FUZZY) |
||
743 | return frame_fuzzy_find(fr, want_frame, get_frame); |
||
744 | /* A bit hackish here... but we need to be fresh when looking for the first header again. */ |
||
745 | fr->firsthead = 0; |
||
746 | fr->oldhead = 0; |
||
747 | #ifdef FRAME_INDEX |
||
748 | } |
||
749 | #endif |
||
750 | debug2("index: 0x%lx for frame %li", (unsigned long)gopos, (long) *get_frame); |
||
751 | return gopos; |
||
752 | } |
||
753 | |||
754 | off_t frame_ins2outs(mpg123_handle *fr, off_t ins) |
||
755 | { |
||
756 | off_t outs = 0; |
||
757 | switch(fr->down_sample) |
||
758 | { |
||
759 | case 0: |
||
760 | # ifndef NO_DOWNSAMPLE |
||
761 | case 1: |
||
762 | case 2: |
||
763 | # endif |
||
764 | outs = ins>>fr->down_sample; |
||
765 | break; |
||
766 | # ifndef NO_NTOM |
||
767 | case 3: outs = ntom_ins2outs(fr, ins); break; |
||
768 | # endif |
||
769 | default: error1("Bad down_sample (%i) ... should not be possible!!", fr->down_sample); |
||
770 | } |
||
771 | return outs; |
||
772 | } |
||
773 | |||
774 | off_t frame_outs(mpg123_handle *fr, off_t num) |
||
775 | { |
||
776 | off_t outs = 0; |
||
777 | switch(fr->down_sample) |
||
778 | { |
||
779 | case 0: |
||
780 | # ifndef NO_DOWNSAMPLE |
||
781 | case 1: |
||
782 | case 2: |
||
783 | # endif |
||
784 | outs = (spf(fr)>>fr->down_sample)*num; |
||
785 | break; |
||
786 | #ifndef NO_NTOM |
||
787 | case 3: outs = ntom_frmouts(fr, num); break; |
||
788 | #endif |
||
789 | default: error1("Bad down_sample (%i) ... should not be possible!!", fr->down_sample); |
||
790 | } |
||
791 | return outs; |
||
792 | } |
||
793 | |||
3960 | Serge | 794 | /* Compute the number of output samples we expect from this frame. |
795 | This is either simple spf() or a tad more elaborate for ntom. */ |
||
796 | off_t frame_expect_outsamples(mpg123_handle *fr) |
||
797 | { |
||
798 | off_t outs = 0; |
||
799 | switch(fr->down_sample) |
||
800 | { |
||
801 | case 0: |
||
802 | # ifndef NO_DOWNSAMPLE |
||
803 | case 1: |
||
804 | case 2: |
||
805 | # endif |
||
806 | outs = spf(fr)>>fr->down_sample; |
||
807 | break; |
||
808 | #ifndef NO_NTOM |
||
809 | case 3: outs = ntom_frame_outsamples(fr); break; |
||
810 | #endif |
||
811 | default: error1("Bad down_sample (%i) ... should not be possible!!", fr->down_sample); |
||
812 | } |
||
813 | return outs; |
||
814 | } |
||
815 | |||
1905 | serge | 816 | off_t frame_offset(mpg123_handle *fr, off_t outs) |
817 | { |
||
818 | off_t num = 0; |
||
819 | switch(fr->down_sample) |
||
820 | { |
||
821 | case 0: |
||
822 | # ifndef NO_DOWNSAMPLE |
||
823 | case 1: |
||
824 | case 2: |
||
825 | # endif |
||
826 | num = outs/(spf(fr)>>fr->down_sample); |
||
827 | break; |
||
828 | #ifndef NO_NTOM |
||
829 | case 3: num = ntom_frameoff(fr, outs); break; |
||
830 | #endif |
||
831 | default: error("Bad down_sample ... should not be possible!!"); |
||
832 | } |
||
833 | return num; |
||
834 | } |
||
835 | |||
836 | #ifdef GAPLESS |
||
837 | /* input in _input_ samples */ |
||
3960 | Serge | 838 | void frame_gapless_init(mpg123_handle *fr, off_t framecount, off_t bskip, off_t eskip) |
1905 | serge | 839 | { |
3960 | Serge | 840 | debug3("frame_gaples_init: given %"OFF_P" frames, skip %"OFF_P" and %"OFF_P, (off_p)framecount, (off_p)bskip, (off_p)eskip); |
841 | fr->gapless_frames = framecount; |
||
842 | if(fr->gapless_frames > 0) |
||
843 | { |
||
844 | fr->begin_s = bskip+GAPLESS_DELAY; |
||
845 | fr->end_s = framecount*spf(fr)-eskip+GAPLESS_DELAY; |
||
846 | } |
||
847 | else fr->begin_s = fr->end_s = 0; |
||
1905 | serge | 848 | /* These will get proper values later, from above plus resampling info. */ |
849 | fr->begin_os = 0; |
||
850 | fr->end_os = 0; |
||
3960 | Serge | 851 | fr->fullend_os = 0; |
852 | debug2("frame_gapless_init: from %"OFF_P" to %"OFF_P" samples", (off_p)fr->begin_s, (off_p)fr->end_s); |
||
1905 | serge | 853 | } |
854 | |||
855 | void frame_gapless_realinit(mpg123_handle *fr) |
||
856 | { |
||
857 | fr->begin_os = frame_ins2outs(fr, fr->begin_s); |
||
858 | fr->end_os = frame_ins2outs(fr, fr->end_s); |
||
3960 | Serge | 859 | fr->fullend_os = frame_ins2outs(fr, fr->gapless_frames*spf(fr)); |
860 | debug2("frame_gapless_realinit: from %"OFF_P" to %"OFF_P" samples", (off_p)fr->begin_os, (off_p)fr->end_os); |
||
1905 | serge | 861 | } |
862 | |||
3960 | Serge | 863 | /* At least note when there is trouble... */ |
1905 | serge | 864 | void frame_gapless_update(mpg123_handle *fr, off_t total_samples) |
865 | { |
||
3960 | Serge | 866 | off_t gapless_samples = fr->gapless_frames*spf(fr); |
867 | debug2("gapless update with new sample count %"OFF_P" as opposed to known %"OFF_P, total_samples, gapless_samples); |
||
868 | if(NOQUIET && total_samples != gapless_samples) |
||
869 | fprintf(stderr, "\nWarning: Real sample count differs from given gapless sample count. Frankenstein stream?\n"); |
||
870 | |||
871 | if(gapless_samples > total_samples) |
||
1905 | serge | 872 | { |
3960 | Serge | 873 | if(NOQUIET) error2("End sample count smaller than gapless end! (%"OFF_P" < %"OFF_P"). Disabling gapless mode from now on.", (off_p)total_samples, (off_p)fr->end_s); |
874 | /* This invalidates the current position... but what should I do? */ |
||
875 | frame_gapless_init(fr, -1, 0, 0); |
||
1905 | serge | 876 | frame_gapless_realinit(fr); |
3960 | Serge | 877 | fr->lastframe = -1; |
878 | fr->lastoff = 0; |
||
1905 | serge | 879 | } |
880 | } |
||
881 | |||
882 | #endif |
||
883 | |||
884 | /* Compute the needed frame to ignore from, for getting accurate/consistent output for intended firstframe. */ |
||
885 | static off_t ignoreframe(mpg123_handle *fr) |
||
886 | { |
||
887 | off_t preshift = fr->p.preframes; |
||
888 | /* Layer 3 _really_ needs at least one frame before. */ |
||
889 | if(fr->lay==3 && preshift < 1) preshift = 1; |
||
890 | /* Layer 1 & 2 reall do not need more than 2. */ |
||
891 | if(fr->lay!=3 && preshift > 2) preshift = 2; |
||
892 | |||
893 | return fr->firstframe - preshift; |
||
894 | } |
||
895 | |||
896 | /* The frame seek... This is not simply the seek to fe*spf(fr) samples in output because we think of _input_ frames here. |
||
897 | Seek to frame offset 1 may be just seek to 200 samples offset in output since the beginning of first frame is delay/padding. |
||
898 | Hm, is that right? OK for the padding stuff, but actually, should the decoder delay be better totally hidden or not? |
||
899 | With gapless, even the whole frame position could be advanced further than requested (since Homey don't play dat). */ |
||
900 | void frame_set_frameseek(mpg123_handle *fr, off_t fe) |
||
901 | { |
||
902 | fr->firstframe = fe; |
||
903 | #ifdef GAPLESS |
||
3960 | Serge | 904 | if(fr->p.flags & MPG123_GAPLESS && fr->gapless_frames > 0) |
1905 | serge | 905 | { |
906 | /* Take care of the beginning... */ |
||
907 | off_t beg_f = frame_offset(fr, fr->begin_os); |
||
908 | if(fe <= beg_f) |
||
909 | { |
||
910 | fr->firstframe = beg_f; |
||
911 | fr->firstoff = fr->begin_os - frame_outs(fr, beg_f); |
||
912 | } |
||
913 | else fr->firstoff = 0; |
||
914 | /* The end is set once for a track at least, on the frame_set_frameseek called in get_next_frame() */ |
||
915 | if(fr->end_os > 0) |
||
916 | { |
||
917 | fr->lastframe = frame_offset(fr,fr->end_os); |
||
918 | fr->lastoff = fr->end_os - frame_outs(fr, fr->lastframe); |
||
3960 | Serge | 919 | } else {fr->lastframe = -1; fr->lastoff = 0; } |
1905 | serge | 920 | } else { fr->firstoff = fr->lastoff = 0; fr->lastframe = -1; } |
921 | #endif |
||
922 | fr->ignoreframe = ignoreframe(fr); |
||
923 | #ifdef GAPLESS |
||
924 | debug5("frame_set_frameseek: begin at %li frames and %li samples, end at %li and %li; ignore from %li", |
||
925 | (long) fr->firstframe, (long) fr->firstoff, |
||
926 | (long) fr->lastframe, (long) fr->lastoff, (long) fr->ignoreframe); |
||
927 | #else |
||
928 | debug3("frame_set_frameseek: begin at %li frames, end at %li; ignore from %li", |
||
929 | (long) fr->firstframe, (long) fr->lastframe, (long) fr->ignoreframe); |
||
930 | #endif |
||
931 | } |
||
932 | |||
933 | void frame_skip(mpg123_handle *fr) |
||
934 | { |
||
935 | #ifndef NO_LAYER3 |
||
936 | if(fr->lay == 3) set_pointer(fr, 512); |
||
937 | #endif |
||
938 | } |
||
939 | |||
940 | /* Sample accurate seek prepare for decoder. */ |
||
941 | /* This gets unadjusted output samples and takes resampling into account */ |
||
942 | void frame_set_seek(mpg123_handle *fr, off_t sp) |
||
943 | { |
||
944 | fr->firstframe = frame_offset(fr, sp); |
||
3960 | Serge | 945 | debug1("frame_set_seek: from %"OFF_P, fr->num); |
1905 | serge | 946 | #ifndef NO_NTOM |
947 | if(fr->down_sample == 3) ntom_set_ntom(fr, fr->firstframe); |
||
948 | #endif |
||
949 | fr->ignoreframe = ignoreframe(fr); |
||
950 | #ifdef GAPLESS /* The sample offset is used for non-gapless mode, too! */ |
||
951 | fr->firstoff = sp - frame_outs(fr, fr->firstframe); |
||
952 | debug5("frame_set_seek: begin at %li frames and %li samples, end at %li and %li; ignore from %li", |
||
953 | (long) fr->firstframe, (long) fr->firstoff, |
||
954 | (long) fr->lastframe, (long) fr->lastoff, (long) fr->ignoreframe); |
||
955 | #else |
||
956 | debug3("frame_set_seek: begin at %li frames, end at %li; ignore from %li", |
||
957 | (long) fr->firstframe, (long) fr->lastframe, (long) fr->ignoreframe); |
||
958 | #endif |
||
959 | } |
||
960 | |||
961 | int attribute_align_arg mpg123_volume_change(mpg123_handle *mh, double change) |
||
962 | { |
||
963 | if(mh == NULL) return MPG123_ERR; |
||
964 | return mpg123_volume(mh, change + (double) mh->p.outscale); |
||
965 | } |
||
966 | |||
967 | int attribute_align_arg mpg123_volume(mpg123_handle *mh, double vol) |
||
968 | { |
||
969 | if(mh == NULL) return MPG123_ERR; |
||
970 | |||
971 | if(vol >= 0) mh->p.outscale = vol; |
||
972 | else mh->p.outscale = 0.; |
||
973 | |||
974 | do_rva(mh); |
||
975 | return MPG123_OK; |
||
976 | } |
||
977 | |||
978 | static int get_rva(mpg123_handle *fr, double *peak, double *gain) |
||
979 | { |
||
980 | double p = -1; |
||
981 | double g = 0; |
||
982 | int ret = 0; |
||
983 | if(fr->p.rva) |
||
984 | { |
||
985 | int rt = 0; |
||
986 | /* Should one assume a zero RVA as no RVA? */ |
||
987 | if(fr->p.rva == 2 && fr->rva.level[1] != -1) rt = 1; |
||
988 | if(fr->rva.level[rt] != -1) |
||
989 | { |
||
990 | p = fr->rva.peak[rt]; |
||
991 | g = fr->rva.gain[rt]; |
||
992 | ret = 1; /* Success. */ |
||
993 | } |
||
994 | } |
||
995 | if(peak != NULL) *peak = p; |
||
996 | if(gain != NULL) *gain = g; |
||
997 | return ret; |
||
998 | } |
||
999 | |||
1000 | /* adjust the volume, taking both fr->outscale and rva values into account */ |
||
1001 | void do_rva(mpg123_handle *fr) |
||
1002 | { |
||
1003 | double peak = 0; |
||
1004 | double gain = 0; |
||
1005 | double newscale; |
||
1006 | double rvafact = 1; |
||
1007 | if(get_rva(fr, &peak, &gain)) |
||
1008 | { |
||
1009 | if(NOQUIET && fr->p.verbose > 1) fprintf(stderr, "Note: doing RVA with gain %f\n", gain); |
||
1010 | rvafact = pow(10,gain/20); |
||
1011 | } |
||
1012 | |||
1013 | newscale = fr->p.outscale*rvafact; |
||
1014 | |||
1015 | /* if peak is unknown (== 0) this check won't hurt */ |
||
1016 | if((peak*newscale) > 1.0) |
||
1017 | { |
||
1018 | newscale = 1.0/peak; |
||
1019 | warning2("limiting scale value to %f to prevent clipping with indicated peak factor of %f", newscale, peak); |
||
1020 | } |
||
1021 | /* first rva setting is forced with fr->lastscale < 0 */ |
||
1022 | if(newscale != fr->lastscale || fr->decoder_change) |
||
1023 | { |
||
1024 | debug3("changing scale value from %f to %f (peak estimated to %f)", fr->lastscale != -1 ? fr->lastscale : fr->p.outscale, newscale, (double) (newscale*peak)); |
||
1025 | fr->lastscale = newscale; |
||
1026 | /* It may be too early, actually. */ |
||
1027 | if(fr->make_decode_tables != NULL) fr->make_decode_tables(fr); /* the actual work */ |
||
1028 | } |
||
1029 | } |
||
1030 | |||
1031 | |||
1032 | int attribute_align_arg mpg123_getvolume(mpg123_handle *mh, double *base, double *really, double *rva_db) |
||
1033 | { |
||
1034 | if(mh == NULL) return MPG123_ERR; |
||
1035 | if(base) *base = mh->p.outscale; |
||
1036 | if(really) *really = mh->lastscale; |
||
1037 | get_rva(mh, NULL, rva_db); |
||
1038 | return MPG123_OK; |
||
1039 | } |
||
1040 | |||
3960 | Serge | 1041 | off_t attribute_align_arg mpg123_framepos(mpg123_handle *mh) |
1042 | { |
||
1043 | if(mh == NULL) return MPG123_ERR; |
||
1044 | |||
1045 | return mh->input_offset; |
||
1046 | }>=>>>>100;>>4;>4;>>>> |