aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorMax Horn2003-07-28 11:13:01 +0000
committerMax Horn2003-07-28 11:13:01 +0000
commit9e051fa5070cd70ff0e69faa647ad26f66b64560 (patch)
treea54a6d7cf2305ff77012f1c1c8da345e10fbe2e0 /sound
parent2b0c2a20b2ccf78832fe147ebe6a98b5277048ac (diff)
downloadscummvm-rg350-9e051fa5070cd70ff0e69faa647ad26f66b64560.tar.gz
scummvm-rg350-9e051fa5070cd70ff0e69faa647ad26f66b64560.tar.bz2
scummvm-rg350-9e051fa5070cd70ff0e69faa647ad26f66b64560.zip
instead of 'int channels', use 'bool stereo' (less extensible, but then I don't think we'll ever support 5.1 sound :-)); fixed a bug in st_rate_flow where it sometimes would overflow the output buffer; made CopyRateConverter a template, too, increasing efficency
svn-id: r9239
Diffstat (limited to 'sound')
-rw-r--r--sound/audiostream.cpp32
-rw-r--r--sound/audiostream.h1
-rw-r--r--sound/rate.cpp69
-rw-r--r--sound/rate.h4
4 files changed, 60 insertions, 46 deletions
diff --git a/sound/audiostream.cpp b/sound/audiostream.cpp
index 1690d58fff..465e1122e5 100644
--- a/sound/audiostream.cpp
+++ b/sound/audiostream.cpp
@@ -22,7 +22,7 @@
#include "audiostream.h"
#include "mixer.h"
-template<int channels, int sampleSize>
+template<bool stereo, int sampleSize>
class LinearMemoryStream : public AudioInputStream {
protected:
const byte *_ptr;
@@ -31,14 +31,14 @@ protected:
public:
LinearMemoryStream(const byte *ptr, uint len) : _ptr(ptr), _end(ptr+len) { }
virtual int size() const { return (_end - _ptr) / sampleSize; }
- virtual bool isStereo() const { return channels == 2; }
+ virtual bool isStereo() const { return stereo; }
};
#if 0
TODO: Implement a wrapped memory stream, to be used by the ChannelStream class
(and possibly others?)
-template<int channels, int sampleSize>
+template<bool stereo, int sampleSize>
class WrappedMemoryStream : public AudioInputStream {
protected:
byte *_bufferStart;
@@ -47,7 +47,7 @@ protected:
byte *_end;
void advance() {
- _ptr += channels * sampleSize;
+ _ptr += sampleSize;
.. TODO: wrap
}
public:
@@ -56,7 +56,7 @@ public:
int size = _end - _pos;
if (size < 0)
size += _bufferEnd - _bufferStart
- return size / (channels * sampleSize);
+ return size / sampleSize;
}
void append(const byte *ptr, uint len) {
@@ -66,7 +66,7 @@ public:
#endif
-template<int channels, class T = class LinearMemoryStream<channels, 1> >
+template<bool stereo, class T = class LinearMemoryStream<stereo, 1> >
class Input8bitSignedStream : public T {
protected:
int16 readIntern() { int8 v = (int8)*_ptr; return v << 8; }
@@ -74,7 +74,7 @@ public:
Input8bitSignedStream(const byte *ptr, int len) : T(ptr, len) { }
};
-template<int channels, class T = class LinearMemoryStream<channels, 1> >
+template<bool stereo, class T = class LinearMemoryStream<stereo, 1> >
class Input8bitUnsignedStream : public T {
protected:
int16 readIntern() { int8 v = (int8)(*_ptr ^ 0x80); return v << 8; }
@@ -82,7 +82,7 @@ public:
Input8bitUnsignedStream(const byte *ptr, int len) : T(ptr, len) { }
};
-template<int channels, class T = class LinearMemoryStream<channels, 2> >
+template<bool stereo, class T = class LinearMemoryStream<stereo, 2> >
class Input16bitSignedStream : public T {
protected:
int16 readIntern() { return (int16)READ_BE_UINT16(_ptr); }
@@ -90,7 +90,7 @@ public:
Input16bitSignedStream(const byte *ptr, int len) : T(ptr, len) { }
};
-template<int channels, class T = class LinearMemoryStream<channels, 2> >
+template<bool stereo, class T = class LinearMemoryStream<stereo, 2> >
class Input16bitUnsignedStream : public T {
protected:
int16 readIntern() { return (int16)(READ_BE_UINT16(_ptr) ^ 0x8000); }
@@ -99,25 +99,25 @@ public:
};
-template<int channels>
+template<bool stereo>
static AudioInputStream *makeInputStream(const byte *ptr, uint32 len, bool isUnsigned, bool is16Bit) {
if (isUnsigned) {
if (is16Bit)
- return new Input16bitUnsignedStream<channels>(ptr, len);
+ return new Input16bitUnsignedStream<stereo>(ptr, len);
else
- return new Input8bitUnsignedStream<channels>(ptr, len);
+ return new Input8bitUnsignedStream<stereo>(ptr, len);
} else {
if (is16Bit)
- return new Input16bitSignedStream<channels>(ptr, len);
+ return new Input16bitSignedStream<stereo>(ptr, len);
else
- return new Input8bitSignedStream<channels>(ptr, len);
+ return new Input8bitSignedStream<stereo>(ptr, len);
}
}
AudioInputStream *makeInputStream(byte _flags, const byte *ptr, uint32 len) {
if (_flags & SoundMixer::FLAG_STEREO)
- return makeInputStream<2>(ptr, len, _flags & SoundMixer::FLAG_UNSIGNED, _flags & SoundMixer::FLAG_16BITS);
+ return makeInputStream<true>(ptr, len, _flags & SoundMixer::FLAG_UNSIGNED, _flags & SoundMixer::FLAG_16BITS);
else
- return makeInputStream<1>(ptr, len, _flags & SoundMixer::FLAG_UNSIGNED, _flags & SoundMixer::FLAG_16BITS);
+ return makeInputStream<false>(ptr, len, _flags & SoundMixer::FLAG_UNSIGNED, _flags & SoundMixer::FLAG_16BITS);
}
diff --git a/sound/audiostream.h b/sound/audiostream.h
index cb4e986124..b37a79b1e4 100644
--- a/sound/audiostream.h
+++ b/sound/audiostream.h
@@ -40,7 +40,6 @@ protected:
virtual void advance() = 0;
public:
int16 read() { assert(size() > 0); int16 val = readIntern(); advance(); return val; }
-// int16 peek() { assert(size() > 0); return readIntern(); }
virtual int size() const = 0;
bool eof() const { return size() <= 0; }
virtual bool isStereo() const = 0;
diff --git a/sound/rate.cpp b/sound/rate.cpp
index f62d20e536..7ee3683b6e 100644
--- a/sound/rate.cpp
+++ b/sound/rate.cpp
@@ -92,29 +92,36 @@ int st_rate_start(eff_t effp, st_rate_t inrate, st_rate_t outrate)
* Processed signed long samples from ibuf to obuf.
* Return number of samples processed.
*/
-template<int channels>
+template<bool stereo>
int st_rate_flow(eff_t effp, AudioInputStream &input, st_sample_t *obuf, st_size_t *osamp, st_volume_t vol)
{
rate_t rate = (rate_t) effp->priv;
st_sample_t *ostart, *oend;
st_sample_t ilast[2], icur[2], out;
unsigned long tmp;
- int i;
- assert(channels == 1 || channels == 2);
-
- for (i = 0; i < channels; i++)
- ilast[i] = rate->ilast[i];
+ ilast[0] = rate->ilast[0];
+ if (stereo)
+ ilast[1] = rate->ilast[1];
ostart = obuf;
oend = obuf + *osamp * 2;
+ if (stereo)
+ assert(input.size() % 2 == 0); // Stereo code assumes even number of input samples
+
+ // If the input position exceeds the output position, then we aborted the
+ // previous conversion run because the output buffer was full. Resume!
+ if (rate->ipos > rate->opos)
+ goto resume;
+
while (obuf < oend && !input.eof()) {
/* read enough input samples so that ipos > opos */
while (rate->ipos <= rate->opos) {
- for (i = 0; i < channels; i++)
- ilast[i] = input.read();
+ ilast[0] = input.read();
+ if (stereo)
+ ilast[1] = input.read();
rate->ipos++;
/* See if we finished the input buffer yet */
@@ -124,27 +131,31 @@ int st_rate_flow(eff_t effp, AudioInputStream &input, st_sample_t *obuf, st_size
// read the input sample(s)
icur[0] = input.read();
- if (channels == 2) {
- if (input.eof())
- goto the_end; // Shouldn't happen if data comes pair-wise
+ if (stereo)
icur[1] = input.read();
- }
- while (rate->ipos > rate->opos) {
- for (i = 0; i < channels; i++) {
+resume:
+ // Loop as long as the outpos trails behind, and as long as there is
+ // still space in the output buffer.
+ while (rate->ipos > rate->opos && obuf < oend) {
+
+ // interpolate
+ out = ilast[0] + (((icur[0] - ilast[0]) * rate->opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS);
+ // adjust volume
+ out = out * vol / 256;
+
+ // output left channel sample
+ clampedAdd(*obuf++, out);
+
+ if (stereo) {
// interpolate
- out = ilast[i] + (((icur[i] - ilast[i]) * rate->opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS);
-
+ out = ilast[1] + (((icur[1] - ilast[1]) * rate->opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS);
// adjust volume
out = out * vol / 256;
-
- // output left channel sample
- clampedAdd(*obuf++, out);
}
- // For mono input, repeat the sample to produce stereo output
- if (channels == 1)
- clampedAdd(*obuf++, out);
+ // output right channel sample
+ clampedAdd(*obuf++, out);
// Increment output position
tmp = rate->opos_frac + rate->opos_inc_frac;
@@ -154,14 +165,16 @@ int st_rate_flow(eff_t effp, AudioInputStream &input, st_sample_t *obuf, st_size
// Increment input position again (for the sample we read now)
rate->ipos++;
- for (i = 0; i < channels; i++)
- ilast[i] = icur[i];
+ ilast[0] = icur[0];
+ if (stereo)
+ ilast[1] = icur[1];
}
the_end:
*osamp = (obuf - ostart) / 2;
- for (i = 0; i < channels; i++)
- rate->ilast[i] = ilast[i];
+ rate->ilast[0] = ilast[0];
+ if (stereo)
+ rate->ilast[1] = ilast[1];
return (ST_SUCCESS);
}
@@ -175,9 +188,9 @@ LinearRateConverter::LinearRateConverter(st_rate_t inrate, st_rate_t outrate) {
int LinearRateConverter::flow(AudioInputStream &input, st_sample_t *obuf, st_size_t *osamp, st_volume_t vol) {
if (input.isStereo())
- return st_rate_flow<2>(&effp, input, obuf, osamp, vol);
+ return st_rate_flow<true>(&effp, input, obuf, osamp, vol);
else
- return st_rate_flow<1>(&effp, input, obuf, osamp, vol);
+ return st_rate_flow<false>(&effp, input, obuf, osamp, vol);
}
int LinearRateConverter::drain(st_sample_t *obuf, st_size_t *osamp, st_volume_t vol) {
diff --git a/sound/rate.h b/sound/rate.h
index 809042a8b2..72ae5a6021 100644
--- a/sound/rate.h
+++ b/sound/rate.h
@@ -81,15 +81,17 @@ public:
virtual int drain(st_sample_t *obuf, st_size_t *osamp, st_volume_t vol);
};
+template<bool stereo>
class CopyRateConverter : public RateConverter {
public:
virtual int flow(AudioInputStream &input, st_sample_t *obuf, st_size_t *osamp, st_volume_t vol) {
int16 tmp;
st_size_t len = *osamp;
+ assert(input.isStereo() == stereo);
while (!input.eof() && len--) {
tmp = input.read() * vol / 256;
clampedAdd(*obuf++, tmp);
- if (input.isStereo())
+ if (stereo)
tmp = input.read() * vol / 256;
clampedAdd(*obuf++, tmp);
}