Coverage Report

Created: 2024-07-27 06:25

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