/* 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. * */ #ifndef AUDIO_MIXER_INTERN_H #define AUDIO_MIXER_INTERN_H #include "common/scummsys.h" #include "common/mutex.h" #include "audio/mixer.h" namespace Audio { /** * @defgroup audio_mixer_intern Mixer implementation * @ingroup audio * * @brief The (default) implementation of the ScummVM audio mixing subsystem. * @{ */ /** * 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 = 32 }; Common::Mutex _mutex; const uint _sampleRate; bool _mixerReady; uint32 _handleSeed; struct SoundTypeSettings { SoundTypeSettings() : mute(false), volume(kMaxMixerVolume) {} bool mute; int volume; }; SoundTypeSettings _soundTypeSettings[4]; Channel *_channels[NUM_CHANNELS]; public: MixerImpl(uint sampleRate); ~MixerImpl(); virtual bool isReady() const { Common::StackLock lock(_mutex); return _mixerReady; } virtual void playStream( SoundType type, SoundHandle *handle, AudioStream *input, int id, byte volume, int8 balance, DisposeAfterUse::Flag autofreeStream, bool permanent, bool reverseStereo); 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 muteSoundType(SoundType type, bool mute); virtual bool isSoundTypeMuted(SoundType type) const; virtual void setChannelVolume(SoundHandle handle, byte volume); virtual byte getChannelVolume(SoundHandle handle); virtual void setChannelBalance(SoundHandle handle, int8 balance); virtual int8 getChannelBalance(SoundHandle handle); virtual uint32 getSoundElapsedTime(SoundHandle handle); virtual Timestamp getElapsedTime(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. * * @param samples Sample buffer, in which stereo 16-bit samples will be stored. * @param len Length of the provided buffer to fill (in bytes, should be divisible by 4). * @return number of sample pairs processed (which can still be silence!) */ int 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. */ void setReady(bool ready); }; /** @} */ } // End of namespace Audio #endif