Coverage Report

Created: 2026-08-31 08:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
1.03M
#define NTOM_MUL (32768)
18
19
1.23M
#define aligned_pointer(p, type, alignment) align_the_pointer(p, alignment)
20
static void *align_the_pointer(void *base, unsigned int alignment)
21
1.23M
{
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.23M
  uintptr_t baseval = (uintptr_t)(char*)base;
28
1.23M
  uintptr_t aoff = baseval % alignment;
29
30
1.23M
  debug3("align_the_pointer: pointer %p is off by %u from %u",
31
1.23M
         base, (unsigned int)aoff, alignment);
32
33
1.23M
  if(aoff) return (char*)base+alignment-aoff;
34
917k
  else     return base;
35
1.23M
}
36
37
static void frame_default_pars(mpg123_pars *mp)
38
346k
{
39
346k
  mp->outscale = 1.0;
40
346k
  mp->flags = 0;
41
346k
#ifdef GAPLESS
42
346k
  mp->flags |= MPG123_GAPLESS;
43
346k
#endif
44
346k
  mp->flags |= MPG123_AUTO_RESAMPLE|MPG123_FLOAT_FALLBACK;
45
346k
#ifndef NO_NTOM
46
346k
  mp->force_rate = 0;
47
346k
#endif
48
346k
  mp->down_sample = 0;
49
346k
  mp->rva = 0;
50
346k
  mp->halfspeed = 0;
51
346k
  mp->doublespeed = 0;
52
346k
  mp->verbose = 0;
53
346k
#ifndef NO_ICY
54
346k
  mp->icy_interval = 0;
55
346k
#endif
56
346k
  mp->timeout = 0;
57
346k
  mp->resync_limit = 1024;
58
346k
#ifdef FRAME_INDEX
59
346k
  mp->index_size = INDEX_SIZE;
60
346k
#endif
61
346k
  mp->preframes = 4; /* That's good  for layer 3 ISO compliance bitstream. */
62
346k
  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
346k
#ifndef NO_FEEDER
65
346k
  mp->feedpool = 5; 
66
346k
  mp->feedbuffer = 4096;
67
346k
#endif
68
346k
  mp->freeformat_framesize = -1;
69
346k
}
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
346k
{
78
346k
  fr->own_buffer = TRUE;
79
346k
  fr->buffer.data = NULL;
80
346k
  fr->buffer.rdata = NULL;
81
346k
  fr->buffer.fill = 0;
82
346k
  fr->buffer.size = 0;
83
346k
  fr->rawbuffs = NULL;
84
346k
  fr->rawbuffss = 0;
85
346k
  fr->rawdecwin = NULL;
86
346k
  fr->rawdecwins = 0;
87
#ifdef REAL_IS_FIXED
88
  fr->gainpow2 = NULL; // At least crash early if I get it wrong.
89
#endif
90
346k
#ifndef NO_8BIT
91
346k
  fr->conv16to8_buf = NULL;
92
346k
#endif
93
346k
#ifdef OPT_DITHER
94
346k
  fr->dithernoise = NULL;
95
346k
#endif
96
346k
  fr->layerscratch = NULL;
97
346k
  fr->xing_toc = NULL;
98
346k
#ifdef OPT_CPU_FLAGS
99
346k
  wrap_getcpuflags(&(fr->cpu_flags));
100
346k
#endif
101
346k
  fr->cpu_opts.type = INT123_defdec();
102
346k
  fr->cpu_opts.class = INT123_decclass(fr->cpu_opts.type);
103
346k
#ifndef NO_NTOM
104
  /* these two look unnecessary, check guarantee for INT123_synth_ntom_set_step (in control_generic, even)! */
105
346k
  fr->INT123_ntom_val[0] = NTOM_MUL>>1;
106
346k
  fr->INT123_ntom_val[1] = NTOM_MUL>>1;
107
346k
  fr->ntom_step = NTOM_MUL;
108
346k
#endif
109
  /* unnecessary: fr->buffer.size = fr->buffer.fill = 0; */
110
346k
  mpg123_reset_eq(fr);
111
346k
  INT123_init_icy(&fr->icy);
112
346k
  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
346k
  INT123_invalidate_format(&fr->af);
117
346k
  fr->rdat.iohandle = NULL;
118
346k
  fr->rdat.r_read64 = NULL;
119
346k
  fr->rdat.r_lseek64 = NULL;
120
346k
  fr->rdat.cleanup_handle = NULL;
121
346k
  fr->wrapperdata = NULL;
122
346k
  fr->decoder_change = 1;
123
346k
  fr->err = MPG123_OK;
124
346k
  if(mp == NULL) frame_default_pars(&fr->p);
125
0
  else memcpy(&fr->p, mp, sizeof(struct mpg123_pars_struct));
126
127
346k
#ifndef NO_FEEDER
128
346k
  INT123_bc_prepare(&fr->rdat.buffer, fr->p.feedpool, fr->p.feedbuffer);
129
346k
#endif
130
131
346k
  fr->down_sample = 0; /* Initialize to silence harmless errors when debugging. */
132
346k
  fr->id3v2_raw = NULL;
133
346k
  frame_fixed_reset(fr); /* Reset only the fixed data, dynamic buffers are not there yet! */
134
346k
  fr->synth = NULL;
135
346k
  fr->synth_mono = NULL;
136
346k
  fr->INT123_make_decode_tables = NULL;
137
346k
#ifdef FRAME_INDEX
138
346k
  INT123_fi_init(&fr->index);
139
346k
  INT123_frame_index_setup(fr); /* Apply the size setting. */
140
346k
#endif
141
346k
#ifndef NO_MOREINFO
142
346k
  fr->pinfo = NULL;
143
346k
#endif
144
346k
}
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
346k
{
178
346k
  if(mh == NULL) return MPG123_BAD_HANDLE;
179
346k
#ifndef NO_EQUALIZER
180
346k
  int i;
181
346k
  mh->have_eq_settings = 0;
182
11.4M
  for(i=0; i < 32; ++i) mh->equalizer[0][i] = mh->equalizer[1][i] = DOUBLE_TO_REAL(1.0);
183
346k
#endif
184
346k
  return MPG123_OK;
185
346k
}
186
187
int INT123_frame_outbuffer(mpg123_handle *fr)
188
282k
{
189
282k
  size_t size = fr->outblock;
190
282k
  if(!fr->own_buffer)
191
280k
  {
192
280k
    if(fr->buffer.size < size)
193
13.5k
    {
194
13.5k
      fr->err = MPG123_BAD_BUFFER;
195
13.5k
      if(NOQUIET)
196
13.5k
        merror("have external buffer of size %zu, need %zu", fr->buffer.size, size);
197
13.5k
      return MPG123_ERR;
198
13.5k
    }
199
280k
  }
200
201
268k
  debug1("need frame buffer of %zu", size);
202
268k
  if(fr->buffer.rdata != NULL && fr->buffer.size != size)
203
654
  {
204
654
    free(fr->buffer.rdata);
205
654
    fr->buffer.rdata = NULL;
206
654
  }
207
268k
  fr->buffer.size = size;
208
268k
  fr->buffer.data = NULL;
209
  /* be generous: use 16 byte alignment */
210
268k
  if(fr->buffer.rdata == NULL) fr->buffer.rdata = (unsigned char*) malloc(fr->buffer.size+15);
211
268k
  if(fr->buffer.rdata == NULL)
212
0
  {
213
0
    fr->err = MPG123_OUT_OF_MEM;
214
0
    return MPG123_ERR;
215
0
  }
216
268k
  fr->buffer.data = aligned_pointer(fr->buffer.rdata, unsigned char*, 16);
217
268k
  fr->own_buffer = TRUE;
218
268k
  fr->buffer.fill = 0;
219
268k
  return MPG123_OK;
220
268k
}
221
222
int attribute_align_arg mpg123_replace_buffer(mpg123_handle *mh, void *data, size_t size)
223
7.21M
{
224
7.21M
  debug2("replace buffer with %p size %zu", data, size);
225
7.21M
  if(mh == NULL) return MPG123_BAD_HANDLE;
226
  /* Will accept any size, the error comes later... */
227
7.21M
  if(data == NULL)
228
0
  {
229
0
    mh->err = MPG123_BAD_BUFFER;
230
0
    return MPG123_ERR;
231
0
  }
232
7.21M
  if(mh->buffer.rdata != NULL) free(mh->buffer.rdata);
233
7.21M
  mh->own_buffer = FALSE;
234
7.21M
  mh->buffer.rdata = NULL;
235
7.21M
  mh->buffer.data = data;
236
7.21M
  mh->buffer.size = size;
237
7.21M
  mh->buffer.fill = 0;
238
7.21M
  return MPG123_OK;
239
7.21M
}
240
241
#ifdef FRAME_INDEX
242
int INT123_frame_index_setup(mpg123_handle *fr)
243
346k
{
244
346k
  int ret = MPG123_ERR;
245
346k
  if(fr->p.index_size >= 0)
246
346k
  { /* Simple fixed index. */
247
346k
    fr->index.grow_size = 0;
248
346k
    ret = INT123_fi_resize(&fr->index, (size_t)fr->p.index_size);
249
346k
  }
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
346k
  debug2("set up frame index of size %lu (ret=%i)", (unsigned long)fr->index.size, ret);
259
346k
  if(ret && NOQUIET)
260
346k
    error("frame index setup (initial resize) failed");
261
346k
  return ret;
262
346k
}
263
#endif
264
265
static void frame_decode_buffers_reset(mpg123_handle *fr)
266
1.32M
{
267
1.32M
  if(fr->rawbuffs) /* memset(NULL, 0, 0) not desired */
268
646k
    memset(fr->rawbuffs, 0, fr->rawbuffss);
269
1.32M
}
270
271
int INT123_frame_buffers(mpg123_handle *fr)
272
282k
{
273
282k
  int buffssize = 0;
274
282k
  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
282k
  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
282k
  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
282k
  if(2*2*0x110*sizeof(real) > buffssize)
298
282k
  buffssize = 2*2*0x110*sizeof(real);
299
282k
  buffssize += 15; /* For 16-byte alignment (SSE likes that). */
300
301
282k
  if(fr->rawbuffs != NULL && fr->rawbuffss != buffssize)
302
0
  {
303
0
    free(fr->rawbuffs);
304
0
    fr->rawbuffs = NULL;
305
0
  }
306
307
282k
  if(fr->rawbuffs == NULL) fr->rawbuffs = (unsigned char*) malloc(buffssize);
308
282k
  if(fr->rawbuffs == NULL) return -1;
309
282k
  fr->rawbuffss = buffssize;
310
282k
  fr->short_buffs[0][0] = aligned_pointer(fr->rawbuffs,short,16);
311
282k
  fr->short_buffs[0][1] = fr->short_buffs[0][0] + 0x110;
312
282k
  fr->short_buffs[1][0] = fr->short_buffs[0][1] + 0x110;
313
282k
  fr->short_buffs[1][1] = fr->short_buffs[1][0] + 0x110;
314
282k
  fr->real_buffs[0][0] = aligned_pointer(fr->rawbuffs,real,16);
315
282k
  fr->real_buffs[0][1] = fr->real_buffs[0][0] + 0x110;
316
282k
  fr->real_buffs[1][0] = fr->real_buffs[0][1] + 0x110;
317
282k
  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
282k
  {
339
282k
    int decwin_size = (512+32)*sizeof(real);
340
282k
#ifdef OPT_MMXORSSE
341
282k
#ifdef OPT_MULTI
342
282k
    if(fr->cpu_opts.class == mmxsse)
343
223k
    {
344
223k
#endif
345
      /* decwin_mmx will share, decwins will be appended ... sizeof(float)==4 */
346
223k
      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
223k
      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
223k
#ifdef OPT_MULTI
353
223k
    }
354
282k
#endif
355
282k
#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
282k
    if(fr->rawdecwin != NULL && fr->rawdecwins != decwin_size)
363
42.4k
    {
364
42.4k
      free(fr->rawdecwin);
365
42.4k
      fr->rawdecwin = NULL;
366
42.4k
    }
367
368
282k
    if(fr->rawdecwin == NULL)
369
224k
    fr->rawdecwin = (unsigned char*) malloc(decwin_size);
370
371
282k
    if(fr->rawdecwin == NULL) return -1;
372
373
282k
    fr->rawdecwins = decwin_size;
374
282k
    fr->decwin = (real*) fr->rawdecwin;
375
282k
#ifdef OPT_MMXORSSE
376
282k
#ifdef OPT_MULTI
377
282k
    if(fr->cpu_opts.class == mmxsse)
378
223k
    {
379
223k
#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
223k
      fr->decwin = aligned_pointer(fr->rawdecwin,real,64);
383
223k
      debug1("aligned decwin: %p", (void*)fr->decwin);
384
223k
      fr->decwin_mmx = (float*)fr->decwin;
385
223k
      fr->decwins = fr->decwin_mmx+512+32;
386
223k
#ifdef OPT_MULTI
387
223k
    }
388
282k
    else debug("no decwins/decwin_mmx for that class");
389
282k
#endif
390
282k
#endif
391
282k
  }
392
393
  /* Layer scratch buffers are of compile-time fixed size, so allocate only once. */
394
282k
  if(fr->layerscratch == NULL)
395
182k
  {
396
    /* Allocate specific layer1/2/3 buffers, so that we know they'll work for SSE. */
397
182k
    size_t scratchsize = 0;
398
182k
    real *scratcher;
399
182k
#ifndef NO_LAYER1
400
182k
    scratchsize += sizeof(real) * 2 * SBLIMIT;
401
182k
#endif
402
182k
#ifndef NO_LAYER2
403
182k
    scratchsize += sizeof(real) * 2 * 4 * SBLIMIT;
404
182k
#endif
405
182k
#ifndef NO_LAYER3
406
182k
    scratchsize += sizeof(real) * 2 * SBLIMIT * SSLIMIT; /* hybrid_in */
407
182k
    scratchsize += sizeof(real) * 2 * SSLIMIT * SBLIMIT; /* hybrid_out */
408
182k
#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
182k
    fr->layerscratch = malloc(scratchsize+63);
414
182k
    if(fr->layerscratch == NULL) return -1;
415
416
    /* Get aligned part of the memory, then divide it up. */
417
182k
    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
182k
#ifndef NO_LAYER1
421
182k
    fr->layer1.fraction = (real(*)[SBLIMIT])scratcher;
422
182k
    scratcher += 2 * SBLIMIT;
423
182k
#endif
424
182k
#ifndef NO_LAYER2
425
182k
    fr->layer2.fraction = (real(*)[4][SBLIMIT])scratcher;
426
182k
    scratcher += 2 * 4 * SBLIMIT;
427
182k
#endif
428
182k
#ifndef NO_LAYER3
429
182k
    fr->layer3.hybrid_in = (real(*)[SBLIMIT][SSLIMIT])scratcher;
430
182k
    scratcher += 2 * SBLIMIT * SSLIMIT;
431
182k
    fr->layer3.hybrid_out = (real(*)[SSLIMIT][SBLIMIT])scratcher;
432
182k
    scratcher += 2 * SSLIMIT * SBLIMIT;
433
182k
#endif
434
    /* Note: These buffers don't need resetting here. */
435
182k
  }
436
437
  /* Only reset the buffers we created just now. */
438
282k
  frame_decode_buffers_reset(fr);
439
440
282k
  debug1("frame %p buffer done", (void*)fr);
441
282k
  return 0;
442
282k
}
443
444
int INT123_frame_buffers_reset(mpg123_handle *fr)
445
1.03M
{
446
1.03M
  fr->buffer.fill = 0; /* hm, reset buffer fill... did we do a flush? */
447
1.03M
  fr->bsnum = 0;
448
  /* Wondering: could it be actually _wanted_ to retain buffer contents over different files? (special gapless / cut stuff) */
449
1.03M
  fr->bsbuf = fr->bsspace[1];
450
1.03M
  fr->bsbufold = fr->bsbuf;
451
1.03M
  fr->bitreservoir = 0;
452
1.03M
  frame_decode_buffers_reset(fr);
453
1.03M
  memset(fr->bsspace, 0, 2*(MAXFRAMESIZE+512));
454
1.03M
  memset(fr->ssave, 0, 34);
455
1.03M
  fr->hybrid_blc[0] = fr->hybrid_blc[1] = 0;
456
1.03M
  memset(fr->hybrid_block, 0, sizeof(real)*2*2*SBLIMIT*SSLIMIT);
457
1.03M
  return 0;
458
1.03M
}
459
460
static void frame_icy_reset(mpg123_handle* fr)
461
1.38M
{
462
1.38M
#ifndef NO_ICY
463
1.38M
  if(fr->icy.data != NULL) free(fr->icy.data);
464
1.38M
  fr->icy.data = NULL;
465
1.38M
  fr->icy.interval = 0;
466
1.38M
  fr->icy.next = 0;
467
1.38M
#endif
468
1.38M
}
469
470
static void frame_free_toc(mpg123_handle *fr)
471
1.38M
{
472
1.38M
  if(fr->xing_toc != NULL){ free(fr->xing_toc); fr->xing_toc = NULL; }
473
1.38M
}
474
475
/* Just copy the Xing TOC over... */
476
int INT123_frame_fill_toc(mpg123_handle *fr, unsigned char* in)
477
2.40k
{
478
2.40k
  if(fr->xing_toc == NULL) fr->xing_toc = malloc(100);
479
2.40k
  if(fr->xing_toc != NULL)
480
2.40k
  {
481
2.40k
    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.40k
    return TRUE;
491
2.40k
  }
492
0
  return FALSE;
493
2.40k
}
494
495
/* Prepare the handle for a new track.
496
   Reset variables, buffers... */
