/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 | } |