Ticket #8659: SoundRateDiffs.txt

File SoundRateDiffs.txt, 7.6 KB (added by SF/robinwatts, 17 years ago)

Sound Rate Diffs v3

Line 
1Index: sound/rate.cpp
2===================================================================
3--- sound/rate.cpp (revision 27465)
4+++ sound/rate.cpp (working copy)
5@@ -55,6 +55,106 @@
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+ while (obuf < oend) {
75+
76+ // read enough input samples so that opos >= 0
77+ do {
78+ // Check if we have to refill the buffer
79+ if (inLen == 0) {
80+ inPtr = inBuf;
81+ inLen = input.readBuffer(inBuf, ARRAYSIZE(inBuf));
82+ if (inLen <= 0)
83+ goto the_end;
84+ }
85+ inLen -= (stereo ? 2 : 1);
86+ opos--;
87+ if (opos >= 0) {
88+ inPtr += (stereo ? 2 : 1);
89+ }
90+ }
91+ while (opos >= 0);
92+ out[reverseStereo ] = *inPtr++;
93+ out[reverseStereo ^ 1] = (stereo ? *inPtr++ : out[reverseStereo]);
94+
95+ // Increment output position
96+ opos += opos_inc;
97+
98+ // output left channel
99+ clampedAdd(*obuf++, (out[0] * (int)vol_l) / Audio::Mixer::kMaxMixerVolume);
100+
101+ // output right channel
102+ clampedAdd(*obuf++, (out[1] * (int)vol_r) / Audio::Mixer::kMaxMixerVolume);
103+ }
104+the_end:
105+ return (ST_SUCCESS);
106+}
107+
108+/**
109 * Audio rate converter based on simple linear Interpolation.
110 *
111 * The use of fractional increment allows us to use no buffer. It
112@@ -73,14 +173,11 @@
113 int inLen;
114
115 /** fractional position of the output stream in input stream unit */
116- unsigned long opos, opos_frac;
117+ long opos, opos_frac;
118
119 /** fractional position increment in the output stream */
120- unsigned long opos_inc, opos_inc_frac;
121+ long opos_inc, opos_inc_frac;
122
123- /** position in the input stream (integer) */
124- unsigned long ipos;
125-
126 /** last sample(s) in the input stream (left/right channel) */
127 st_sample_t ilast[2];
128 /** current sample(s) in the input stream (left/right channel) */
129@@ -119,8 +216,6 @@
130 opos_inc_frac = incr & ((1UL << FRAC_BITS) - 1);
131 opos_inc = incr >> FRAC_BITS;
132
133- ipos = 0;
134-
135 ilast[0] = ilast[1] = 0;
136 icur[0] = icur[1] = 0;
137
138@@ -136,16 +231,13 @@
139 st_sample_t *ostart, *oend;
140 st_sample_t out[2];
141
142- const int numChannels = stereo ? 2 : 1;
143- int i;
144-
145 ostart = obuf;
146 oend = obuf + osamp * 2;
147
148 while (obuf < oend) {
149
150- // read enough input samples so that ipos > opos
151- while (ipos <= opos) {
152+ // read enough input samples so that opos <= 0
153+ while (0 <= opos) {
154 // Check if we have to refill the buffer
155 if (inLen == 0) {
156 inPtr = inBuf;
157@@ -153,26 +245,26 @@
158 if (inLen <= 0)
159 goto the_end;
160 }
161- for (i = 0; i < numChannels; i++) {
162- ilast[i] = icur[i];
163- icur[i] = *inPtr++;
164- inLen--;
165+ inLen -= (stereo ? 2 : 1);
166+ ilast[0] = icur[0];
167+ icur[0] = *inPtr++;
168+ if (stereo) {
169+ ilast[1] = icur[1];
170+ icur[1] = *inPtr++;
171 }
172- ipos++;
173+ opos--;
174 }
175
176 // Loop as long as the outpos trails behind, and as long as there is
177 // still space in the output buffer.
178- while (ipos > opos) {
179+ while (0 > opos) {
180
181 // interpolate
182- out[0] = out[1] = (st_sample_t)(ilast[0] + (((icur[0] - ilast[0]) * opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS));
183+ out[reverseStereo ] = (st_sample_t)(ilast[0] + (((icur[0] - ilast[0]) * opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS));
184+ out[reverseStereo ^ 1] = (stereo ?
185+ (st_sample_t)(ilast[1] + (((icur[1] - ilast[1]) * opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS)) :
186+ out[reverseStereo]);
187
188- if (stereo) {
189- // interpolate
190- out[reverseStereo ? 0 : 1] = (st_sample_t)(ilast[1] + (((icur[1] - ilast[1]) * opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS));
191- }
192-
193 // output left channel
194 clampedAdd(*obuf++, (out[0] * (int)vol_l) / Audio::Mixer::kMaxMixerVolume);
195
196@@ -180,7 +272,7 @@
197 clampedAdd(*obuf++, (out[1] * (int)vol_r) / Audio::Mixer::kMaxMixerVolume);
198
199 // Increment output position
200- unsigned long tmp = opos_frac + opos_inc_frac;
201+ long tmp = opos_frac + opos_inc_frac;
202 opos += opos_inc + (tmp >> FRAC_BITS);
203 opos_frac = tmp & ((1UL << FRAC_BITS) - 1);
204
205@@ -189,7 +281,6 @@
206 goto the_end;
207 }
208 }
209-
210 the_end:
211 return (ST_SUCCESS);
212 }
213@@ -232,22 +323,17 @@
214
215 // Mix the data into the output buffer
216 ptr = _buffer;
217- while (len-- > 0) {
218- st_sample_t tmp0, tmp1;
219- tmp0 = tmp1 = *ptr++;
220- if (stereo) {
221- if (reverseStereo)
222- tmp0 = *ptr++;
223- else
224- tmp1 = *ptr++;
225- len--;
226- }
227+ while (len > 0) {
228+ st_sample_t tmp[2];
229+ tmp[reverseStereo ] = *ptr++;
230+ tmp[reverseStereo ^ 1] = (stereo ? *ptr++ : tmp[reverseStereo]);
231
232 // output left channel
233- clampedAdd(*obuf++, (tmp0 * (int)vol_l) / Audio::Mixer::kMaxMixerVolume);
234+ clampedAdd(*obuf++, (tmp[0] * (int)vol_l) / Audio::Mixer::kMaxMixerVolume);
235
236 // output right channel
237- clampedAdd(*obuf++, (tmp1 * (int)vol_r) / Audio::Mixer::kMaxMixerVolume);
238+ clampedAdd(*obuf++, (tmp[1] * (int)vol_r) / Audio::Mixer::kMaxMixerVolume);
239+ len -= (stereo ? 2 : 1);
240 }
241 return (ST_SUCCESS);
242 }
243@@ -265,14 +351,23 @@
244 */
245 RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool stereo, bool reverseStereo) {
246 if (inrate != outrate) {
247- if (stereo) {
248- if (reverseStereo)
249- return new LinearRateConverter<true, true>(inrate, outrate);
250- else
251- return new LinearRateConverter<true, false>(inrate, outrate);
252- } else
253- return new LinearRateConverter<false, false>(inrate, outrate);
254- //return new ResampleRateConverter(inrate, outrate, 1);
255+ if ((inrate % outrate) == 0) {
256+ if (stereo) {
257+ if (reverseStereo)
258+ return new SimpleRateConverter<true, true>(inrate, outrate);
259+ else
260+ return new SimpleRateConverter<true, false>(inrate, outrate);
261+ } else
262+ return new SimpleRateConverter<false, false>(inrate, outrate);
263+ } else {
264+ if (stereo) {
265+ if (reverseStereo)
266+ return new LinearRateConverter<true, true>(inrate, outrate);
267+ else
268+ return new LinearRateConverter<true, false>(inrate, outrate);
269+ } else
270+ return new LinearRateConverter<false, false>(inrate, outrate);
271+ }
272 } else {
273 if (stereo) {
274 if (reverseStereo)