diff --git a/sound/audiostream.cpp b/sound/audiostream.cpp index 6fc99cc4f0e..3f66ebfce99 100644 --- a/sound/audiostream.cpp +++ b/sound/audiostream.cpp @@ -302,42 +302,6 @@ void AppendableMemoryStream::append(const byt } } -#pragma mark - -#pragma mark --- Procedural stream --- -#pragma mark - - - -#if 0 -// Work in progress!!! Not yet usable/finished/working/anything :-) - -class ProcInputStream : public AudioStream { -public: - typedef void InputProc (void *refCon, int16 *data, uint len); - -private: - const int _rate; - const bool _isStereo; - InputProc *_proc; - void *_refCon; - -public: - ProcInputStream(int rate, bool stereo, InputProc *proc, void *refCon) - : _rate(rate), _isStereo(stereo), _proc(proc), _refCon(refCon) { } - int readBuffer(int16 *buffer, const int numSamples) { - (_proc)(_refCon, buffer, numSamples); - return numSamples; - } - int16 read() { - int16 sample; - (_proc)(_refCon, &sample, 1); - return sample; - } - bool isStereo() const { return _isStereo; } - bool endOfData() const { return false; } - - int getRate() const { return _rate; } -}; -#endif #pragma mark - #pragma mark --- Input stream factories --- diff --git a/sound/mixer.cpp b/sound/mixer.cpp index 954e7e15b45..1849ab3f489 100644 --- a/sound/mixer.cpp +++ b/sound/mixer.cpp @@ -98,6 +98,43 @@ public: void finish(); }; + +#pragma mark - +#pragma mark --- Procedural stream --- +#pragma mark - + + +class ProcInputStream : public AudioStream { +public: + typedef void (*InputProc)(void *refCon, int16 *data, uint len); + +private: + const int _rate; + const bool _isStereo; + InputProc _proc; + void *_refCon; + +public: + ProcInputStream(int rate, bool stereo, InputProc proc, void *refCon) + : _rate(rate), _isStereo(stereo), _proc(proc), _refCon(refCon) { } + int readBuffer(int16 *buffer, const int numSamples) { + memset(buffer, 0, 2 * numSamples); // FIXME + (_proc)(_refCon, buffer, _isStereo ? (numSamples / 2) : numSamples); + return numSamples; + } + int16 read() { + error("ProcInputStream::read not supported"); + int16 sample[2] = { 0, 0 }; + (_proc)(_refCon, sample, 1); + return sample[0]; + } + bool isStereo() const { return _isStereo; } + bool endOfData() const { return false; } + + int getRate() const { return _rate; } +}; + + #pragma mark - #pragma mark --- SoundMixer --- #pragma mark - @@ -107,8 +144,7 @@ SoundMixer::SoundMixer() { _syst = OSystem::instance(); _mutex = _syst->createMutex(); - _premixParam = 0; - _premixProc = 0; + _premixChannel = 0; int i = 0; _globalVolume = 0; @@ -131,6 +167,10 @@ SoundMixer::SoundMixer() { SoundMixer::~SoundMixer() { _syst->clearSoundCallback(); stopAll(); + + delete _premixChannel; + _premixChannel = 0; + _syst->deleteMutex(_mutex); } @@ -140,8 +180,31 @@ bool SoundMixer::isPaused() { void SoundMixer::setupPremix(PremixProc *proc, void *param) { Common::StackLock lock(_mutex); - _premixParam = param; - _premixProc = proc; + + delete _premixChannel; + _premixChannel = 0; + + if (proc == 0) + return; + + // Create an input stream + AudioStream *input = new ProcInputStream(_outputRate, true, proc, param); + + // Create the channel + _premixChannel = new Channel(this, 0, input, true, false); +} + +void SoundMixer::setupPremix(AudioStream *stream) { + Common::StackLock lock(_mutex); + + delete _premixChannel; + _premixChannel = 0; + + if (stream == 0) + return; + + // Create the channel + _premixChannel = new Channel(this, 0, stream, false, false); } void SoundMixer::newStream(PlayingSoundHandle *handle, uint rate, byte flags, uint32 buffer_size, byte volume, int8 balance) { @@ -315,8 +378,8 @@ void SoundMixer::mix(int16 *buf, uint len) { memset(buf, 0, 2 * len * sizeof(int16)); if (!_paused) { - if (_premixProc) - _premixProc(_premixParam, buf, len); + if (_premixChannel) + _premixChannel->mix(buf, len); // now mix all channels for (int i = 0; i != NUM_CHANNELS; i++) diff --git a/sound/mixer.h b/sound/mixer.h index d2093ec5608..523e47fb6fb 100644 --- a/sound/mixer.h +++ b/sound/mixer.h @@ -66,8 +66,7 @@ private: OSystem *_syst; OSystem::MutexRef _mutex; - void *_premixParam; - PremixProc *_premixProc; + Channel *_premixChannel; uint _outputRate; @@ -96,13 +95,24 @@ public: * Set the premix procedure. This is mainly used for the adlib music, but * is not limited to it. The premix proc is invoked by the mixer whenever * it needs to generate any data, before any other mixing takes place. The - * premixer than has a chanve to fill the mix buffer with data (usually + * premixer than has a chance to fill the mix buffer with data (usually * music samples). It should generate the specified number of 16bit stereo * samples (i.e. len * 4 bytes). The endianness of these samples shall be * the native endianness. + * + * @obsolete Instead of this, use the other setupPremix method which + * takes an AudioStream. */ void setupPremix(PremixProc *proc, void *param); + /** + * Set the premix stream. This is mainly used for the adlib music, but + * is not limited to it. The premix stream is invoked by the mixer whenever + * it needs to generate any data, before any other mixing takes place. + */ + void setupPremix(AudioStream *stream); + + // start playing a raw sound void playRaw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, int id = -1, byte volume = 255, int8 balance = 0, uint32 loopStart = 0, uint32 loopEnd = 0);