497
int INT123_frame_reset(mpg123_handle* fr)
498
1.03M
{
499
1.03M
  INT123_frame_buffers_reset(fr);
500
1.03M
  frame_fixed_reset(fr);
501
1.03M
  frame_free_toc(fr);
502
1.03M
#ifdef FRAME_INDEX
503
1.03M
  INT123_fi_reset(&fr->index);
504
1.03M
#endif
505
506
1.03M
  return 0;
507
1.03M
}
508
509
/* Reset everythign except dynamic memory. */
510
static void frame_fixed_reset(mpg123_handle *fr)
511
1.38M
{
512
1.38M
  frame_icy_reset(fr);
513
1.38M
  INT123_open_bad(fr);
514
1.38M
  memset(&(fr->hdr), 0, sizeof(fr->hdr));
515
1.38M
  fr->to_decode = FALSE;
516
1.38M
  fr->to_ignore = FALSE;
517
1.38M
  fr->metaflags = 0;
518
1.38M
  fr->outblock = 0; /* This will be set before decoding! */
519
1.38M
  fr->num = -1;
520
1.38M
  fr->input_offset = -1;
521
1.38M
  fr->playnum = -1;
522
1.38M
  fr->state_flags = FRAME_ACCURATE;
523
1.38M
  fr->silent_resync = 0;
524
1.38M
  fr->audio_start = 0;
525
1.38M
  fr->clip = 0;
526
1.38M
  fr->oldhead = 0;
527
1.38M
  fr->firsthead = 0;
528
1.38M
  fr->vbr = MPG123_CBR;
529
1.38M
  fr->abr_rate = 0;
530
1.38M
  fr->track_frames = 0;
531
1.38M
  fr->track_samples = -1;
532
1.38M
  fr->mean_frames = 0;
533
1.38M
  fr->mean_framesize = 0;
534
1.38M
  fr->lastscale = -1;
535
1.38M
  fr->rva.level[0] = -1;
536
1.38M
  fr->rva.level[1] = -1;
537
1.38M
  fr->rva.gain[0] = 0;
538
1.38M
  fr->rva.gain[1] = 0;
539
1.38M
  fr->rva.peak[0] = 0;
540
1.38M
  fr->rva.peak[1] = 0;
541
1.38M
  fr->fsizeold = 0;
542
1.38M
  fr->firstframe = 0;
543
1.38M
  fr->ignoreframe = fr->firstframe-fr->p.preframes;
544
1.38M
  fr->header_change = 0;
545
1.38M
  fr->lastframe = -1;
546
1.38M
  fr->fresh = 1;
547
1.38M
  fr->new_format = 0;
548
1.38M
#ifdef GAPLESS
549
1.38M
  INT123_frame_gapless_init(fr,-1,0,0);
550
1.38M
  fr->lastoff = 0;
551
1.38M
  fr->firstoff = 0;
552
1.38M
#endif
553
#ifdef OPT_I486
554
  fr->i486bo[0] = fr->i486bo[1] = FIR_SIZE-1;
555
#endif
556
1.38M
  fr->bo = 1; /* the usual bo */
557
1.38M
#ifdef OPT_DITHER
558
1.38M
  fr->ditherindex = 0;
559
1.38M
#endif
560
1.38M
  INT123_reset_id3(fr);
561
1.38M
  INT123_reset_icy(&fr->icy);
562
  /* ICY stuff should go into icy.c, eh? */
563
1.38M
#ifndef NO_ICY
564
1.38M
  fr->icy.interval = 0;
565
1.38M
  fr->icy.next = 0;
566
1.38M
#endif
567
1.38M
  fr->halfphase = 0; /* here or indeed only on first-time init? */
568
1.38M
  fr->hdr.freeformat_framesize = fr->p.freeformat_framesize;
569
1.38M
  fr->enc_delay = -1;
570
1.38M
  fr->enc_padding = -1;
571
1.38M
  memset(fr->id3buf, 0, sizeof(fr->id3buf));
572
1.38M
  if(fr->id3v2_raw)
573
0
    free(fr->id3v2_raw);
574
1.38M
  fr->id3v2_raw = NULL;
575
1.38M
  fr->id3v2_size = 0;
576
1.38M
}
577
578
static void frame_free_buffers(mpg123_handle *fr)
579
346k
{
580
346k
  if(fr->rawbuffs != NULL) free(fr->rawbuffs);
581
346k
  fr->rawbuffs = NULL;
582
346k
  fr->rawbuffss = 0;
583
346k
  if(fr->rawdecwin != NULL) free(fr->rawdecwin);
584
346k
  fr->rawdecwin = NULL;
585
346k
  fr->rawdecwins = 0;
586
346k
#ifndef NO_8BIT
587
346k
  if(fr->conv16to8_buf != NULL) free(fr->conv16to8_buf);
588
346k
  fr->conv16to8_buf = NULL;
589
346k
#endif
590
346k
  if(fr->layerscratch != NULL) free(fr->layerscratch);
591
346k
}
592
593
void INT123_frame_exit(mpg123_handle *fr)
594
346k
{
595
346k
  if(fr->buffer.rdata != NULL)
596
6.08k
  {
597
6.08k
    debug1("freeing buffer at %p", (void*)fr->buffer.rdata);
598
6.08k
    free(fr->buffer.rdata);
599
6.08k
  }
600
346k
  fr->buffer.rdata = NULL;
601
346k
  frame_free_buffers(fr);
602
346k
  frame_free_toc(fr);
603
346k
#ifdef FRAME_INDEX
604
346k
  INT123_fi_exit(&fr->index);
605
346k
#endif
606
346k
#ifdef OPT_DITHER
607
346k
  if(fr->dithernoise != NULL)
608
0
  {
609
0
    free(fr->dithernoise);
610
0
    fr->dithernoise = NULL;
611
0
  }
612
346k
#endif
613
346k
  INT123_exit_id3(fr);
614
346k
  INT123_clear_icy(&fr->icy);
615
346k
#ifndef NO_FEEDER
616
346k
  INT123_bc_cleanup(&fr->rdat.buffer);
617
346k
#endif
618
346k
}
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
369k
{ 
749
369k
  int64_t outs = 0;
750
369k
  switch(fr->down_sample)
751
369k
  {
752
342k
    case 0:
753
342k
#   ifndef NO_DOWNSAMPLE
754
346k
    case 1:
755
350k
    case 2:
756
350k
#   endif
757
350k
      outs = ins>>fr->down_sample;
758
350k
    break;
759
0
#   ifndef NO_NTOM
760
19.4k
    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
369k
      , fr->down_sample );
765
369k
  }
