diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/midiparser_smf.cpp | 25 | ||||
-rw-r--r-- | sound/midiparser_xmidi.cpp | 61 | ||||
-rw-r--r-- | sound/mixer.cpp | 83 | ||||
-rw-r--r-- | sound/mixer.h | 85 | ||||
-rw-r--r-- | sound/mixer_intern.h | 154 | ||||
-rw-r--r-- | sound/mp3.cpp | 2 | ||||
-rw-r--r-- | sound/softsynth/mt32.cpp | 28 |
7 files changed, 319 insertions, 119 deletions
diff --git a/sound/midiparser_smf.cpp b/sound/midiparser_smf.cpp index ed5007ecb7..89b7d3f525 100644 --- a/sound/midiparser_smf.cpp +++ b/sound/midiparser_smf.cpp @@ -85,16 +85,26 @@ void MidiParser_SMF::parseNextEvent(EventInfo &info) { _position._running_status = info.event; switch (info.command()) { - case 0xC: case 0xD: + case 0x9: // Note On + info.basic.param1 = *(_position._play_pos++); + info.basic.param2 = *(_position._play_pos++); + if (info.basic.param2 == 0) + info.event = info.channel() | 0x80; + info.length = 0; + break; + + case 0xC: + case 0xD: info.basic.param1 = *(_position._play_pos++); info.basic.param2 = 0; break; - case 0x8: case 0x9: case 0xA: case 0xB: case 0xE: + case 0x8: + case 0xA: + case 0xB: + case 0xE: info.basic.param1 = *(_position._play_pos++); info.basic.param2 = *(_position._play_pos++); - if (info.command() == 0x9 && info.basic.param2 == 0) - info.event = info.channel() | 0x80; info.length = 0; break; @@ -110,7 +120,12 @@ void MidiParser_SMF::parseNextEvent(EventInfo &info) { info.basic.param2 = 0; break; - case 0x6: case 0x8: case 0xA: case 0xB: case 0xC: case 0xE: + case 0x6: + case 0x8: + case 0xA: + case 0xB: + case 0xC: + case 0xE: info.basic.param1 = info.basic.param2 = 0; break; diff --git a/sound/midiparser_xmidi.cpp b/sound/midiparser_xmidi.cpp index d2aac49351..7cf114dcc6 100644 --- a/sound/midiparser_xmidi.cpp +++ b/sound/midiparser_xmidi.cpp @@ -38,6 +38,14 @@ protected: NoteTimer _notes_cache[32]; uint32 _inserted_delta; // Track simulated deltas for note-off events + struct Loop { + byte *pos; + byte repeat; + }; + + Loop _loop[4]; + int _loopCount; + protected: uint32 readVLQ2(byte * &data); void resetTracking(); @@ -78,16 +86,56 @@ void MidiParser_XMIDI::parseNextEvent(EventInfo &info) { } break; - case 0xC: case 0xD: + case 0xC: + case 0xD: info.basic.param1 = *(_position._play_pos++); info.basic.param2 = 0; break; - case 0x8: case 0xA: case 0xB: case 0xE: + case 0x8: + case 0xA: + case 0xE: info.basic.param1 = *(_position._play_pos++); info.basic.param2 = *(_position._play_pos++); break; + case 0xB: + info.basic.param1 = *(_position._play_pos++); + info.basic.param2 = *(_position._play_pos++); + + // Simplified XMIDI looping. + // + // I would really like to turn the loop events into some sort + // of NOP event (perhaps a dummy META event?), but for now we + // just pass them on to the MIDI driver. That has worked in the + // past, so it shouldn't cause any actual damage... + + if (info.basic.param1 == 0x74) { + // XMIDI_CONTROLLER_FOR_LOOP + byte *pos = _position._play_pos; + if (_loopCount < ARRAYSIZE(_loop) - 1) + _loopCount++; + + _loop[_loopCount].pos = pos; + _loop[_loopCount].repeat = info.basic.param2; + } else if (info.basic.param1 == 0x75) { + // XMIDI_CONTROLLER_NEXT_BREAK + if (_loopCount >= 0) { + if (info.basic.param2 < 64) { + // End the current loop. + _loopCount--; + } else { + _position._play_pos = _loop[_loopCount].pos; + // Repeat 0 means "loop forever". + if (_loop[_loopCount].repeat) { + if (--_loop[_loopCount].repeat == 0) + _loopCount--; + } + } + } + } + break; + case 0xF: // Meta or SysEx event switch (info.event & 0x0F) { case 0x2: // Song Position Pointer @@ -100,7 +148,12 @@ void MidiParser_XMIDI::parseNextEvent(EventInfo &info) { info.basic.param2 = 0; break; - case 0x6: case 0x8: case 0xA: case 0xB: case 0xC: case 0xE: + case 0x6: + case 0x8: + case 0xA: + case 0xB: + case 0xC: + case 0xE: info.basic.param1 = info.basic.param2 = 0; break; @@ -136,6 +189,8 @@ bool MidiParser_XMIDI::loadMusic(byte *data, uint32 size) { uint32 chunk_len; char buf[32]; + _loopCount = -1; + unloadMusic(); byte *pos = data; diff --git a/sound/mixer.cpp b/sound/mixer.cpp index fc5b21cf32..27e031f108 100644 --- a/sound/mixer.cpp +++ b/sound/mixer.cpp @@ -27,7 +27,7 @@ #include "common/util.h" #include "common/system.h" -#include "sound/mixer.h" +#include "sound/mixer_intern.h" #include "sound/rate.h" #include "sound/audiostream.h" @@ -103,32 +103,38 @@ public: #pragma mark - -Mixer::Mixer() { - _syst = g_system; +MixerImpl::MixerImpl(OSystem *system) + : _syst(system), _sampleRate(0), _mixerReady(false), _handleSeed(0) { - _handleSeed = 0; - - int i = 0; + int i; for (i = 0; i < ARRAYSIZE(_volumeForSoundType); i++) _volumeForSoundType[i] = kMaxMixerVolume; for (i = 0; i != NUM_CHANNELS; i++) _channels[i] = 0; - - _mixerReady = false; } -Mixer::~Mixer() { +MixerImpl::~MixerImpl() { for (int i = 0; i != NUM_CHANNELS; i++) delete _channels[i]; } -uint Mixer::getOutputRate() const { - return (uint)_syst->getOutputSampleRate(); +void MixerImpl::setReady(bool ready) { + _mixerReady = ready; +} + +uint MixerImpl::getOutputRate() const { + return _sampleRate; +} + +void MixerImpl::setOutputRate(uint sampleRate) { + if (_sampleRate != 0 && _sampleRate != sampleRate) + error("Changing the Audio::Mixer output sample rate is not supported"); + _sampleRate = sampleRate; } -void Mixer::insertChannel(SoundHandle *handle, Channel *chan) { +void MixerImpl::insertChannel(SoundHandle *handle, Channel *chan) { int index = -1; for (int i = 0; i != NUM_CHANNELS; i++) { @@ -138,7 +144,7 @@ void Mixer::insertChannel(SoundHandle *handle, Channel *chan) { } } if (index == -1) { - warning("Mixer::out of mixer slots"); + warning("MixerImpl::out of mixer slots"); delete chan; return; } @@ -151,7 +157,7 @@ void Mixer::insertChannel(SoundHandle *handle, Channel *chan) { } } -void Mixer::playRaw( +void MixerImpl::playRaw( SoundType type, SoundHandle *handle, void *sound, @@ -166,7 +172,7 @@ void Mixer::playRaw( playInputStream(type, handle, input, id, volume, balance, true, false, ((flags & Mixer::FLAG_REVERSE_STEREO) != 0)); } -void Mixer::playInputStream( +void MixerImpl::playInputStream( SoundType type, SoundHandle *handle, AudioStream *input, @@ -198,8 +204,13 @@ void Mixer::playInputStream( insertChannel(handle, chan); } -void Mixer::mix(int16 *buf, uint len) { +void MixerImpl::mixCallback(byte *samples, uint len) { + assert(samples); + Common::StackLock lock(_mutex); + + int16 *buf = (int16 *)samples; + len >>= 2; // Since the mixer callback has been called, the mixer must be ready... _mixerReady = true; @@ -218,15 +229,7 @@ void Mixer::mix(int16 *buf, uint len) { } } -void Mixer::mixCallback(void *s, byte *samples, int len) { - assert(s); - assert(samples); - // Len is the number of bytes in the buffer; we divide it by - // four to get the number of samples (stereo 16 bit). - ((Mixer *)s)->mix((int16 *)samples, len >> 2); -} - -void Mixer::stopAll() { +void MixerImpl::stopAll() { Common::StackLock lock(_mutex); for (int i = 0; i != NUM_CHANNELS; i++) { if (_channels[i] != 0 && !_channels[i]->isPermanent()) { @@ -236,7 +239,7 @@ void Mixer::stopAll() { } } -void Mixer::stopID(int id) { +void MixerImpl::stopID(int id) { Common::StackLock lock(_mutex); for (int i = 0; i != NUM_CHANNELS; i++) { if (_channels[i] != 0 && _channels[i]->getId() == id) { @@ -246,7 +249,7 @@ void Mixer::stopID(int id) { } } -void Mixer::stopHandle(SoundHandle handle) { +void MixerImpl::stopHandle(SoundHandle handle) { Common::StackLock lock(_mutex); // Simply ignore stop requests for handles of sounds that already terminated @@ -258,7 +261,7 @@ void Mixer::stopHandle(SoundHandle handle) { _channels[index] = 0; } -void Mixer::setChannelVolume(SoundHandle handle, byte volume) { +void MixerImpl::setChannelVolume(SoundHandle handle, byte volume) { Common::StackLock lock(_mutex); const int index = handle._val % NUM_CHANNELS; @@ -268,7 +271,7 @@ void Mixer::setChannelVolume(SoundHandle handle, byte volume) { _channels[index]->setVolume(volume); } -void Mixer::setChannelBalance(SoundHandle handle, int8 balance) { +void MixerImpl::setChannelBalance(SoundHandle handle, int8 balance) { Common::StackLock lock(_mutex); const int index = handle._val % NUM_CHANNELS; @@ -278,7 +281,7 @@ void Mixer::setChannelBalance(SoundHandle handle, int8 balance) { _channels[index]->setBalance(balance); } -uint32 Mixer::getSoundElapsedTime(SoundHandle handle) { +uint32 MixerImpl::getSoundElapsedTime(SoundHandle handle) { Common::StackLock lock(_mutex); const int index = handle._val % NUM_CHANNELS; @@ -288,7 +291,7 @@ uint32 Mixer::getSoundElapsedTime(SoundHandle handle) { return _channels[index]->getElapsedTime(); } -void Mixer::pauseAll(bool paused) { +void MixerImpl::pauseAll(bool paused) { Common::StackLock lock(_mutex); for (int i = 0; i != NUM_CHANNELS; i++) { if (_channels[i] != 0) { @@ -297,7 +300,7 @@ void Mixer::pauseAll(bool paused) { } } -void Mixer::pauseID(int id, bool paused) { +void MixerImpl::pauseID(int id, bool paused) { Common::StackLock lock(_mutex); for (int i = 0; i != NUM_CHANNELS; i++) { if (_channels[i] != 0 && _channels[i]->getId() == id) { @@ -307,7 +310,7 @@ void Mixer::pauseID(int id, bool paused) { } } -void Mixer::pauseHandle(SoundHandle handle, bool paused) { +void MixerImpl::pauseHandle(SoundHandle handle, bool paused) { Common::StackLock lock(_mutex); // Simply ignore (un)pause requests for sounds that already terminated @@ -318,7 +321,7 @@ void Mixer::pauseHandle(SoundHandle handle, bool paused) { _channels[index]->pause(paused); } -bool Mixer::isSoundIDActive(int id) { +bool MixerImpl::isSoundIDActive(int id) { Common::StackLock lock(_mutex); for (int i = 0; i != NUM_CHANNELS; i++) if (_channels[i] && _channels[i]->getId() == id) @@ -326,7 +329,7 @@ bool Mixer::isSoundIDActive(int id) { return false; } -int Mixer::getSoundID(SoundHandle handle) { +int MixerImpl::getSoundID(SoundHandle handle) { Common::StackLock lock(_mutex); const int index = handle._val % NUM_CHANNELS; if (_channels[index] && _channels[index]->_handle._val == handle._val) @@ -334,13 +337,13 @@ int Mixer::getSoundID(SoundHandle handle) { return 0; } -bool Mixer::isSoundHandleActive(SoundHandle handle) { +bool MixerImpl::isSoundHandleActive(SoundHandle handle) { Common::StackLock lock(_mutex); const int index = handle._val % NUM_CHANNELS; return _channels[index] && _channels[index]->_handle._val == handle._val; } -bool Mixer::hasActiveChannelOfType(SoundType type) { +bool MixerImpl::hasActiveChannelOfType(SoundType type) { Common::StackLock lock(_mutex); for (int i = 0; i != NUM_CHANNELS; i++) if (_channels[i] && _channels[i]->_type == type) @@ -348,7 +351,7 @@ bool Mixer::hasActiveChannelOfType(SoundType type) { return false; } -void Mixer::setVolumeForSoundType(SoundType type, int volume) { +void MixerImpl::setVolumeForSoundType(SoundType type, int volume) { assert(0 <= type && type < ARRAYSIZE(_volumeForSoundType)); // Check range @@ -363,7 +366,7 @@ void Mixer::setVolumeForSoundType(SoundType type, int volume) { _volumeForSoundType[type] = volume; } -int Mixer::getVolumeForSoundType(SoundType type) const { +int MixerImpl::getVolumeForSoundType(SoundType type) const { assert(0 <= type && type < ARRAYSIZE(_volumeForSoundType)); return _volumeForSoundType[type]; @@ -443,7 +446,7 @@ uint32 Channel::getElapsedTime() { // Convert the number of samples into a time duration. To avoid // overflow, this has to be done in a somewhat non-obvious way. - uint rate = _mixer->getOutputRate(); + uint32 rate = _mixer->getOutputRate(); uint32 seconds = _samplesConsumed / rate; uint32 milliseconds = (1000 * (_samplesConsumed % rate)) / rate; diff --git a/sound/mixer.h b/sound/mixer.h index 26ae0898fd..28988256b3 100644 --- a/sound/mixer.h +++ b/sound/mixer.h @@ -38,6 +38,7 @@ namespace Audio { class AudioStream; class Channel; class Mixer; +class MixerImpl; /** * A SoundHandle instances corresponds to a specific sound @@ -47,7 +48,7 @@ class Mixer; */ class SoundHandle { friend class Channel; - friend class Mixer; + friend class MixerImpl; uint32 _val; public: inline SoundHandle() : _val(0xFFFFFFFF) {} @@ -104,24 +105,9 @@ public: kMaxMixerVolume = 256 }; -private: - enum { - NUM_CHANNELS = 16 - }; - - OSystem *_syst; - Common::Mutex _mutex; - - int _volumeForSoundType[4]; - - uint32 _handleSeed; - Channel *_channels[NUM_CHANNELS]; - - bool _mixerReady; - public: - Mixer(); - ~Mixer(); + Mixer() {} + virtual ~Mixer() {} @@ -132,8 +118,10 @@ public: * sync with an audio stream. In particular, the Adlib MIDI emulation... * * @return whether the mixer is ready and setup + * + * @todo get rid of this? */ - bool isReady() const { return _mixerReady; } + virtual bool isReady() const = 0; @@ -143,12 +131,12 @@ public: * (using the makeLinearInputStream factory function), which is then * passed on to playInputStream. */ - void playRaw( + virtual void playRaw( SoundType type, SoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, int id = -1, byte volume = kMaxChannelVolume, int8 balance = 0, - uint32 loopStart = 0, uint32 loopEnd = 0); + uint32 loopStart = 0, uint32 loopEnd = 0) = 0; /** * Start playing the given audio input stream. @@ -170,35 +158,35 @@ public: * not stop this particular stream * @param reverseStereo a flag indicating whether left and right channels shall be swapped */ - void playInputStream( + virtual void playInputStream( SoundType type, SoundHandle *handle, AudioStream *input, int id = -1, byte volume = kMaxChannelVolume, int8 balance = 0, bool autofreeStream = true, bool permanent = false, - bool reverseStereo = false); + bool reverseStereo = false) = 0; /** * Stop all currently playing sounds. */ - void stopAll(); + virtual void stopAll() = 0; /** * Stop playing the sound with given ID. * * @param id the ID of the sound to affect */ - void stopID(int id); + virtual void stopID(int id) = 0; /** * Stop playing the sound corresponding to the given handle. * * @param handle the sound to affect */ - void stopHandle(SoundHandle handle); + virtual void stopHandle(SoundHandle handle) = 0; @@ -208,7 +196,7 @@ public: * * @param paused true to pause everything, false to unpause */ - void pauseAll(bool paused); + virtual void pauseAll(bool paused) = 0; /** * Pause/unpause the sound with the given ID. @@ -216,7 +204,7 @@ public: * @param id the ID of the sound to affect * @param paused true to pause the sound, false to unpause it */ - void pauseID(int id, bool paused); + virtual void pauseID(int id, bool paused) = 0; /** * Pause/unpause the sound corresponding to the given handle. @@ -224,7 +212,7 @@ public: * @param handle the sound to affect * @param paused true to pause the sound, false to unpause it */ - void pauseHandle(SoundHandle handle, bool paused); + virtual void pauseHandle(SoundHandle handle, bool paused) = 0; @@ -234,7 +222,7 @@ public: * @param id the ID of the sound to query * @return true if the sound is active */ - bool isSoundIDActive(int id); + virtual bool isSoundIDActive(int id) = 0; /** * Get the sound ID of handle sound @@ -242,7 +230,7 @@ public: * @param handle sound to query * @return sound ID if active */ - int getSoundID(SoundHandle handle); + virtual int getSoundID(SoundHandle handle) = 0; /** * Check if a sound with the given handle is active. @@ -250,7 +238,7 @@ public: * @param handle sound to query * @return true if the sound is active */ - bool isSoundHandleActive(SoundHandle handle); + virtual bool isSoundHandleActive(SoundHandle handle) = 0; @@ -260,7 +248,7 @@ public: * @param handle the sound to affect * @param volume the new channel volume (0 - kMaxChannelVolume) */ - void setChannelVolume(SoundHandle handle, byte volume); + virtual void setChannelVolume(SoundHandle handle, byte volume) = 0; /** * Set the channel balance for the given handle. @@ -269,12 +257,12 @@ public: * @param balance the new channel balance: * (-127 ... 0 ... 127) corresponds to (left ... center ... right) */ - void setChannelBalance(SoundHandle handle, int8 balance); + virtual void setChannelBalance(SoundHandle handle, int8 balance) = 0; /** * Get approximation of for how long the channel has been playing. */ - uint32 getSoundElapsedTime(SoundHandle handle); + virtual uint32 getSoundElapsedTime(SoundHandle handle) = 0; /** * Check whether any channel of the given sound type is active. @@ -284,7 +272,7 @@ public: * @param type the sound type to look for * @return true if any channels of the specified type are active. */ - bool hasActiveChannelOfType(SoundType type); + virtual bool hasActiveChannelOfType(SoundType type) = 0; /** * Set the volume for the given sound type. @@ -292,7 +280,7 @@ public: * @param type the sound type * @param volume the new global volume, 0 - kMaxMixerVolume */ - void setVolumeForSoundType(SoundType type, int volume); + virtual void setVolumeForSoundType(SoundType type, int volume) = 0; /** * Query the global volume. @@ -300,7 +288,7 @@ public: * @param type the sound type * @return the global music volume, 0 - kMaxMixerVolume */ - int getVolumeForSoundType(SoundType type) const; + virtual int getVolumeForSoundType(SoundType type) const = 0; /** * Query the system's audio output sample rate. This returns @@ -308,26 +296,7 @@ public: * * @return the output sample rate in Hz */ - uint getOutputRate() const; - -protected: - void insertChannel(SoundHandle *handle, Channel *chan); - - /** - * Internal main method -- all the actual mixing work is done from here. - */ - void mix(int16 * buf, uint len); - - // FIXME: temporary "public" to allow access to mixCallback - // from within OSystem::makeMixer() -public: - /** - * The mixer callback function, passed on to OSystem::setSoundCallback(). - * This simply calls the mix() method. - */ - static void mixCallback(void *s, byte *samples, int len); - - void setReady(bool ready) { _mixerReady = ready; } + virtual uint getOutputRate() const = 0; }; diff --git a/sound/mixer_intern.h b/sound/mixer_intern.h new file mode 100644 index 0000000000..46ba97e66c --- /dev/null +++ b/sound/mixer_intern.h @@ -0,0 +1,154 @@ +/* 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 SOUND_MIXER_INTERN_H +#define SOUND_MIXER_INTERN_H + +#include "common/scummsys.h" +#include "common/mutex.h" +#include "sound/mixer.h" + +namespace Audio { + +/** + * The (default) implementation of the ScummVM audio mixing subsystem. + * + * Backends are responsible for allocating (and later releasing) an instance + * of this class, which engines can access via OSystem::getMixer(). + * + * Initialisation of instances of this class usually happens as follows: + * 1) Creat a new Audio::MixerImpl instance. + * 2) Set the hardware output sample rate via the setSampleRate() method. + * 3) Hook up the mixCallback() in a suitable audio processing thread/callback. + * 4) Change the mixer into ready mode via setReady(true). + * 5) Start audio processing (e.g. by resuming the audio thread, if applicable). + * + * In the future, we might make it possible for backends to provide + * (partial) alternative implementations of the mixer, e.g. to make + * better use of native sound mixing support on low-end devices. + * + * @see OSystem::getMixer() + */ +class MixerImpl : public Mixer { +private: + enum { + NUM_CHANNELS = 16 + }; + + OSystem *_syst; + Common::Mutex _mutex; + + uint _sampleRate; + bool _mixerReady; + uint32 _handleSeed; + + int _volumeForSoundType[4]; + Channel *_channels[NUM_CHANNELS]; + + +public: + MixerImpl(OSystem *system); + ~MixerImpl(); + + virtual bool isReady() const { return _mixerReady; } + + virtual void playRaw( + SoundType type, + SoundHandle *handle, + void *sound, uint32 size, uint rate, byte flags, + int id = -1, byte volume = 255, int8 balance = 0, + uint32 loopStart = 0, uint32 loopEnd = 0); + + virtual void playInputStream( + SoundType type, + SoundHandle *handle, + AudioStream *input, + int id = -1, byte volume = 255, int8 balance = 0, + bool autofreeStream = true, + bool permanent = false, + bool reverseStereo = false); + + + + virtual void stopAll(); + virtual void stopID(int id); + virtual void stopHandle(SoundHandle handle); + + virtual void pauseAll(bool paused); + virtual void pauseID(int id, bool paused); + virtual void pauseHandle(SoundHandle handle, bool paused); + + virtual bool isSoundIDActive(int id); + virtual int getSoundID(SoundHandle handle); + + virtual bool isSoundHandleActive(SoundHandle handle); + + virtual void setChannelVolume(SoundHandle handle, byte volume); + virtual void setChannelBalance(SoundHandle handle, int8 balance); + + virtual uint32 getSoundElapsedTime(SoundHandle handle); + + virtual bool hasActiveChannelOfType(SoundType type); + + virtual void setVolumeForSoundType(SoundType type, int volume); + virtual int getVolumeForSoundType(SoundType type) const; + + virtual uint getOutputRate() const; + +protected: + void insertChannel(SoundHandle *handle, Channel *chan); + +public: + /** + * The mixer callback function, to be called at regular intervals by + * the backend (e.g. from an audio mixing thread). All the actual mixing + * work is done from here. + */ + void mixCallback(byte *samples, uint len); + + /** + * Set the internal 'is ready' flag of the mixer. + * Backends should invoke Mixer::setReady(true) once initialisation of + * their audio system has been completed (and in particular, *after* + * setOutputRate() has been called). + */ + void setReady(bool ready); + + /** + * Set the output sample rate. + * + * @param sampleRate the new output sample rate + * + * @note Right now, this can be done exactly ONCE. That is, the mixer + * currently does not support changing the output sample rate after it + * has been set for the first time. This may change in the future. + */ + void setOutputRate(uint sampleRate); +}; + + +} // End of namespace Audio + +#endif diff --git a/sound/mp3.cpp b/sound/mp3.cpp index eea725ce3a..70467bdb39 100644 --- a/sound/mp3.cpp +++ b/sound/mp3.cpp @@ -121,7 +121,7 @@ MP3InputStream::MP3InputStream(Common::SeekableReadStream *inStream, bool dispos mad_timer_add(&length, start); mad_timer_negate(&length); - if (mad_timer_sign(end) == 0) { + if (mad_timer_sign(end) != 0) { mad_timer_add(&length, end); } else { mad_stream_init(&_stream); diff --git a/sound/softsynth/mt32.cpp b/sound/softsynth/mt32.cpp index 053df544b1..360ef4539d 100644 --- a/sound/softsynth/mt32.cpp +++ b/sound/softsynth/mt32.cpp @@ -80,37 +80,41 @@ public: }; class MT32File : public MT32Emu::File { - Common::File file; + Common::File _in; + Common::DumpFile _out; public: bool open(const char *filename, OpenMode mode) { - Common::File::AccessMode accessMode = mode == OpenMode_read ? Common::File::kFileReadMode : Common::File::kFileWriteMode; - return file.open(filename, accessMode); + if (mode == OpenMode_read) + return _in.open(filename); + else + return _out.open(filename); } void close() { - return file.close(); + _in.close(); + _out.close(); } size_t read(void *in, size_t size) { - return file.read(in, size); + return _in.read(in, size); } bool readLine(char *in, size_t size) { - return file.readLine(in, size) != NULL; + return _in.readLine(in, size) != NULL; } bool readBit8u(MT32Emu::Bit8u *in) { - byte b = file.readByte(); - if (file.eof()) + byte b = _in.readByte(); + if (_in.eof()) return false; *in = b; return true; } size_t write(const void *in, size_t size) { - return file.write(in, size); + return _out.write(in, size); } bool writeBit8u(MT32Emu::Bit8u out) { - file.writeByte(out); - return !file.ioFailed(); + _out.writeByte(out); + return !_out.ioFailed(); } bool isEOF() { - return file.eof(); + return _in.isOpen() ? _in.eof() : _out.eof(); } }; |