From 9e051fa5070cd70ff0e69faa647ad26f66b64560 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jul 2003 11:13:01 +0000 Subject: 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 --- sound/audiostream.cpp | 32 ++++++++++++------------ sound/audiostream.h | 1 - sound/rate.cpp | 69 ++++++++++++++++++++++++++++++--------------------- sound/rate.h | 4 ++- 4 files changed, 60 insertions(+), 46 deletions(-) (limited to 'sound') 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 +template 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 +template 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 > +template > 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 > +template > 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 > +template > 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 > +template > class Input16bitUnsignedStream : public T { protected: int16 readIntern() { return (int16)(READ_BE_UINT16(_ptr) ^ 0x8000); } @@ -99,25 +99,25 @@ public: }; -template +template static AudioInputStream *makeInputStream(const byte *ptr, uint32 len, bool isUnsigned, bool is16Bit) { if (isUnsigned) { if (is16Bit) - return new Input16bitUnsignedStream(ptr, len); + return new Input16bitUnsignedStream(ptr, len); else - return new Input8bitUnsignedStream(ptr, len); + return new Input8bitUnsignedStream(ptr, len); } else { if (is16Bit) - return new Input16bitSignedStream(ptr, len); + return new Input16bitSignedStream(ptr, len); else - return new Input8bitSignedStream(ptr, len); + return new Input8bitSignedStream(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(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(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 +template 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(&effp, input, obuf, osamp, vol); else - return st_rate_flow<1>(&effp, input, obuf, osamp, vol); + return st_rate_flow(&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 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); } -- cgit v1.2.3