766
369k
  return outs;
767
369k
}
768
769
int64_t INT123_frame_outs(mpg123_handle *fr, int64_t num)
770
10.6k
{
771
10.6k
  int64_t outs = 0;
772
10.6k
  switch(fr->down_sample)
773
10.6k
  {
774
9.40k
    case 0:
775
9.40k
#   ifndef NO_DOWNSAMPLE
776
9.67k
    case 1:
777
10.2k
    case 2:
778
10.2k
#   endif
779
10.2k
      outs = (fr->spf>>fr->down_sample)*num;
780
10.2k
    break;
781
0
#ifndef NO_NTOM
782
462
    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
10.6k
      , fr->down_sample );
787
10.6k
  }
788
10.6k
  return outs;
789
10.6k
}
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.26M
{
795
2.26M
  int64_t outs = 0;
796
2.26M
  switch(fr->down_sample)
797
2.26M
  {
798
2.15M
    case 0:
799
2.15M
#   ifndef NO_DOWNSAMPLE
800
2.15M
    case 1:
801
2.16M
    case 2:
802
2.16M
#   endif
803
2.16M
      outs = fr->spf>>fr->down_sample;
804
2.16M
    break;
805
0
#ifndef NO_NTOM
806
93.7k
    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.26M
      , fr->down_sample );
811
2.26M
  }
