diff options
author | Max Horn | 2007-06-28 19:35:48 +0000 |
---|---|---|
committer | Max Horn | 2007-06-28 19:35:48 +0000 |
commit | 6dfa44dbd58e0a8c1a6b4e31c2fe605b75fce6ed (patch) | |
tree | 8a13896b3e691d3176cb4ad079df6d0a077819ee | |
parent | 2249db2c6d7603bf3fc81241fa4b87b0a7f72610 (diff) | |
download | scummvm-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.h | 51 | ||||
-rw-r--r-- | sound/rate.cpp | 89 |
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 |