Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3960 | Serge | 1 | /* |
2 | ntom.c: N->M down/up sampling; the setup code. |
||
3 | |||
4 | copyright 1995-2008 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 off_t*off_t with big values still being in the range... */ |
||
10 | #include "mpg123lib_intern.h" |
||
11 | #include "debug.h" |
||
12 | |||
13 | int synth_ntom_set_step(mpg123_handle *fr) |
||
14 | { |
||
15 | long m,n; |
||
16 | m = frame_freq(fr); |
||
17 | n = fr->af.rate; |
||
18 | if(VERBOSE2) |
||
19 | fprintf(stderr,"Init rate converter: %ld->%ld\n",m,n); |
||
20 | |||
21 | if(n > NTOM_MAX_FREQ || m > NTOM_MAX_FREQ || m <= 0 || n <= 0) { |
||
22 | if(NOQUIET) error("NtoM converter: illegal rates"); |
||
23 | fr->err = MPG123_BAD_RATE; |
||
24 | return -1; |
||
25 | } |
||
26 | |||
27 | n *= NTOM_MUL; |
||
28 | fr->ntom_step = (unsigned long) n / m; |
||
29 | |||
30 | if(fr->ntom_step > (unsigned long)NTOM_MAX*NTOM_MUL) { |
||
31 | if(NOQUIET) error3("max. 1:%i conversion allowed (%lu vs %lu)!", NTOM_MAX, fr->ntom_step, (unsigned long)8*NTOM_MUL); |
||
32 | fr->err = MPG123_BAD_RATE; |
||
33 | return -1; |
||
34 | } |
||
35 | |||
36 | fr->ntom_val[0] = fr->ntom_val[1] = ntom_val(fr, fr->num); |
||
37 | return 0; |
||
38 | } |
||
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 off_t could overflow too easily). |
||
44 | */ |
||
45 | |||
46 | unsigned long ntom_val(mpg123_handle *fr, off_t frame) |
||
47 | { |
||
48 | off_t ntm; |
||
49 | #ifdef SAFE_NTOM /* Carry out the loop, without the threatening integer overflow. */ |
||
50 | off_t f; |
||
51 | ntm = NTOM_MUL>>1; /* for frame 0 */ |
||
52 | for(f=0; f 0 */ |
||
53 | { |
||
54 | ntm += spf(fr)*fr->ntom_step; |
||
55 | ntm -= (ntm/NTOM_MUL)*NTOM_MUL; |
||
56 | } |
||
57 | #else /* Just make one computation with overall sample offset. */ |
||
58 | ntm = (NTOM_MUL>>1) + spf(fr)*frame*fr->ntom_step; |
||
59 | ntm -= (ntm/NTOM_MUL)*NTOM_MUL; |
||
60 | #endif |
||
61 | return (unsigned long) ntm; |
||
62 | } |
||
63 | |||
64 | /* Set the ntom value for next expected frame to be decoded. |
||
65 | This is for keeping output consistent across seeks. */ |
||
66 | void ntom_set_ntom(mpg123_handle *fr, off_t num) |
||
67 | { |
||
68 | fr->ntom_val[1] = fr->ntom_val[0] = ntom_val(fr, num); |
||
69 | } |
||
70 | |||
71 | /* Carry out the ntom sample count operation for this one frame. |
||
72 | No fear of integer overflow here. */ |
||
73 | off_t ntom_frame_outsamples(mpg123_handle *fr) |
||
74 | { |
||
75 | /* The do this before decoding the separate channels, so there is only one common ntom value. */ |
||
76 | int ntm = fr->ntom_val[0]; |
||
77 | ntm += spf(fr)*fr->ntom_step; |
||
78 | return ntm/NTOM_MUL; |
||
79 | } |
||
80 | |||
81 | /* Convert frame offset to unadjusted output sample offset. */ |
||
82 | off_t ntom_frmouts(mpg123_handle *fr, off_t frame) |
||
83 | { |
||
84 | #ifdef SAFE_NTOM |
||
85 | off_t f; |
||
86 | #endif |
||
87 | off_t soff = 0; |
||
88 | off_t ntm = ntom_val(fr,0); |
||
89 | #ifdef SAFE_NTOM |
||
90 | if(frame <= 0) return 0; |
||
91 | for(f=0; f |
||
92 | { |
||
93 | ntm += spf(fr)*fr->ntom_step; |
||
94 | soff += ntm/NTOM_MUL; |
||
95 | ntm -= (ntm/NTOM_MUL)*NTOM_MUL; |
||
96 | } |
||
97 | #else |
||
98 | soff = (ntm + frame*(off_t)spf(fr)*(off_t)fr->ntom_step)/(off_t)NTOM_MUL; |
||
99 | #endif |
||
100 | return soff; |
||
101 | } |
||
102 | |||
103 | /* Convert input samples to unadjusted output samples. */ |
||
104 | off_t ntom_ins2outs(mpg123_handle *fr, off_t ins) |
||
105 | { |
||
106 | off_t soff = 0; |
||
107 | off_t ntm = ntom_val(fr,0); |
||
108 | #ifdef SAFE_NTOM |
||
109 | { |
||
110 | off_t block = spf(fr); |
||
111 | if(ins <= 0) return 0; |
||
112 | do |
||
113 | { |
||
114 | off_t nowblock = ins > block ? block : ins; |
||
115 | ntm += nowblock*fr->ntom_step; |
||
116 | soff += ntm/NTOM_MUL; |
||
117 | ntm -= (ntm/NTOM_MUL)*NTOM_MUL; |
||
118 | ins -= nowblock; |
||
119 | } while(ins > 0); |
||
120 | } |
||
121 | #else |
||
122 | /* Beware of overflows: when off_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 = ((off_t)ntm + (off_t)ins*(off_t)fr->ntom_step)/(off_t)NTOM_MUL; |
||
125 | #endif |
||
126 | return soff; |
||
127 | } |
||
128 | |||
129 | /* Determine frame offset from unadjusted output sample offset. */ |
||
130 | off_t ntom_frameoff(mpg123_handle *fr, off_t soff) |
||
131 | { |
||
132 | off_t ioff = 0; /* frames or samples */ |
||
133 | off_t ntm = ntom_val(fr,0); |
||
134 | #ifdef SAFE_NTOM |
||
135 | if(soff <= 0) return 0; |
||
136 | for(ioff=0; 1; ++ioff) |
||
137 | { |
||
138 | ntm += spf(fr)*fr->ntom_step; |
||
139 | if(ntm/NTOM_MUL > soff) break; |
||
140 | soff -= ntm/NTOM_MUL; |
||
141 | ntm -= (ntm/NTOM_MUL)*NTOM_MUL; |
||
142 | } |
||
143 | return ioff; |
||
144 | #else |
||
145 | ioff = (soff*(off_t)NTOM_MUL-ntm)/(off_t)fr->ntom_step; |
||
146 | return ioff/(off_t)spf(fr); |
||
147 | #endif |
||
148 | }=>=>=>=>=> |