xref: /reactos/sdk/lib/3rdparty/libmpg123/ntom.c (revision 34593d93)
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 
synth_ntom_set_step(mpg123_handle * fr)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 
ntom_val(mpg123_handle * fr,off_t frame)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<frame; ++f)   /* for frame > 0 */
53 	{
54 		ntm += fr->spf*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) + fr->spf*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. */
ntom_set_ntom(mpg123_handle * fr,off_t num)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. */
ntom_frame_outsamples(mpg123_handle * fr)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 += fr->spf*fr->ntom_step;
78 	return ntm/NTOM_MUL;
79 }
80 
81 /* Convert frame offset to unadjusted output sample offset. */
ntom_frmouts(mpg123_handle * fr,off_t frame)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<frame; ++f)
92 	{
93 		ntm  += fr->spf*fr->ntom_step;
94 		soff += ntm/NTOM_MUL;
95 		ntm  -= (ntm/NTOM_MUL)*NTOM_MUL;
96 	}
97 #else
98 	soff = (ntm + frame*(off_t)fr->spf*(off_t)fr->ntom_step)/(off_t)NTOM_MUL;
99 #endif
100 	return soff;
101 }
102 
103 /* Convert input samples to unadjusted output samples. */
ntom_ins2outs(mpg123_handle * fr,off_t ins)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 = fr->spf;
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. */
ntom_frameoff(mpg123_handle * fr,off_t soff)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  += fr->spf*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)fr->spf;
147 #endif
148 }
149