Ticket #8659: diff.2

File diff.2, 11.2 KB (added by SF/robinwatts, 17 years ago)

Revised version

Line 
1Index: rate.cpp
2===================================================================
3--- rate.cpp (revision 26806)
4+++ rate.cpp (working copy)
5@@ -52,6 +52,140 @@
6
7
8 /**
9+ * Audio rate converter based on simple resampling. Used when no
10+ * interpolation is required.
11+ *
12+ * Limited to sampling frequency <= 65535 Hz.
13+ */
14+template<bool stereo, bool reverseStereo>
15+class SimpleRateConverter : public RateConverter {
16+protected:
17+ st_sample_t inBuf[INTERMEDIATE_BUFFER_SIZE];
18+ const st_sample_t *inPtr;
19+ int inLen;
20+
21+ /** position of how far output is ahead of input */
22+ /** Holds what would have been opos-ipos */
23+ long opos;
24+
25+ /** fractional position increment in the output stream */
26+ long opos_inc;
27+
28+public:
29+ SimpleRateConverter(st_rate_t inrate, st_rate_t outrate);
30+ int flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r);
31+ int drain(st_sample_t *obuf, st_size_t osamp, st_volume_t vol) {
32+ return (ST_SUCCESS);
33+ }
34+};
35+
36+
37+/*
38+ * Prepare processing.
39+ */
40+template<bool stereo, bool reverseStereo>
41+SimpleRateConverter<stereo, reverseStereo>::SimpleRateConverter(st_rate_t inrate, st_rate_t outrate) {
42+ if (inrate == outrate) {
43+ error("Input and Output rates must be different to use rate effect");
44+ }
45+
46+ if ((inrate % outrate) != 0) {
47+ error("Input rate must be a multiple of Output rate to use rate effect");
48+ }
49+
50+ if (inrate >= 65536 || outrate >= 65536) {
51+ error("rate effect can only handle rates < 65536");
52+ }
53+
54+ opos = 1;
55+
56+ /* increment */
57+ opos_inc = inrate / outrate;
58+
59+ inLen = 0;
60+}
61+
62+/*
63+ * Processed signed long samples from ibuf to obuf.
64+ * Return number of samples processed.
65+ */
66+template<bool stereo, bool reverseStereo>
67+int SimpleRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) {
68+ st_sample_t *ostart, *oend;
69+ st_sample_t out[2];
70+
71+ ostart = obuf;
72+ oend = obuf + osamp * 2;
73+
74+ if ((vol_l != Audio::Mixer::kMaxMixerVolume) || (vol_r != Audio::Mixer::kMaxMixerVolume)) {
75+
76+ while (obuf < oend) {
77+
78+ // read enough input samples so that opos >= 0
79+ do {
80+ // Check if we have to refill the buffer
81+ if (inLen == 0) {
82+ inPtr = inBuf;
83+ inLen = input.readBuffer(inBuf, ARRAYSIZE(inBuf));
84+ if (inLen <= 0)
85+ goto the_end;
86+ }
87+ inLen -= (stereo ? 2 : 1);
88+ opos--;
89+ if (opos >= 0) {
90+ inPtr += (stereo ? 2 : 1);
91+ }
92+ }
93+ while (opos >= 0);
94+ out[reverseStereo ] = *inPtr++;
95+ out[reverseStereo ^ 1] = (stereo ? *inPtr++ : out[reverseStereo]);
96+
97+ // Increment output position
98+ opos += opos_inc;
99+
100+ // output left channel
101+ clampedAdd(*obuf++, (out[0] * (int)vol_l) / Audio::Mixer::kMaxMixerVolume);
102+
103+ // output right channel
104+ clampedAdd(*obuf++, (out[1] * (int)vol_r) / Audio::Mixer::kMaxMixerVolume);
105+ }
106+ } else {
107+ while (obuf < oend) {
108+
109+ // read enough input samples so that ipos > opos
110+ do {
111+ // Check if we have to refill the buffer
112+ if (inLen == 0) {
113+ inPtr = inBuf;
114+ inLen = input.readBuffer(inBuf, ARRAYSIZE(inBuf));
115+ if (inLen <= 0)
116+ goto the_end;
117+ }
118+ inLen -= (stereo ? 2 : 1);
119+ opos--;
120+ if (opos >= 0) {
121+ inPtr += (stereo ? 2 : 1);
122+ }
123+ }
124+ while (opos >= 0);
125+ out[reverseStereo ] = *inPtr++;
126+ out[reverseStereo ^ 1] = (stereo ? *inPtr++ : out[reverseStereo]);
127+
128+ // Increment output position
129+ opos += opos_inc;
130+
131+ // output left channel
132+ clampedAdd(*obuf++, out[0]);
133+
134+ // output right channel
135+ clampedAdd(*obuf++, out[1]);
136+ }
137+ }
138+the_end:
139+ return (ST_SUCCESS);
140+}
141+
142+/**
143 * Audio rate converter based on simple linear Interpolation.
144 *
145 * The use of fractional increment allows us to use no buffer. It
146@@ -70,14 +204,11 @@
147 int inLen;
148
149 /** fractional position of the output stream in input stream unit */
150- unsigned long opos, opos_frac;
151+ long opos, opos_frac;
152
153 /** fractional position increment in the output stream */
154- unsigned long opos_inc, opos_inc_frac;
155+ long opos_inc, opos_inc_frac;
156
157- /** position in the input stream (integer) */
158- unsigned long ipos;
159-
160 /** last sample(s) in the input stream (left/right channel) */
161 st_sample_t ilast[2];
162 /** current sample(s) in the input stream (left/right channel) */
163@@ -116,8 +247,6 @@
164 opos_inc_frac = incr & ((1UL << FRAC_BITS) - 1);
165 opos_inc = incr >> FRAC_BITS;
166
167- ipos = 0;
168-
169 ilast[0] = ilast[1] = 0;
170 icur[0] = icur[1] = 0;
171
172@@ -133,60 +262,108 @@
173 st_sample_t *ostart, *oend;
174 st_sample_t out[2];
175
176- const int numChannels = stereo ? 2 : 1;
177- int i;
178-
179 ostart = obuf;
180 oend = obuf + osamp * 2;
181
182- while (obuf < oend) {
183+ if ((vol_l != Audio::Mixer::kMaxMixerVolume) || (vol_r != Audio::Mixer::kMaxMixerVolume)) {
184
185- // read enough input samples so that ipos > opos
186- while (ipos <= opos) {
187- // Check if we have to refill the buffer
188- if (inLen == 0) {
189- inPtr = inBuf;
190- inLen = input.readBuffer(inBuf, ARRAYSIZE(inBuf));
191- if (inLen <= 0)
192+ while (obuf < oend) {
193+
194+ // read enough input samples so that opos <= 0
195+ while (0 <= opos) {
196+ // Check if we have to refill the buffer
197+ if (inLen == 0) {
198+ inPtr = inBuf;
199+ inLen = input.readBuffer(inBuf, ARRAYSIZE(inBuf));
200+ if (inLen <= 0)
201+ goto the_end;
202+ }
203+ inLen -= (stereo ? 2 : 1);
204+ ilast[0] = icur[0];
205+ icur[0] = *inPtr++;
206+ if (stereo) {
207+ ilast[1] = icur[1];
208+ icur[1] = *inPtr++;
209+ }
210+ opos--;
211+ }
212+
213+ // Loop as long as the outpos trails behind, and as long as there is
214+ // still space in the output buffer.
215+ while (0 > opos) {
216+
217+ // interpolate
218+ out[reverseStereo ] = (st_sample_t)(ilast[0] + (((icur[0] - ilast[0]) * opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS));
219+ out[reverseStereo ^ 1] = (stereo ?
220+ (st_sample_t)(ilast[1] + (((icur[1] - ilast[1]) * opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS)) :
221+ out[reverseStereo]);
222+
223+ // output left channel
224+ clampedAdd(*obuf++, (out[0] * (int)vol_l) / Audio::Mixer::kMaxMixerVolume);
225+
226+ // output right channel
227+ clampedAdd(*obuf++, (out[1] * (int)vol_r) / Audio::Mixer::kMaxMixerVolume);
228+
229+ // Increment output position
230+ long tmp = opos_frac + opos_inc_frac;
231+ opos += opos_inc + (tmp >> FRAC_BITS);
232+ opos_frac = tmp & ((1UL << FRAC_BITS) - 1);
233+
234+ // Abort if we reached the end of the output buffer
235+ if (obuf >= oend)
236 goto the_end;
237 }
238- for (i = 0; i < numChannels; i++) {
239- ilast[i] = icur[i];
240- icur[i] = *inPtr++;
241- inLen--;
242- }
243- ipos++;
244 }
245+ } else {
246
247- // Loop as long as the outpos trails behind, and as long as there is
248- // still space in the output buffer.
249- while (ipos > opos) {
250+ while (obuf < oend) {
251
252- // interpolate
253- out[0] = out[1] = (st_sample_t)(ilast[0] + (((icur[0] - ilast[0]) * opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS));
254+ // read enough input samples so that ipos > opos
255+ while (0 <= opos) {
256+ // Check if we have to refill the buffer
257+ if (inLen == 0) {
258+ inPtr = inBuf;
259+ inLen = input.readBuffer(inBuf, ARRAYSIZE(inBuf));
260+ if (inLen <= 0)
261+ goto the_end;
262+ }
263+ inLen -= (stereo ? 2 : 1);
264+ ilast[0] = icur[0];
265+ icur[0] = *inPtr++;
266+ if (stereo) {
267+ ilast[1] = icur[1];
268+ icur[1] = *inPtr++;
269+ }
270+ opos--;
271+ }
272
273- if (stereo) {
274+ // Loop as long as the outpos trails behind, and as long as there is
275+ // still space in the output buffer.
276+ while (0 > opos) {
277+
278 // interpolate
279- out[reverseStereo ? 0 : 1] = (st_sample_t)(ilast[1] + (((icur[1] - ilast[1]) * opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS));
280- }
281+ out[reverseStereo ] = (st_sample_t)(ilast[0] + (((icur[0] - ilast[0]) * opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS));
282+ out[reverseStereo ^ 1] = (stereo ?
283+ (st_sample_t)(ilast[1] + (((icur[1] - ilast[1]) * opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS)) :
284+ out[reverseStereo]);
285
286- // output left channel
287- clampedAdd(*obuf++, (out[0] * (int)vol_l) / Audio::Mixer::kMaxMixerVolume);
288+ // output left channel
289+ clampedAdd(*obuf++, out[0]);
290
291- // output right channel
292- clampedAdd(*obuf++, (out[1] * (int)vol_r) / Audio::Mixer::kMaxMixerVolume);
293+ // output right channel
294+ clampedAdd(*obuf++, out[1]);
295
296- // Increment output position
297- unsigned long tmp = opos_frac + opos_inc_frac;
298- opos += opos_inc + (tmp >> FRAC_BITS);
299- opos_frac = tmp & ((1UL << FRAC_BITS) - 1);
300+ // Increment output position
301+ long tmp = opos_frac + opos_inc_frac;
302+ opos += opos_inc + (tmp >> FRAC_BITS);
303+ opos_frac = tmp & ((1UL << FRAC_BITS) - 1);
304
305- // Abort if we reached the end of the output buffer
306- if (obuf >= oend)
307- goto the_end;
308+ // Abort if we reached the end of the output buffer
309+ if (obuf >= oend)
310+ goto the_end;
311+ }
312 }
313 }
314-
315 the_end:
316 return (ST_SUCCESS);
317 }
318@@ -229,22 +406,32 @@
319
320 // Mix the data into the output buffer
321 ptr = _buffer;
322- while (len-- > 0) {
323- st_sample_t tmp0, tmp1;
324- tmp0 = tmp1 = *ptr++;
325- if (stereo) {
326- if (reverseStereo)
327- tmp0 = *ptr++;
328- else
329- tmp1 = *ptr++;
330- len--;
331+ if ((vol_l != Audio::Mixer::kMaxMixerVolume) || (vol_r != Audio::Mixer::kMaxMixerVolume)) {
332+ while (len > 0) {
333+ st_sample_t tmp[2];
334+ tmp[reverseStereo ] = *ptr++;
335+ tmp[reverseStereo ^ 1] = (stereo ? *ptr++ : tmp[reverseStereo]);
336+
337+ // output left channel
338+ clampedAdd(*obuf++, (tmp[0] * (int)vol_l) / Audio::Mixer::kMaxMixerVolume);
339+
340+ // output right channel
341+ clampedAdd(*obuf++, (tmp[1] * (int)vol_r) / Audio::Mixer::kMaxMixerVolume);
342+ len -= (stereo ? 2 : 1);
343 }
344+ } else {
345+ while (len > 0) {
346+ st_sample_t tmp[2];
347+ tmp[reverseStereo ] = *ptr++;
348+ tmp[reverseStereo ^ 1] = (stereo ? *ptr++ : tmp[reverseStereo]);
349
350- // output left channel
351- clampedAdd(*obuf++, (tmp0 * (int)vol_l) / Audio::Mixer::kMaxMixerVolume);
352+ // output left channel
353+ clampedAdd(*obuf++, tmp[0]);
354
355- // output right channel
356- clampedAdd(*obuf++, (tmp1 * (int)vol_r) / Audio::Mixer::kMaxMixerVolume);
357+ // output right channel
358+ clampedAdd(*obuf++, tmp[1]);
359+ len -= (stereo ? 2 : 1);
360+ }
361 }
362 return (ST_SUCCESS);
363 }
364@@ -262,14 +449,23 @@
365 */
366 RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool stereo, bool reverseStereo) {
367 if (inrate != outrate) {
368- if (stereo) {
369- if (reverseStereo)
370- return new LinearRateConverter<true, true>(inrate, outrate);
371- else
372- return new LinearRateConverter<true, false>(inrate, outrate);
373- } else
374- return new LinearRateConverter<false, false>(inrate, outrate);
375- //return new ResampleRateConverter(inrate, outrate, 1);
376+ if ((inrate % outrate) == 0) {
377+ if (stereo) {
378+ if (reverseStereo)
379+ return new SimpleRateConverter<true, true>(inrate, outrate);
380+ else
381+ return new SimpleRateConverter<true, false>(inrate, outrate);
382+ } else
383+ return new SimpleRateConverter<false, false>(inrate, outrate);
384+ } else {
385+ if (stereo) {
386+ if (reverseStereo)
387+ return new LinearRateConverter<true, true>(inrate, outrate);
388+ else
389+ return new LinearRateConverter<true, false>(inrate, outrate);
390+ } else
391+ return new LinearRateConverter<false, false>(inrate, outrate);
392+ }
393 } else {
394 if (stereo) {
395 if (reverseStereo)