Only set interface palette when painting backdrop. (This fixes movie palette.)
[scummvm-innocent.git] / sound / rate.cpp
blob91213b312c42765e0eb95b8bb08ce020dd0c05ad
1 /* ScummVM - Graphic Adventure Engine
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * $URL$
22 * $Id$
27 * The code in this file is based on code with Copyright 1998 Fabrice Bellard
28 * Fabrice original code is part of SoX (http://sox.sourceforge.net).
29 * Max Horn adapted that code to the needs of ScummVM and rewrote it partial,
30 * in the process removing any use of floating point arithmetic. Various other
31 * improvments over the original code were made.
34 #include "sound/audiostream.h"
35 #include "sound/rate.h"
36 #include "sound/mixer.h"
37 #include "common/frac.h"
38 #include "common/util.h"
40 namespace Audio {
43 /**
44 * The size of the intermediate input cache. Bigger values may increase
45 * performance, but only until some point (depends largely on cache size,
46 * target processor and various other factors), at which it will decrease
47 * again.
49 #define INTERMEDIATE_BUFFER_SIZE 512
52 /**
53 * Audio rate converter based on simple resampling. Used when no
54 * interpolation is required.
56 * Limited to sampling frequency <= 65535 Hz.
58 template<bool stereo, bool reverseStereo>
59 class SimpleRateConverter : public RateConverter {
60 protected:
61 st_sample_t inBuf[INTERMEDIATE_BUFFER_SIZE];
62 const st_sample_t *inPtr;
63 int inLen;
65 /** position of how far output is ahead of input */
66 /** Holds what would have been opos-ipos */
67 long opos;
69 /** fractional position increment in the output stream */
70 long opos_inc;
72 public:
73 SimpleRateConverter(st_rate_t inrate, st_rate_t outrate);
74 int flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r);
75 int drain(st_sample_t *obuf, st_size_t osamp, st_volume_t vol) {
76 return ST_SUCCESS;
82 * Prepare processing.
84 template<bool stereo, bool reverseStereo>
85 SimpleRateConverter<stereo, reverseStereo>::SimpleRateConverter(st_rate_t inrate, st_rate_t outrate) {
86 if ((inrate % outrate) != 0) {
87 error("Input rate must be a multiple of output rate to use rate effect");
90 if (inrate >= 65536 || outrate >= 65536) {
91 error("rate effect can only handle rates < 65536");
94 opos = 1;
96 /* increment */
97 opos_inc = inrate / outrate;
99 inLen = 0;
103 * Processed signed long samples from ibuf to obuf.
104 * Return number of samples processed.
106 template<bool stereo, bool reverseStereo>
107 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) {
108 st_sample_t *ostart, *oend;
110 ostart = obuf;
111 oend = obuf + osamp * 2;
113 while (obuf < oend) {
115 // read enough input samples so that opos >= 0
116 do {
117 // Check if we have to refill the buffer
118 if (inLen == 0) {
119 inPtr = inBuf;
120 inLen = input.readBuffer(inBuf, ARRAYSIZE(inBuf));
121 if (inLen <= 0)
122 return ST_EOF;
124 inLen -= (stereo ? 2 : 1);
125 opos--;
126 if (opos >= 0) {
127 inPtr += (stereo ? 2 : 1);
129 } while (opos >= 0);
131 st_sample_t out0, out1;
132 out0 = *inPtr++;
133 out1 = (stereo ? *inPtr++ : out0);
135 // Increment output position
136 opos += opos_inc;
138 // output left channel
139 clampedAdd(obuf[reverseStereo ], (out0 * (int)vol_l) / Audio::Mixer::kMaxMixerVolume);
141 // output right channel
142 clampedAdd(obuf[reverseStereo ^ 1], (out1 * (int)vol_r) / Audio::Mixer::kMaxMixerVolume);
144 obuf += 2;
146 return ST_SUCCESS;
150 * Audio rate converter based on simple linear Interpolation.
152 * The use of fractional increment allows us to use no buffer. It
153 * avoid the problems at the end of the buffer we had with the old
154 * method which stored a possibly big buffer of size
155 * lcm(in_rate,out_rate).
157 * Limited to sampling frequency <= 65535 Hz.
160 template<bool stereo, bool reverseStereo>
161 class LinearRateConverter : public RateConverter {
162 protected:
163 st_sample_t inBuf[INTERMEDIATE_BUFFER_SIZE];
164 const st_sample_t *inPtr;
165 int inLen;
167 /** fractional position of the output stream in input stream unit */
168 frac_t opos;
170 /** fractional position increment in the output stream */
171 frac_t opos_inc;
173 /** last sample(s) in the input stream (left/right channel) */
174 st_sample_t ilast0, ilast1;
175 /** current sample(s) in the input stream (left/right channel) */
176 st_sample_t icur0, icur1;
178 public:
179 LinearRateConverter(st_rate_t inrate, st_rate_t outrate);
180 int flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r);
181 int drain(st_sample_t *obuf, st_size_t osamp, st_volume_t vol) {
182 return ST_SUCCESS;
188 * Prepare processing.
190 template<bool stereo, bool reverseStereo>
191 LinearRateConverter<stereo, reverseStereo>::LinearRateConverter(st_rate_t inrate, st_rate_t outrate) {
192 if (inrate >= 65536 || outrate >= 65536) {
193 error("rate effect can only handle rates < 65536");
196 opos = FRAC_ONE;
198 // Compute the linear interpolation increment.
199 // This will overflow if inrate >= 2^16, and underflow if outrate >= 2^16.
200 // Also, if the quotient of the two rate becomes too small / too big, that
201 // would cause problems, but since we rarely scale from 1 to 65536 Hz or vice
202 // versa, I think we can live with that limiation ;-).
203 opos_inc = (inrate << FRAC_BITS) / outrate;
205 ilast0 = ilast1 = 0;
206 icur0 = icur1 = 0;
208 inLen = 0;
212 * Processed signed long samples from ibuf to obuf.
213 * Return number of samples processed.
215 template<bool stereo, bool reverseStereo>
216 int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) {
217 st_sample_t *ostart, *oend;
219 ostart = obuf;
220 oend = obuf + osamp * 2;
222 while (obuf < oend) {
224 // read enough input samples so that opos < 0
225 while ((frac_t)FRAC_ONE <= opos) {
226 // Check if we have to refill the buffer
227 if (inLen == 0) {
228 inPtr = inBuf;
229 inLen = input.readBuffer(inBuf, ARRAYSIZE(inBuf));
230 if (inLen <= 0)
231 return ST_EOF;
233 inLen -= (stereo ? 2 : 1);
234 ilast0 = icur0;
235 icur0 = *inPtr++;
236 if (stereo) {
237 ilast1 = icur1;
238 icur1 = *inPtr++;
240 opos -= FRAC_ONE;
243 // Loop as long as the outpos trails behind, and as long as there is
244 // still space in the output buffer.
245 while (opos < (frac_t)FRAC_ONE && obuf < oend) {
246 // interpolate
247 st_sample_t out0, out1;
248 out0 = (st_sample_t)(ilast0 + (((icur0 - ilast0) * opos + FRAC_HALF) >> FRAC_BITS));
249 out1 = (stereo ?
250 (st_sample_t)(ilast1 + (((icur1 - ilast1) * opos + FRAC_HALF) >> FRAC_BITS)) :
251 out0);
253 // output left channel
254 clampedAdd(obuf[reverseStereo ], (out0 * (int)vol_l) / Audio::Mixer::kMaxMixerVolume);
256 // output right channel
257 clampedAdd(obuf[reverseStereo ^ 1], (out1 * (int)vol_r) / Audio::Mixer::kMaxMixerVolume);
259 obuf += 2;
261 // Increment output position
262 opos += opos_inc;
265 return ST_SUCCESS;
269 #pragma mark -
273 * Simple audio rate converter for the case that the inrate equals the outrate.
275 template<bool stereo, bool reverseStereo>
276 class CopyRateConverter : public RateConverter {
277 st_sample_t *_buffer;
278 st_size_t _bufferSize;
279 public:
280 CopyRateConverter() : _buffer(0), _bufferSize(0) {}
281 ~CopyRateConverter() {
282 free(_buffer);
285 virtual int flow(AudioStream &input, st_sample_t *obuf, st_size_t osamp, st_volume_t vol_l, st_volume_t vol_r) {
286 assert(input.isStereo() == stereo);
288 st_sample_t *ptr;
289 st_size_t len;
291 if (stereo)
292 osamp *= 2;
294 // Reallocate temp buffer, if necessary
295 if (osamp > _bufferSize) {
296 free(_buffer);
297 _buffer = (st_sample_t *)malloc(osamp * 2);
298 _bufferSize = osamp;
301 // Read up to 'osamp' samples into our temporary buffer
302 len = input.readBuffer(_buffer, osamp);
304 // Mix the data into the output buffer
305 ptr = _buffer;
306 for (; len > 0; len -= (stereo ? 2 : 1)) {
307 st_sample_t out0, out1;
308 out0 = *ptr++;
309 out1 = (stereo ? *ptr++ : out0);
311 // output left channel
312 clampedAdd(obuf[reverseStereo ], (out0 * (int)vol_l) / Audio::Mixer::kMaxMixerVolume);
314 // output right channel
315 clampedAdd(obuf[reverseStereo ^ 1], (out1 * (int)vol_r) / Audio::Mixer::kMaxMixerVolume);
317 obuf += 2;
319 return ST_SUCCESS;
322 virtual int drain(st_sample_t *obuf, st_size_t osamp, st_volume_t vol) {
323 return ST_SUCCESS;
328 #pragma mark -
330 template<bool stereo, bool reverseStereo>
331 RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate) {
332 if (inrate != outrate) {
333 if ((inrate % outrate) == 0) {
334 return new SimpleRateConverter<stereo, reverseStereo>(inrate, outrate);
335 } else {
336 return new LinearRateConverter<stereo, reverseStereo>(inrate, outrate);
338 } else {
339 return new CopyRateConverter<stereo, reverseStereo>();
344 * Create and return a RateConverter object for the specified input and output rates.
346 RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool stereo, bool reverseStereo) {
347 if (stereo) {
348 if (reverseStereo)
349 return makeRateConverter<true, true>(inrate, outrate);
350 else
351 return makeRateConverter<true, false>(inrate, outrate);
352 } else
353 return makeRateConverter<false, false>(inrate, outrate);
356 } // End of namespace Audio