Coverage Report

Created: 2024-07-27 06:25

/src/mpg123/src/libmpg123/ntom.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
  ntom.c: N->M down/up sampling; the setup code.
3
4
  copyright 1995-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 Michael Hipp
7
*/
8
9
#define SAFE_NTOM /* Do not depend on int64_t*int64_t with big values still being in the range... */
10
#include "mpg123lib_intern.h"
11
#include "../common/debug.h"
12
13
int INT123_synth_ntom_set_step(mpg123_handle *fr)
14
0
{
15
0
  long m,n;
16
0
  m = INT123_frame_freq(fr);
17
0
  n = fr->af.rate;
18
0
  if(VERBOSE2)
19
0
    fprintf(stderr,"Init rate converter: %ld->%ld\n",m,n);
20
21
0
  if(n > NTOM_MAX_FREQ || m > NTOM_MAX_FREQ || m <= 0 || n <= 0) {
22
0
    if(NOQUIET) error("NtoM converter: illegal rates");
23
0
    fr->err = MPG123_BAD_RATE;
24
0
    return -1;
25
0
  }
26
27
0
  n *= NTOM_MUL;
28
0
  fr->ntom_step = (unsigned long) n / m;
29
30
0
  if(fr->ntom_step > (unsigned long)NTOM_MAX*NTOM_MUL) {
31
0
    if(NOQUIET) error3("max. 1:%i conversion allowed (%lu vs %lu)!", NTOM_MAX, fr->ntom_step, (unsigned long)8*NTOM_MUL);
32
0
    fr->err = MPG123_BAD_RATE;
33
0
    return -1;
34
0
  }
35
36
0
  fr->INT123_ntom_val[0] = fr->INT123_ntom_val[1] = INT123_ntom_val(fr, fr->num);
37
0
  return 0;
38
0
}
39
40
/*
41
  The SAFE_NTOM does iterative loops instead of straight multiplication.
42
  The safety is not just about the algorithm closely mimicking the decoder instead of applying some formula,
43
  it is more about avoiding multiplication of possibly big sample offsets (a 32bit int64_t could overflow too easily).
44
*/
45
46
unsigned long INT123_ntom_val(mpg123_handle *fr, int64_t frame)
47
0
{
48
0
  int64_t ntm;
49
0
#ifdef SAFE_NTOM /* Carry out the loop, without the threatening integer overflow. */
50
0
  int64_t f;
51
0
  ntm = NTOM_MUL>>1; /* for frame 0 */
52
0
  for(f=0; f<frame; ++f)   /* for frame > 0 */
53
0
  {
54
0
    ntm += fr->spf*fr->ntom_step;
55
0
    ntm -= (ntm/NTOM_MUL)*NTOM_MUL;
56
0
  }
57
#else /* Just make one computation with overall sample offset. */
58
  ntm  = (NTOM_MUL>>1) + fr->spf*frame*fr->ntom_step;
59
  ntm -= (ntm/NTOM_MUL)*NTOM_MUL;
60
#endif
61
0
  return (unsigned long) ntm;
62
0
}
63
64
/* Set the ntom value for next expected frame to be decoded.
65
   This is for keeping output consistent across seeks. */
66
void INT123_ntom_set_ntom(mpg123_handle *fr, int64_t num)
67
0
{
68
0
  fr->INT123_ntom_val[1] = fr->INT123_ntom_val[0] = INT123_ntom_val(fr, num);
69
0
}
70
71
/* Carry out the ntom sample count operation for this one frame. 
72
   No fear of integer overflow here. */
73
int64_t INT123_ntom_frame_outsamples(mpg123_handle *fr)
74
0
{
75
  /* The do this before decoding the separate channels, so there is only one common ntom value. */
76
0
  int ntm = fr->INT123_ntom_val[0];
77
0
  ntm += fr->spf*fr->ntom_step;
78
0
  return ntm/NTOM_MUL;
79
0
}
80
81
/* Convert frame offset to unadjusted output sample offset. */
82
int64_t INT123_ntom_frmouts(mpg123_handle *fr, int64_t frame)
83
0
{
84
0
#ifdef SAFE_NTOM
85
0
  int64_t f;
86
0
#endif
87
0
  int64_t soff = 0;
88
0
  int64_t ntm = INT123_ntom_val(fr,0);
89
0
#ifdef SAFE_NTOM
90
0
  if(frame <= 0) return 0;
91
0
  for(f=0; f<frame; ++f)
92
0
  {
93
0
    ntm  += fr->spf*fr->ntom_step;
94
0
    soff += ntm/NTOM_MUL;
95
0
    ntm  -= (ntm/NTOM_MUL)*NTOM_MUL;
96
0
  }
97
#else
98
  soff = (ntm + frame*(int64_t)fr->spf*(int64_t)fr->ntom_step)/(int64_t)NTOM_MUL;
99
#endif
100
0
  return soff;
101
0
}
102
103
/* Convert input samples to unadjusted output samples. */
104
int64_t INT123_ntom_ins2outs(mpg123_handle *fr, int64_t ins)
105
0
{
106
0
  int64_t soff = 0;
107
0
  int64_t ntm = INT123_ntom_val(fr,0);
108
0
#ifdef SAFE_NTOM
109
0
  {
110
0
    int64_t block = fr->spf;
111
0
    if(ins <= 0) return 0;
112
0
    do
113
0
    {
114
0
      int64_t nowblock = ins > block ? block : ins;
115
0
      ntm  += nowblock*fr->ntom_step;
116
0
      soff += ntm/NTOM_MUL;
117
0
      ntm  -= (ntm/NTOM_MUL)*NTOM_MUL;
118
0
      ins -= nowblock;
119
0
    } while(ins > 0);
120
0
  }
121
#else
122
  /* Beware of overflows: when int64_t is 32bits, the multiplication blows too easily.
123
     Of course, it blows for 64bits, too, in theory, but that's for _really_ large files. */
124
  soff = ((int64_t)ntm + (int64_t)ins*(int64_t)fr->ntom_step)/(int64_t)NTOM_MUL;
125
#endif
126
0
  return soff;
127
0
}
128
129
/* Determine frame offset from unadjusted output sample offset. */
130
int64_t INT123_ntom_frameoff(mpg123_handle *fr, int64_t soff)
131
0
{
132
0
  int64_t ioff = 0; /* frames or samples */
133
0
  int64_t ntm = INT123_ntom_val(fr,0);
134
0
#ifdef SAFE_NTOM
135
0
  if(soff <= 0) return 0;
136
0
  for(ioff=0; 1; ++ioff)
137
0
  {
138
0
    ntm  += fr->spf*fr->ntom_step;
139
0
    if(ntm/NTOM_MUL > soff) break;
140
0
    soff -= ntm/NTOM_MUL;
141
0
    ntm  -= (ntm/NTOM_MUL)*NTOM_MUL;
142
0
  }
143
0
  return ioff;
144
#else
145
  ioff = (soff*(int64_t)NTOM_MUL-ntm)/(int64_t)fr->ntom_step;
146
  return ioff/(int64_t)fr->spf;
147
#endif
148
0
}