diff options
-rw-r--r-- | sound/audiostream.h | 72 | ||||
-rw-r--r-- | sound/rate.cpp | 2 | ||||
-rw-r--r-- | sound/rate.h | 52 | ||||
-rw-r--r-- | sound/resample.cpp | 2 |
4 files changed, 107 insertions, 21 deletions
diff --git a/sound/audiostream.h b/sound/audiostream.h index c3d43d6b2a..a913e892a7 100644 --- a/sound/audiostream.h +++ b/sound/audiostream.h @@ -22,14 +22,19 @@ #ifndef AUDIOSTREAM_H #define AUDIOSTREAM_H +#include "mixer.h" + +// TODO: +// * maybe make readIntern return 16.16 or 24.8 fixed point values +// since MAD (and maybe OggVorbis?) gives us those -> higher quality. +// The rate converters should be able to deal with those just fine, too. +// * possibly add MADInputStream and VorbisInputStream + /** * Generic input stream for the resampling code. */ -class InputStream { -public: - byte *_ptr; - byte *_end; - InputStream(byte *ptr, uint len) : _ptr(ptr), _end(ptr+len) { } +class AudioInputStream { +protected: virtual int16 readIntern() = 0; virtual void advance() = 0; public: @@ -39,53 +44,86 @@ public: bool eof() { return size() <= 0; } }; -class ZeroInputStream : public InputStream { +class ZeroInputStream : public AudioInputStream { protected: + uint _len; int16 readIntern() { return 0; } - void advance() { _ptr++; } + void advance() { _len--; } public: - ZeroInputStream(uint len) : InputStream(0, len) { } - virtual int size() { return _end - _ptr; } + ZeroInputStream(uint len) : _len(len) { } + virtual int size() { return _len; } }; +class MemoryAudioInputStream : public AudioInputStream { +protected: + const byte *_ptr; + const byte *_end; +public: + MemoryAudioInputStream(const byte *ptr, uint len) : _ptr(ptr), _end(ptr+len) { } +}; + + template<int channels> -class Input8bitSignedStream : public InputStream { +class Input8bitSignedStream : public MemoryAudioInputStream { protected: int16 readIntern() { int8 v = (int8)*_ptr; return v << 8; } void advance() { _ptr += channels; } public: - Input8bitSignedStream(byte *ptr, int len) : InputStream(ptr, len) { } + Input8bitSignedStream(const byte *ptr, int len) : MemoryAudioInputStream(ptr, len) { } virtual int size() { return (_end - _ptr) / channels; } }; template<int channels> -class Input8bitUnsignedStream : public InputStream { +class Input8bitUnsignedStream : public MemoryAudioInputStream { protected: int16 readIntern() { int8 v = (int8)(*_ptr ^ 0x80); return v << 8; } void advance() { _ptr += channels; } public: - Input8bitUnsignedStream(byte *ptr, int len) : InputStream(ptr, len) { } + Input8bitUnsignedStream(const byte *ptr, int len) : MemoryAudioInputStream(ptr, len) { } virtual int size() { return (_end - _ptr) / channels; } }; template<int channels> -class Input16bitSignedStream : public InputStream { +class Input16bitSignedStream : public MemoryAudioInputStream { protected: int16 readIntern() { return (int16)READ_BE_UINT16(_ptr); } void advance() { _ptr += 2*channels; } public: - Input16bitSignedStream(byte *ptr, int len) : InputStream(ptr, len) { } + Input16bitSignedStream(const byte *ptr, int len) : MemoryAudioInputStream(ptr, len) { } virtual int size() { return (_end - _ptr) / (2 * channels); } }; template<int channels> -class Input16bitUnsignedStream : public InputStream { +class Input16bitUnsignedStream : public MemoryAudioInputStream { protected: int16 readIntern() { return (int16)(READ_BE_UINT16(_ptr) ^ 0x8000); } void advance() { _ptr += 2*channels; } public: - Input16bitUnsignedStream(byte *ptr, int len) : InputStream(ptr, len) { } + Input16bitUnsignedStream(const byte *ptr, int len) : MemoryAudioInputStream(ptr, len) { } virtual int size() { return (_end - _ptr) / (2 * channels); } }; + +template<int channels> +static AudioInputStream *makeInputStream(const byte *ptr, uint32 len, bool isUnsigned, bool is16Bit) { + if (isUnsigned) { + if (is16Bit) + return new Input16bitUnsignedStream<channels>(ptr, len); + else + return new Input8bitUnsignedStream<channels>(ptr, len); + } else { + if (is16Bit) + return new Input16bitSignedStream<channels>(ptr, len); + else + return new Input8bitSignedStream<channels>(ptr, len); + } +} + +static inline 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); + else + return makeInputStream<1>(ptr, len, _flags & SoundMixer::FLAG_UNSIGNED, _flags & SoundMixer::FLAG_16BITS); +} + #endif diff --git a/sound/rate.cpp b/sound/rate.cpp index bde477647a..dcbd25b8a2 100644 --- a/sound/rate.cpp +++ b/sound/rate.cpp @@ -104,7 +104,7 @@ 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. */ -int st_rate_flow(eff_t effp, InputStream &input, st_sample_t *obuf, st_size_t *osamp) +int st_rate_flow(eff_t effp, AudioInputStream &input, st_sample_t *obuf, st_size_t *osamp) { rate_t rate = (rate_t) effp->priv; st_sample_t *ostart, *oend; diff --git a/sound/rate.h b/sound/rate.h index aa8edea1b0..fb9ca40ad4 100644 --- a/sound/rate.h +++ b/sound/rate.h @@ -59,14 +59,62 @@ static inline void clampedAdd(int16& a, int b) { // Resample (high quality) int st_resample_getopts(eff_t effp, int n, char **argv); int st_resample_start(eff_t effp, st_rate_t inrate, st_rate_t outrate); -int st_resample_flow(eff_t effp, InputStream &input, st_sample_t *obuf, st_size_t *osamp); +int st_resample_flow(eff_t effp, AudioInputStream &input, st_sample_t *obuf, st_size_t *osamp); int st_resample_drain(eff_t effp, st_sample_t *obuf, st_size_t *osamp); int st_resample_stop(eff_t effp); // Rate (linear filter, low quality) int st_rate_getopts(eff_t effp, int n, char **argv); int st_rate_start(eff_t effp, st_rate_t inrate, st_rate_t outrate); -int st_rate_flow(eff_t effp, InputStream &input, st_sample_t *obuf, st_size_t *osamp); +int st_rate_flow(eff_t effp, AudioInputStream &input, st_sample_t *obuf, st_size_t *osamp); int st_rate_stop(eff_t effp); +#if 1 +class RateConverter { +protected: + eff_struct effp; +public: + RateConverter() {} + virtual ~RateConverter() {} + virtual int flow(AudioInputStream &input, st_sample_t *obuf, st_size_t *osamp) = 0; + virtual int drain(st_sample_t *obuf, st_size_t *osamp) = 0; +}; + +class LinearRateConverter : public RateConverter { +public: + LinearRateConverter(st_rate_t inrate, st_rate_t outrate) { + st_rate_getopts(&effp, 0, NULL); + st_rate_start(&effp, inrate, outrate); + } + ~LinearRateConverter() { + st_rate_stop(&effp); + } + virtual int flow(AudioInputStream &input, st_sample_t *obuf, st_size_t *osamp) { + return st_rate_flow(&effp, input, obuf, osamp); + } + virtual int drain(st_sample_t *obuf, st_size_t *osamp) { + return (ST_SUCCESS); + } +}; + +class ResampleRateConverter : public RateConverter { +public: + ResampleRateConverter(st_rate_t inrate, st_rate_t outrate) { + st_resample_getopts(&effp, 0, NULL); + st_resample_start(&effp, inrate, outrate); + } + ~ResampleRateConverter() { + st_resample_stop(&effp); + } + virtual int flow(AudioInputStream &input, st_sample_t *obuf, st_size_t *osamp) { + return st_resample_flow(&effp, input, obuf, osamp); + } + virtual int drain(st_sample_t *obuf, st_size_t *osamp) { + return st_resample_drain(&effp, obuf, osamp); + } +}; + +#endif + + #endif diff --git a/sound/resample.cpp b/sound/resample.cpp index 8dc63af6fb..825760236b 100644 --- a/sound/resample.cpp +++ b/sound/resample.cpp @@ -262,7 +262,7 @@ int st_resample_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. */ -int st_resample_flow(eff_t effp, InputStream &input, st_sample_t *obuf, st_size_t *osamp) { +int st_resample_flow(eff_t effp, AudioInputStream &input, st_sample_t *obuf, st_size_t *osamp) { resample_t r = (resample_t) effp->priv; long i, k, last; long Nout; // The number of bytes we effectively output |