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