812
2.26M
  return outs;
813
2.26M
}
814
815
int64_t INT123_frame_offset(mpg123_handle *fr, int64_t outs)
816
10.6k
{
817
10.6k
  int64_t num = 0;
818
10.6k
  switch(fr->down_sample)
819
10.6k
  {
820
9.40k
    case 0:
821
9.40k
#   ifndef NO_DOWNSAMPLE
822
9.67k
    case 1:
823
10.2k
    case 2:
824
10.2k
#   endif
825
10.2k
      num = outs/(fr->spf>>fr->down_sample);
826
10.2k
    break;
827
0
#ifndef NO_NTOM
828
462
    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
10.6k
  }
833
10.6k
  return num;
834
10.6k
}
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.39M
{
840
1.39M
  debug3("INT123_frame_gapless_init: given %"PRIi64" frames, skip %"PRIi64" and %"PRIi64, framecount, bskip, eskip);
841
1.39M
  fr->gapless_frames = framecount;
842
1.39M
  if(fr->gapless_frames > 0 && bskip >=0 && eskip >= 0)
843
9.83k
  {
844
9.83k
    fr->begin_s = bskip+GAPLESS_DELAY;
845
9.83k
    fr->end_s = framecount*fr->spf-eskip+GAPLESS_DELAY;
846
9.83k
  }
847
1.38M
  else fr->begin_s = fr->end_s = 0;
848
  /* These will get proper values later, from above plus resampling info. */
849
1.39M
  fr->begin_os = 0;
850
1.39M
  fr->end_os = 0;
851
1.39M
  fr->fullend_os = 0;
852
1.39M
  debug2("INT123_frame_gapless_init: from %"PRIi64" to %"PRIi64" samples", fr->begin_s, fr->end_s);
853
1.39M
}
854
855
void INT123_frame_gapless_realinit(mpg123_handle *fr)
856
182k
{
857
182k
  fr->begin_os = INT123_frame_ins2outs(fr, fr->begin_s);
858
182k
  fr->end_os   = INT123_frame_ins2outs(fr, fr->end_s);
859
182k
  if(fr->gapless_frames > 0)
860
5.43k
  fr->fullend_os = INT123_frame_ins2outs(fr, fr->gapless_frames*fr->spf);
861
176k
  else fr->fullend_os = 0;
862
863
182k
  debug4("INT123_frame_gapless_realinit: from %"PRIi64" to %"PRIi64" samples (%"PRIi64", %"PRIi64")"
864
182k
  , fr->begin_os, fr->end_os, fr->fullend_os, fr->gapless_frames);
865
182k
}
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
182k
{
898
182k
  int64_t preshift = fr->p.preframes;
899
  /* Layer 3 _really_ needs at least one frame before. */
900
182k
  if(fr->hdr.lay==3 && preshift < 1) preshift = 1;
901
  /* Layer 1 & 2 reall do not need more than 2. */
902
182k
  if(fr->hdr.lay!=3 && preshift > 2) preshift = 2;
903
904
182k
  return fr->firstframe - preshift;
905
182k
}
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
182k
{
913
182k
  fr->firstframe = fe;
914
182k
#ifdef GAPLESS
915
182k
  if(fr->p.flags & MPG123_GAPLESS && fr->gapless_frames > 0)
916
5.43k
  {
917
    /* Take care of the beginning... */
918
5.43k
    int64_t beg_f = INT123_frame_offset(fr, fr->begin_os);
919
5.43k
    if(fe <= beg_f)
920
5.43k
    {
921
5.43k
      fr->firstframe = beg_f;
922
5.43k
      fr->firstoff   = fr->begin_os - INT123_frame_outs(fr, beg_f);
923
5.43k
    }
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
5.43k
    if(fr->end_os > 0)
927
5.24k
    {
928
5.24k
      fr->lastframe  = INT123_frame_offset(fr,fr->end_os);
929
5.24k
      fr->lastoff    = fr->end_os - INT123_frame_outs(fr, fr->lastframe);
930
5.24k
    } else {fr->lastframe = -1; fr->lastoff = 0; }
931
176k
  } else { fr->firstoff = fr->lastoff = 0; fr->lastframe = -1; }
932
182k
#endif
933
182k
  fr->ignoreframe = ignoreframe(fr);
934
182k
#ifdef GAPLESS
935
182k
  debug5("INT123_frame_set_frameseek: begin at %" PRIi64 " frames and %" PRIi64
936
182k
    " samples, end at %" PRIi64 " and %" PRIi64 "; ignore from %" PRIi64,
937
182k
    fr->firstframe,  fr->firstoff
938
182k
  , 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
182k
}
945
946
void INT123_frame_skip(mpg123_handle *fr)
947
1.22k
{
948
1.22k
#ifndef NO_LAYER3
949
1.22k
  if(fr->hdr.lay == 3) INT123_set_pointer(fr, 1, 512);
950
1.22k
#endif
951
1.22k
}
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
445k
{
1001
445k
  double p = -1;
1002
445k
  double g = 0;
1003
445k
  int ret = 0;
1004
445k
  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
445k
  if(peak != NULL) *peak = p;
1017
445k
  if(gain != NULL) *gain = g;
1018
445k
  return ret;
1019
445k
}
1020
1021
/* adjust the volume, taking both fr->outscale and rva values into account */
1022
void INT123_do_rva(mpg123_handle *fr)
1023
445k
{
1024
445k
  double peak = 0;
1025
445k
  double gain = 0;
1026
445k
  double newscale;
1027
445k
  double rvafact = 1;
1028
445k
  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
445k
  newscale = fr->p.outscale*rvafact;
1035
1036
  /* if peak is unknown (== 0) this check won't hurt */
1037
445k
  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
445k
  if(newscale != fr->lastscale || fr->decoder_change)
1044
358k
  {
1045
358k
    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
358k
    fr->lastscale = newscale;
1047
    /* It may be too early, actually. */
1048
358k
    if(fr->INT123_make_decode_tables != NULL) fr->INT123_make_decode_tables(fr); /* the actual work */
1049
358k
  }
1050
445k
}
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
}