aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Horn2007-06-28 19:35:48 +0000
committerMax Horn2007-06-28 19:35:48 +0000
commit6dfa44dbd58e0a8c1a6b4e31c2fe605b75fce6ed (patch)
tree8a13896b3e691d3176cb4ad079df6d0a077819ee
parent2249db2c6d7603bf3fc81241fa4b87b0a7f72610 (diff)
downloadscummvm-rg350-6dfa44dbd58e0a8c1a6b4e31c2fe605b75fce6ed.tar.gz
scummvm-rg350-6dfa44dbd58e0a8c1a6b4e31c2fe605b75fce6ed.tar.bz2
scummvm-rg350-6dfa44dbd58e0a8c1a6b4e31c2fe605b75fce6ed.zip
Moved some fixed point code to its own header file; simplified the LinearRateConverter code a bit; corrected some comments; split makeRateConverter into two funcs (one of them being a template func), for easier maintenance
svn-id: r27760
-rw-r--r--common/frac.h51
-rw-r--r--sound/rate.cpp89
2 files changed, 82 insertions, 58 deletions
diff --git a/common/frac.h b/common/frac.h
new file mode 100644
index 0000000000..d4df455c32
--- /dev/null
+++ b/common/frac.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef COMMON_FRAC_H
+#define COMMON_FRAC_H
+
+#include "common/scummsys.h"
+
+/**
+ * The precision of the fractional (fixed point) type we define below.
+ * Normally you should never have to modify this value.
+ */
+enum {
+ FRAC_BITS = 16,
+ FRAC_LO_MASK = ((1L << FRAC_BITS) - 1),
+ FRAC_HI_MASK = ((1L << FRAC_BITS) - 1) << FRAC_BITS,
+
+ FRAC_ONE = (1L << FRAC_BITS), // 1.0
+ FRAC_HALF = (1L << (FRAC_BITS-1)) // 0.5
+};
+
+/**
+ * Fixed-point fractions, used by the sound rate converter and other code.
+ */
+typedef int32 frac_t;
+
+inline frac_t intToFrac(int16 value) { return value << FRAC_BITS; }
+
+#endif
diff --git a/sound/rate.cpp b/sound/rate.cpp
index 6a51f3d5d5..105b5d5d26 100644
--- a/sound/rate.cpp
+++ b/sound/rate.cpp
@@ -35,15 +35,11 @@
#include "sound/audiostream.h"
#include "sound/rate.h"
#include "sound/mixer.h"
+#include "common/frac.h"
#include "common/util.h"
namespace Audio {
-/**
- * The precision of the fractional computations used by the rate converter.
- * Normally you should never have to modify this value.
- */
-#define FRAC_BITS 16
/**
* The size of the intermediate input cache. Bigger values may increase
@@ -88,12 +84,8 @@ public:
*/
template<bool stereo, bool reverseStereo>
SimpleRateConverter<stereo, reverseStereo>::SimpleRateConverter(st_rate_t inrate, st_rate_t outrate) {
- if (inrate == outrate) {
- error("Input and Output rates must be different to use rate effect");
- }
-
if ((inrate % outrate) != 0) {
- error("Input rate must be a multiple of Output rate to use rate effect");
+ error("Input rate must be a multiple of output rate to use rate effect");
}
if (inrate >= 65536 || outrate >= 65536) {
@@ -174,10 +166,10 @@ protected:
int inLen;
/** fractional position of the output stream in input stream unit */
- long opos, opos_frac;
+ frac_t opos;
/** fractional position increment in the output stream */
- long opos_inc, opos_inc_frac;
+ frac_t opos_inc;
/** last sample(s) in the input stream (left/right channel) */
st_sample_t ilast0, ilast1;
@@ -198,24 +190,14 @@ public:
*/
template<bool stereo, bool reverseStereo>
LinearRateConverter<stereo, reverseStereo>::LinearRateConverter(st_rate_t inrate, st_rate_t outrate) {
- unsigned long incr;
-
- if (inrate == outrate) {
- error("Input and Output rates must be different to use rate effect");
- }
-
if (inrate >= 65536 || outrate >= 65536) {
error("rate effect can only handle rates < 65536");
}
- opos_frac = 0;
- opos = 1;
+ opos = FRAC_ONE;
/* increment */
- incr = (inrate << FRAC_BITS) / outrate;
-
- opos_inc_frac = incr & ((1UL << FRAC_BITS) - 1);
- opos_inc = incr >> FRAC_BITS;
+ opos_inc = (inrate << FRAC_BITS) / outrate;
ilast0 = ilast1 = 0;
icur0 = icur1 = 0;
@@ -236,7 +218,7 @@ int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
while (obuf < oend) {
- // read enough input samples so that opos <= 0
+ // read enough input samples so that opos < 0
while (0 <= opos) {
// Check if we have to refill the buffer
if (inLen == 0) {
@@ -252,7 +234,7 @@ int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
ilast1 = icur1;
icur1 = *inPtr++;
}
- opos--;
+ opos -= FRAC_ONE;
}
// Loop as long as the outpos trails behind, and as long as there is
@@ -260,9 +242,10 @@ int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
while (0 > opos && obuf < oend) {
// interpolate
st_sample_t out0, out1;
- out0 = (st_sample_t)(ilast0 + (((icur0 - ilast0) * opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS));
+ const frac_t scale = (opos & FRAC_LO_MASK);
+ out0 = (st_sample_t)(ilast0 + (((icur0 - ilast0) * scale + FRAC_HALF) >> FRAC_BITS));
out1 = (stereo ?
- (st_sample_t)(ilast1 + (((icur1 - ilast1) * opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS)) :
+ (st_sample_t)(ilast1 + (((icur1 - ilast1) * scale + FRAC_HALF) >> FRAC_BITS)) :
out0);
// output left channel
@@ -274,9 +257,7 @@ int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp
obuf += 2;
// Increment output position
- long tmp = opos_frac + opos_inc_frac;
- opos += opos_inc + (tmp >> FRAC_BITS);
- opos_frac = tmp & ((1UL << FRAC_BITS) - 1);
+ opos += opos_inc;
}
}
return ST_SUCCESS;
@@ -344,38 +325,30 @@ public:
#pragma mark -
-
-/**
- * Create and return a RateConverter object for the specified input and output rates.
- */
-RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool stereo, bool reverseStereo) {
+template<bool stereo, bool reverseStereo>
+RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate) {
if (inrate != outrate) {
if ((inrate % outrate) == 0) {
- if (stereo) {
- if (reverseStereo)
- return new SimpleRateConverter<true, true>(inrate, outrate);
- else
- return new SimpleRateConverter<true, false>(inrate, outrate);
- } else
- return new SimpleRateConverter<false, false>(inrate, outrate);
+ return new SimpleRateConverter<stereo, reverseStereo>(inrate, outrate);
} else {
- if (stereo) {
- if (reverseStereo)
- return new LinearRateConverter<true, true>(inrate, outrate);
- else
- return new LinearRateConverter<true, false>(inrate, outrate);
- } else
- return new LinearRateConverter<false, false>(inrate, outrate);
- }
+ return new LinearRateConverter<stereo, reverseStereo>(inrate, outrate);
+ }
} else {
- if (stereo) {
- if (reverseStereo)
- return new CopyRateConverter<true, true>();
- else
- return new CopyRateConverter<true, false>();
- } else
- return new CopyRateConverter<false, false>();
+ return new CopyRateConverter<stereo, reverseStereo>();
}
}
+/**
+ * Create and return a RateConverter object for the specified input and output rates.
+ */
+RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool stereo, bool reverseStereo) {
+ if (stereo) {
+ if (reverseStereo)
+ return makeRateConverter<true, true>(inrate, outrate);
+ else
+ return makeRateConverter<true, false>(inrate, outrate);
+ } else
+ return makeRateConverter<false, false>(inrate, outrate);
+}
+
} // End of namespace Audio