Ticket #8862: mixer-rev.patch

File mixer-rev.patch, 37.3 KB (added by fingolfin, 16 years ago)
  • common/system.h

     
    810810         */
    811811        virtual Audio::Mixer *getMixer() = 0;
    812812
    813         /**
    814          * Determine the output sample rate. Audio data provided by the sound
    815          * callback will be played using this rate.
    816          * @note Client code other than the sound mixer should _not_ use this
    817          *       method. Instead, call Mixer::getOutputRate()!
    818          * @return the output sample rate
    819          */
    820         virtual int getOutputSampleRate() const = 0;
    821 
    822813        //@}
    823814
    824815
  • sound/mixer.cpp

     
    2727#include "common/util.h"
    2828#include "common/system.h"
    2929
    30 #include "sound/mixer.h"
     30#include "sound/mixer_intern.h"
    3131#include "sound/rate.h"
    3232#include "sound/audiostream.h"
    3333
     
    103103#pragma mark -
    104104
    105105
    106 Mixer::Mixer() {
    107         _syst = g_system;
     106MixerImpl::MixerImpl(OSystem *system)
     107        : _syst(system), _sampleRate(0), _mixerReady(false), _handleSeed(0) {
    108108
    109         _handleSeed = 0;
     109        int i;
    110110
    111         int i = 0;
    112 
    113111        for (i = 0; i < ARRAYSIZE(_volumeForSoundType); i++)
    114112                _volumeForSoundType[i] = kMaxMixerVolume;
    115113
    116114        for (i = 0; i != NUM_CHANNELS; i++)
    117115                _channels[i] = 0;
    118 
    119         _mixerReady = false;
    120116}
    121117
    122 Mixer::~Mixer() {
     118MixerImpl::~MixerImpl() {
    123119        for (int i = 0; i != NUM_CHANNELS; i++)
    124120                delete _channels[i];
    125121}
    126122
    127 uint Mixer::getOutputRate() const {
    128         return (uint)_syst->getOutputSampleRate();
     123void MixerImpl::setReady(bool ready) {
     124        _mixerReady = ready;
    129125}
    130126
    131 void Mixer::insertChannel(SoundHandle *handle, Channel *chan) {
     127uint MixerImpl::getOutputRate() const {
     128        return _sampleRate;
     129}
    132130
     131void MixerImpl::setOutputRate(uint sampleRate) {
     132        if (_sampleRate != 0 && _sampleRate != sampleRate)
     133                error("Changing the Audio::Mixer output sample rate is not supported");
     134        _sampleRate = sampleRate;
     135}
     136
     137void MixerImpl::insertChannel(SoundHandle *handle, Channel *chan) {
     138
    133139        int index = -1;
    134140        for (int i = 0; i != NUM_CHANNELS; i++) {
    135141                if (_channels[i] == 0) {
     
    138144                }
    139145        }
    140146        if (index == -1) {
    141                 warning("Mixer::out of mixer slots");
     147                warning("MixerImpl::out of mixer slots");
    142148                delete chan;
    143149                return;
    144150        }
     
    151157        }
    152158}
    153159
    154 void Mixer::playRaw(
     160void MixerImpl::playRaw(
    155161                        SoundType type,
    156162                        SoundHandle *handle,
    157163                        void *sound,
     
    166172        playInputStream(type, handle, input, id, volume, balance, true, false, ((flags & Mixer::FLAG_REVERSE_STEREO) != 0));
    167173}
    168174
    169 void Mixer::playInputStream(
     175void MixerImpl::playInputStream(
    170176                        SoundType type,
    171177                        SoundHandle *handle,
    172178                        AudioStream *input,
     
    198204        insertChannel(handle, chan);
    199205}
    200206
    201 void Mixer::mix(int16 *buf, uint len) {
     207void MixerImpl::mixCallback(byte *samples, uint len) {
     208        assert(samples);
     209
    202210        Common::StackLock lock(_mutex);
     211       
     212        int16 *buf = (int16 *)samples;
     213        len >>= 2;
    203214
    204215        // Since the mixer callback has been called, the mixer must be ready...
    205216        _mixerReady = true;
     
    218229                }
    219230}
    220231
    221 void Mixer::mixCallback(void *s, byte *samples, int len) {
    222         assert(s);
    223         assert(samples);
    224         // Len is the number of bytes in the buffer; we divide it by
    225         // four to get the number of samples (stereo 16 bit).
    226         ((Mixer *)s)->mix((int16 *)samples, len >> 2);
    227 }
    228 
    229 void Mixer::stopAll() {
     232void MixerImpl::stopAll() {
    230233        Common::StackLock lock(_mutex);
    231234        for (int i = 0; i != NUM_CHANNELS; i++) {
    232235                if (_channels[i] != 0 && !_channels[i]->isPermanent()) {
     
    236239        }
    237240}
    238241
    239 void Mixer::stopID(int id) {
     242void MixerImpl::stopID(int id) {
    240243        Common::StackLock lock(_mutex);
    241244        for (int i = 0; i != NUM_CHANNELS; i++) {
    242245                if (_channels[i] != 0 && _channels[i]->getId() == id) {
     
    246249        }
    247250}
    248251
    249 void Mixer::stopHandle(SoundHandle handle) {
     252void MixerImpl::stopHandle(SoundHandle handle) {
    250253        Common::StackLock lock(_mutex);
    251254
    252255        // Simply ignore stop requests for handles of sounds that already terminated
     
    258261        _channels[index] = 0;
    259262}
    260263
    261 void Mixer::setChannelVolume(SoundHandle handle, byte volume) {
     264void MixerImpl::setChannelVolume(SoundHandle handle, byte volume) {
    262265        Common::StackLock lock(_mutex);
    263266
    264267        const int index = handle._val % NUM_CHANNELS;
     
    268271        _channels[index]->setVolume(volume);
    269272}
    270273
    271 void Mixer::setChannelBalance(SoundHandle handle, int8 balance) {
     274void MixerImpl::setChannelBalance(SoundHandle handle, int8 balance) {
    272275        Common::StackLock lock(_mutex);
    273276
    274277        const int index = handle._val % NUM_CHANNELS;
     
    278281        _channels[index]->setBalance(balance);
    279282}
    280283
    281 uint32 Mixer::getSoundElapsedTime(SoundHandle handle) {
     284uint32 MixerImpl::getSoundElapsedTime(SoundHandle handle) {
    282285        Common::StackLock lock(_mutex);
    283286
    284287        const int index = handle._val % NUM_CHANNELS;
     
    288291        return _channels[index]->getElapsedTime();
    289292}
    290293
    291 void Mixer::pauseAll(bool paused) {
     294void MixerImpl::pauseAll(bool paused) {
    292295        Common::StackLock lock(_mutex);
    293296        for (int i = 0; i != NUM_CHANNELS; i++) {
    294297                if (_channels[i] != 0) {
     
    297300        }
    298301}
    299302
    300 void Mixer::pauseID(int id, bool paused) {
     303void MixerImpl::pauseID(int id, bool paused) {
    301304        Common::StackLock lock(_mutex);
    302305        for (int i = 0; i != NUM_CHANNELS; i++) {
    303306                if (_channels[i] != 0 && _channels[i]->getId() == id) {
     
    307310        }
    308311}
    309312
    310 void Mixer::pauseHandle(SoundHandle handle, bool paused) {
     313void MixerImpl::pauseHandle(SoundHandle handle, bool paused) {
    311314        Common::StackLock lock(_mutex);
    312315
    313316        // Simply ignore (un)pause requests for sounds that already terminated
     
    318321        _channels[index]->pause(paused);
    319322}
    320323
    321 bool Mixer::isSoundIDActive(int id) {
     324bool MixerImpl::isSoundIDActive(int id) {
    322325        Common::StackLock lock(_mutex);
    323326        for (int i = 0; i != NUM_CHANNELS; i++)
    324327                if (_channels[i] && _channels[i]->getId() == id)
     
    326329        return false;
    327330}
    328331
    329 int Mixer::getSoundID(SoundHandle handle) {
     332int MixerImpl::getSoundID(SoundHandle handle) {
    330333        Common::StackLock lock(_mutex);
    331334        const int index = handle._val % NUM_CHANNELS;
    332335        if (_channels[index] && _channels[index]->_handle._val == handle._val)
     
    334337        return 0;
    335338}
    336339
    337 bool Mixer::isSoundHandleActive(SoundHandle handle) {
     340bool MixerImpl::isSoundHandleActive(SoundHandle handle) {
    338341        Common::StackLock lock(_mutex);
    339342        const int index = handle._val % NUM_CHANNELS;
    340343        return _channels[index] && _channels[index]->_handle._val == handle._val;
    341344}
    342345
    343 bool Mixer::hasActiveChannelOfType(SoundType type) {
     346bool MixerImpl::hasActiveChannelOfType(SoundType type) {
    344347        Common::StackLock lock(_mutex);
    345348        for (int i = 0; i != NUM_CHANNELS; i++)
    346349                if (_channels[i] && _channels[i]->_type == type)
     
    348351        return false;
    349352}
    350353
    351 void Mixer::setVolumeForSoundType(SoundType type, int volume) {
     354void MixerImpl::setVolumeForSoundType(SoundType type, int volume) {
    352355        assert(0 <= type && type < ARRAYSIZE(_volumeForSoundType));
    353356
    354357        // Check range
     
    363366        _volumeForSoundType[type] = volume;
    364367}
    365368
    366 int Mixer::getVolumeForSoundType(SoundType type) const {
     369int MixerImpl::getVolumeForSoundType(SoundType type) const {
    367370        assert(0 <= type && type < ARRAYSIZE(_volumeForSoundType));
    368371
    369372        return _volumeForSoundType[type];
     
    443446        // Convert the number of samples into a time duration. To avoid
    444447        // overflow, this has to be done in a somewhat non-obvious way.
    445448
    446         uint rate = _mixer->getOutputRate();
     449        uint32 rate = _mixer->getOutputRate();
    447450
    448451        uint32 seconds = _samplesConsumed / rate;
    449452        uint32 milliseconds = (1000 * (_samplesConsumed % rate)) / rate;
  • sound/mixer_intern.h

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 *
     24 */
     25
     26#ifndef SOUND_MIXER_INTERN_H
     27#define SOUND_MIXER_INTERN_H
     28
     29#include "common/scummsys.h"
     30#include "common/mutex.h"
     31#include "sound/mixer.h"
     32
     33namespace Audio {
     34
     35/**
     36 * The (default) implementation of the ScummVM audio mixing subsystem.
     37 *
     38 * Backends are responsible for allocating (and later releasing) an instance
     39 * of this class, which engines can access via OSystem::getMixer().
     40 *
     41 * Initialisation of instances of this class usually happens as follows:
     42 * 1) Creat a new Audio::MixerImpl instance.
     43 * 2) Set the hardware output sample rate via the setSampleRate() method.
     44 * 3) Hook up the mixCallback() in a suitable audio processing thread/callback.
     45 * 4) Change the mixer into ready mode via setReady(true).
     46 * 5) Start audio processing (e.g. by resuming the audio thread, if applicable).
     47 *
     48 * In the future, we might make it possible for backends to provide
     49 * (partial) alternative implementations of the mixer, e.g. to make
     50 * better use of native sound mixing support on low-end devices.
     51 *
     52 * @see OSystem::getMixer()
     53 */
     54class MixerImpl : public Mixer {
     55private:
     56        enum {
     57                NUM_CHANNELS = 16
     58        };
     59
     60        OSystem *_syst;
     61        Common::Mutex _mutex;
     62
     63        uint _sampleRate;
     64        bool _mixerReady;
     65        uint32 _handleSeed;
     66
     67        int _volumeForSoundType[4];
     68        Channel *_channels[NUM_CHANNELS];
     69
     70
     71public:
     72        MixerImpl(OSystem *system);
     73        ~MixerImpl();
     74
     75        virtual bool isReady() const { return _mixerReady; }
     76
     77        virtual void playRaw(
     78                SoundType type,
     79                SoundHandle *handle,
     80                void *sound, uint32 size, uint rate, byte flags,
     81                int id = -1, byte volume = 255, int8 balance = 0,
     82                uint32 loopStart = 0, uint32 loopEnd = 0);
     83
     84        virtual void playInputStream(
     85                SoundType type,
     86                SoundHandle *handle,
     87                AudioStream *input,
     88                int id = -1, byte volume = 255, int8 balance = 0,
     89                bool autofreeStream = true,
     90                bool permanent = false,
     91                bool reverseStereo = false);
     92
     93
     94
     95        virtual void stopAll();
     96        virtual void stopID(int id);
     97        virtual void stopHandle(SoundHandle handle);
     98
     99        virtual void pauseAll(bool paused);
     100        virtual void pauseID(int id, bool paused);
     101        virtual void pauseHandle(SoundHandle handle, bool paused);
     102
     103        virtual bool isSoundIDActive(int id);
     104        virtual int getSoundID(SoundHandle handle);
     105
     106        virtual bool isSoundHandleActive(SoundHandle handle);
     107
     108        virtual void setChannelVolume(SoundHandle handle, byte volume);
     109        virtual void setChannelBalance(SoundHandle handle, int8 balance);
     110
     111        virtual uint32 getSoundElapsedTime(SoundHandle handle);
     112
     113        virtual bool hasActiveChannelOfType(SoundType type);
     114
     115        virtual void setVolumeForSoundType(SoundType type, int volume);
     116        virtual int getVolumeForSoundType(SoundType type) const;
     117
     118        virtual uint getOutputRate() const;
     119
     120protected:
     121        void insertChannel(SoundHandle *handle, Channel *chan);
     122
     123public:
     124        /**
     125         * The mixer callback function, to be called at regular intervals by
     126         * the backend (e.g. from an audio mixing thread). All the actual mixing
     127         * work is done from here.
     128         */
     129        void mixCallback(byte *samples, uint len);
     130
     131        /**
     132         * Set the internal 'is ready' flag of the mixer.
     133         * Backends should invoke Mixer::setReady(true) once initialisation of
     134         * their audio system has been completed (and in particular, *after*
     135         * setOutputRate() has been called).
     136         */
     137        void setReady(bool ready);
     138       
     139        /**
     140         * Set the output sample rate.
     141         *
     142         * @param sampleRate    the new output sample rate
     143         *
     144         * @note Right now, this can be done exactly ONCE. That is, the mixer
     145         * currently does not support changing the output sample rate after it
     146         * has been set for the first time.  This may change in the future.
     147         */
     148        void setOutputRate(uint sampleRate);
     149};
     150
     151
     152} // End of namespace Audio
     153
     154#endif
  • sound/mixer.h

    Property changes on: sound/mixer_intern.h
    ___________________________________________________________________
    Name: svn:mime-type
       + text/plain
    Name: svn:keywords
       + Date Rev Author URL Id
    Name: svn:eol-style
       + native
    
     
    3838class AudioStream;
    3939class Channel;
    4040class Mixer;
     41class MixerImpl;
    4142
    4243/**
    4344 * A SoundHandle instances corresponds to a specific sound
     
    4748 */
    4849class SoundHandle {
    4950        friend class Channel;
    50         friend class Mixer;
     51        friend class MixerImpl;
    5152        uint32 _val;
    5253public:
    5354        inline SoundHandle() : _val(0xFFFFFFFF) {}
     
    104105                kMaxMixerVolume = 256
    105106        };
    106107
    107 private:
    108         enum {
    109                 NUM_CHANNELS = 16
    110         };
    111 
    112         OSystem *_syst;
    113         Common::Mutex _mutex;
    114 
    115         int _volumeForSoundType[4];
    116 
    117         uint32 _handleSeed;
    118         Channel *_channels[NUM_CHANNELS];
    119 
    120         bool _mixerReady;
    121 
    122108public:
    123         Mixer();
    124         ~Mixer();
     109        Mixer() {}
     110        virtual ~Mixer() {}
    125111
    126112
    127113
     
    132118         * sync with an audio stream. In particular, the Adlib MIDI emulation...
    133119         *
    134120         * @return whether the mixer is ready and setup
     121         *
     122         * @todo get rid of this?
    135123         */
    136         bool isReady() const { return _mixerReady; }
     124        virtual bool isReady() const = 0;
    137125
    138126
    139127
     
    143131         * (using the makeLinearInputStream factory function), which is then
    144132         * passed on to playInputStream.
    145133         */
    146         void playRaw(
     134        virtual void playRaw(
    147135                SoundType type,
    148136                SoundHandle *handle,
    149137                void *sound, uint32 size, uint rate, byte flags,
    150138                int id = -1, byte volume = 255, int8 balance = 0,
    151                 uint32 loopStart = 0, uint32 loopEnd = 0);
     139                uint32 loopStart = 0, uint32 loopEnd = 0) = 0;
    152140
    153141        /**
    154142         * Start playing the given audio input stream.
     
    170158         *                  not stop this particular stream
    171159         * @param reverseStereo a flag indicating whether left and right channels shall be swapped
    172160         */
    173         void playInputStream(
     161        virtual void playInputStream(
    174162                SoundType type,
    175163                SoundHandle *handle,
    176164                AudioStream *input,
    177165                int id = -1, byte volume = 255, int8 balance = 0,
    178166                bool autofreeStream = true,
    179167                bool permanent = false,
    180                 bool reverseStereo = false);
     168                bool reverseStereo = false) = 0;
    181169
    182170
    183171
    184172        /**
    185173         * Stop all currently playing sounds.
    186174         */
    187         void stopAll();
     175        virtual void stopAll() = 0;
    188176
    189177        /**
    190178         * Stop playing the sound with given ID.
    191179         *
    192180         * @param id the ID of the sound to affect
    193181         */
    194         void stopID(int id);
     182        virtual void stopID(int id) = 0;
    195183
    196184        /**
    197185         * Stop playing the sound corresponding to the given handle.
    198186         *
    199187         * @param handle the sound to affect
    200188         */
    201         void stopHandle(SoundHandle handle);
     189        virtual void stopHandle(SoundHandle handle) = 0;
    202190
    203191
    204192
     
    208196         *
    209197         * @param paused true to pause everything, false to unpause
    210198         */
    211         void pauseAll(bool paused);
     199        virtual void pauseAll(bool paused) = 0;
    212200
    213201        /**
    214202         * Pause/unpause the sound with the given ID.
     
    216204         * @param id the ID of the sound to affect
    217205         * @param paused true to pause the sound, false to unpause it
    218206         */
    219         void pauseID(int id, bool paused);
     207        virtual void pauseID(int id, bool paused) = 0;
    220208
    221209        /**
    222210         * Pause/unpause the sound corresponding to the given handle.
     
    224212         * @param handle the sound to affect
    225213         * @param paused true to pause the sound, false to unpause it
    226214         */
    227         void pauseHandle(SoundHandle handle, bool paused);
     215        virtual void pauseHandle(SoundHandle handle, bool paused) = 0;
    228216
    229217
    230218
     
    234222         * @param id the ID of the sound to query
    235223         * @return true if the sound is active
    236224         */
    237         bool isSoundIDActive(int id);
     225        virtual bool isSoundIDActive(int id) = 0;
    238226
    239227        /**
    240228         * Get the sound ID of handle sound
     
    242230         * @param handle sound to query
    243231         * @return sound ID if active
    244232         */
    245         int getSoundID(SoundHandle handle);
     233        virtual int getSoundID(SoundHandle handle) = 0;
    246234
    247235        /**
    248236         * Check if a sound with the given handle is active.
     
    250238         * @param handle sound to query
    251239         * @return true if the sound is active
    252240         */
    253         bool isSoundHandleActive(SoundHandle handle);
     241        virtual bool isSoundHandleActive(SoundHandle handle) = 0;
    254242
    255243
    256244
     
    260248         * @param handle the sound to affect
    261249         * @param volume the new channel volume (0 - 255)
    262250         */
    263         void setChannelVolume(SoundHandle handle, byte volume);
     251        virtual void setChannelVolume(SoundHandle handle, byte volume) = 0;
    264252
    265253        /**
    266254         * Set the channel balance for the given handle.
     
    269257         * @param balance the new channel balance:
    270258         *        (-127 ... 0 ... 127) corresponds to (left ... center ... right)
    271259         */
    272         void setChannelBalance(SoundHandle handle, int8 balance);
     260        virtual void setChannelBalance(SoundHandle handle, int8 balance) = 0;
    273261
    274262        /**
    275263         * Get approximation of for how long the channel has been playing.
    276264         */
    277         uint32 getSoundElapsedTime(SoundHandle handle);
     265        virtual uint32 getSoundElapsedTime(SoundHandle handle) = 0;
    278266
    279267        /**
    280268         * Check whether any channel of the given sound type is active.
     
    284272         * @param  type the sound type to look for
    285273         * @return true if any channels of the specified type are active.
    286274         */
    287         bool hasActiveChannelOfType(SoundType type);
     275        virtual bool hasActiveChannelOfType(SoundType type) = 0;
    288276
    289277        /**
    290278         * Set the volume for the given sound type.
     
    292280         * @param type the sound type
    293281         * @param volume the new global volume, 0-kMaxMixerVolume
    294282         */
    295         void setVolumeForSoundType(SoundType type, int volume);
     283        virtual void setVolumeForSoundType(SoundType type, int volume) = 0;
    296284
    297285        /**
    298286         * Query the global volume.
     
    300288         * @param type the sound type
    301289         * @return the global music volume, 0-kMaxMixerVolume
    302290         */
    303         int getVolumeForSoundType(SoundType type) const;
     291        virtual int getVolumeForSoundType(SoundType type) const = 0;
    304292
    305293        /**
    306294         * Query the system's audio output sample rate. This returns
     
    308296         *
    309297         * @return the output sample rate in Hz
    310298         */
    311         uint getOutputRate() const;
    312 
    313 protected:
    314         void insertChannel(SoundHandle *handle, Channel *chan);
    315 
    316         /**
    317          * Internal main method -- all the actual mixing work is done from here.
    318          */
    319         void mix(int16 * buf, uint len);
    320 
    321         // FIXME: temporary "public" to allow access to mixCallback
    322         // from within OSystem::makeMixer()
    323 public:
    324         /**
    325          * The mixer callback function, passed on to OSystem::setSoundCallback().
    326          * This simply calls the mix() method.
    327          */
    328         static void mixCallback(void *s, byte *samples, int len);
    329 
    330         void setReady(bool ready) { _mixerReady = ready; }
     299        virtual uint getOutputRate() const = 0;
    331300};
    332301
    333302
  • backends/timer/default/default-timer.h

     
    3838        void *_timerHandler;
    3939        TimerSlot *_head;
    4040
    41 
    4241public:
    4342        DefaultTimerManager();
    4443        ~DefaultTimerManager();
    4544        bool installTimerProc(TimerProc proc, int32 interval, void *refCon);
    4645        void removeTimerProc(TimerProc proc);
    4746
    48         // Timer callback, to be invoked at regular time intervals by the backend.
     47        /**
     48         * Timer callback, to be invoked at regular time intervals by the backend.
     49         */
    4950        void handler();
    5051};
    5152
  • backends/platform/gp2x/gp2x.cpp

     
    4040#include "backends/timer/default/default-timer.h"
    4141#include "backends/plugins/posix/posix-provider.h"
    4242#include "backends/fs/posix/posix-fs-factory.h" // for getFilesystemFactory()
    43 #include "sound/mixer.h"
     43#include "sound/mixer_intern.h"
    4444
    4545#include <stdio.h>
    4646#include <stdlib.h>
     
    225225        // Create and hook up the mixer, if none exists yet (we check for this to
    226226        // allow subclasses to provide their own).
    227227        if (_mixer == 0) {
    228                 _mixer = new Audio::Mixer();
    229                 setSoundCallback(Audio::Mixer::mixCallback, _mixer);
     228                setupMixer();
    230229        }
    231230
    232231        // Create and hook up the timer manager, if none exists yet (we check for
     
    445444#pragma mark --- Audio ---
    446445#pragma mark -
    447446
    448 bool OSystem_GP2X::setSoundCallback(SoundProc proc, void *param) {
     447void OSystem_GP2X::setupMixer() {
    449448        SDL_AudioSpec desired;
    450449        SDL_AudioSpec obtained;
    451450
     
    467466        desired.channels = 2;
    468467        //desired.samples = (uint16)samples;
    469468        desired.samples = 128; // Samples hack
    470         desired.callback = proc;
    471         desired.userdata = param;
     469        desired.callback = mixCallback;
     470        desired.userdata = this;
     471
     472        // Create the mixer instance
     473        assert(!_mixer);
     474        _mixer = new Audio::MixerImpl(this);
     475        assert(_mixer);
     476
    472477        if (SDL_OpenAudio(&desired, &obtained) != 0) {
    473478                warning("Could not open audio device: %s", SDL_GetError());
    474                 return false;
     479                _samplesPerSec = 0;
     480                _mixer->setReady(false);
     481        } else {
     482                // Note: This should be the obtained output rate, but it seems that at
     483                // least on some platforms SDL will lie and claim it did get the rate
     484                // even if it didn't. Probably only happens for "weird" rates, though.
     485                _samplesPerSec = obtained.freq;
     486                debug(1, "Output sample rate: %d Hz", _samplesPerSec);
     487       
     488                // Tell the mixer that we are ready and start the sound processing
     489                _mixer->setOutputRate(_samplesPerSec);
     490                _mixer->setReady(true);
     491                SDL_PauseAudio(0);
    475492        }
    476         _samplesPerSec = obtained.freq;
    477         SDL_PauseAudio(0);
    478         return true;
    479493}
    480494
    481 void OSystem_GP2X::clearSoundCallback() {
    482         SDL_CloseAudio();
    483 }
    484 
    485495int OSystem_GP2X::getOutputSampleRate() const {
    486496        return _samplesPerSec;
    487497}
  • backends/platform/gp2x/gp2x-common.h

     
    3737#include <SDL_gp2x.h>
    3838
    3939namespace Audio {
    40         class Mixer;
     40        class MixerImpl;
    4141}
    4242
    4343namespace Common {
     
    128128        virtual bool pollEvent(Common::Event &event); // overloaded by CE backend
    129129
    130130        // Set function that generates samples
    131         typedef void (*SoundProc)(void *param, byte *buf, int len);
    132         virtual bool setSoundCallback(SoundProc proc, void *param); // overloaded by CE backend
     131        virtual void setupMixer();
    133132        virtual Audio::Mixer *getMixer();
    134133
    135         void clearSoundCallback();
    136 
    137134        // Poll CD status
    138135        // Returns true if cd audio is playing
    139136        bool pollCD();
     
    369366        Common::SaveFileManager *_savefile;
    370367        FilesystemFactory *getFilesystemFactory();
    371368
    372         Audio::Mixer *_mixer;
     369        Audio::MixerImpl *_mixer;
    373370
    374371        SDL_TimerID _timerID;
    375372        Common::TimerManager *_timer;
  • backends/platform/sdl/sdl.cpp

     
    3030
    3131#include "backends/saves/default/default-saves.h"
    3232#include "backends/timer/default/default-timer.h"
    33 #include "sound/mixer.h"
     33#include "sound/mixer_intern.h"
    3434
    3535#include "icons/scummvm.xpm"
    3636
     
    131131        // Create and hook up the mixer, if none exists yet (we check for this to
    132132        // allow subclasses to provide their own).
    133133        if (_mixer == 0) {
    134                 _mixer = new Audio::Mixer();
    135                 bool result = setSoundCallback(Audio::Mixer::mixCallback, _mixer);
    136                 _mixer->setReady(result);
     134                setupMixer();
    137135        }
    138136
    139137        // Create and hook up the timer manager, if none exists yet (we check for
     
    391389#pragma mark --- Audio ---
    392390#pragma mark -
    393391
    394 bool OSystem_SDL::setSoundCallback(SoundProc proc, void *param) {
     392void OSystem_SDL::mixCallback(void *sys, byte *samples, int len) {
     393        OSystem_SDL *this_ = (OSystem_SDL *)sys;
     394        assert(this_);
     395
     396        if (this_->_mixer)
     397                this_->_mixer->mixCallback(samples, len);
     398}
     399
     400void OSystem_SDL::setupMixer() {
    395401        SDL_AudioSpec desired;
    396402        SDL_AudioSpec obtained;
    397403
     
    415421        desired.format = AUDIO_S16SYS;
    416422        desired.channels = 2;
    417423        desired.samples = (uint16)samples;
    418         desired.callback = proc;
    419         desired.userdata = param;
     424        desired.callback = mixCallback;
     425        desired.userdata = this;
     426
     427        // Create the mixer instance
     428        assert(!_mixer);
     429        _mixer = new Audio::MixerImpl(this);
     430        assert(_mixer);
     431
    420432        if (SDL_OpenAudio(&desired, &obtained) != 0) {
    421433                warning("Could not open audio device: %s", SDL_GetError());
    422                 return false;
     434                _samplesPerSec = 0;
     435                _mixer->setReady(false);
     436        } else {
     437                // Note: This should be the obtained output rate, but it seems that at
     438                // least on some platforms SDL will lie and claim it did get the rate
     439                // even if it didn't. Probably only happens for "weird" rates, though.
     440                _samplesPerSec = obtained.freq;
     441                debug(1, "Output sample rate: %d Hz", _samplesPerSec);
     442       
     443                // Tell the mixer that we are ready and start the sound processing
     444                _mixer->setOutputRate(_samplesPerSec);
     445                _mixer->setReady(true);
     446                SDL_PauseAudio(0);
    423447        }
    424         // Note: This should be the obtained output rate, but it seems that at
    425         // least on some platforms SDL will lie and claim it did get the rate
    426         // even if it didn't. Probably only happens for "weird" rates, though.
    427         _samplesPerSec = obtained.freq;
    428         debug(1, "Output sample rate: %d Hz", _samplesPerSec);
    429         SDL_PauseAudio(0);
    430         return true;
    431448}
    432449
    433 int OSystem_SDL::getOutputSampleRate() const {
    434         return _samplesPerSec;
    435 }
    436 
    437450Audio::Mixer *OSystem_SDL::getMixer() {
    438451        assert(_mixer);
    439452        return _mixer;
  • backends/platform/sdl/sdl.h

     
    3838
    3939
    4040namespace Audio {
    41         class Mixer;
     41        class MixerImpl;
    4242}
    4343
    4444namespace Common {
     
    134134        virtual bool pollEvent(Common::Event &event); // overloaded by CE backend
    135135
    136136        // Set function that generates samples
    137         typedef void (*SoundProc)(void *param, byte *buf, int len);
    138         virtual bool setSoundCallback(SoundProc proc, void *param); // overloaded by CE backend
     137        virtual void setupMixer();
     138        static void mixCallback(void *s, byte *samples, int len);
     139
    139140        virtual Audio::Mixer *getMixer();
    140141
    141142        // Poll CD status
     
    186187
    187188        virtual void setWindowCaption(const char *caption);
    188189        virtual bool openCD(int drive);
    189         virtual int getOutputSampleRate() const;
    190190
    191191        virtual bool hasFeature(Feature f);
    192192        virtual void setFeatureState(Feature f, bool enable);
     
    371371
    372372
    373373        Common::SaveFileManager *_savefile;
    374         Audio::Mixer *_mixer;
     374        Audio::MixerImpl *_mixer;
    375375
    376376        SDL_TimerID _timerID;
    377377        Common::TimerManager *_timer;
  • backends/platform/psp/osys_psp.cpp

     
    3434#include "backends/timer/default/default-timer.h"
    3535#include "graphics/surface.h"
    3636#include "graphics/scaler.h"
    37 #include "sound/mixer.h"
     37#include "sound/mixer_intern.h"
    3838
    3939#include <pspgu.h>
    4040
     
    9999
    100100void OSystem_PSP::initBackend() {
    101101        _savefile = new DefaultSaveFileManager();
    102         _mixer = new Audio::Mixer();
     102        _mixer = new Audio::MixerImpl(this);
    103103        _timer = new DefaultTimerManager();
    104104        setSoundCallback(Audio::Mixer::mixCallback, _mixer);
    105105        setTimerCallback(&timer_handler, 10);
  • backends/platform/symbian/src/SymbianOS.cpp

     
    173173        OSystem_SDL::quit();
    174174}
    175175
    176 bool OSystem_SDL_Symbian::setSoundCallback(SoundProc proc, void *param) {
     176void OSystem_SDL_Symbian::setupMixer() {
    177177
    178         // First save the proc and param
    179         _sound_proc_param = param;
    180         _sound_proc = proc;
    181178        SDL_AudioSpec desired;
    182179        SDL_AudioSpec obtained;
    183180
     
    207204        desired.format = AUDIO_S16SYS;
    208205        desired.channels = 2;
    209206        desired.samples = (uint16)samples;
    210 #ifdef S60
    211207        desired.callback = symbianMixCallback;
    212208        desired.userdata = this;
    213 #else
    214         desired.callback = proc;
    215         desired.userdata = param;
    216 #endif
     209
     210        // Create the mixer instance
     211        assert(!_mixer);
     212        _mixer = new Audio::MixerImpl(this);
     213        assert(_mixer);
     214
    217215        if (SDL_OpenAudio(&desired, &obtained) != 0) {
    218216                warning("Could not open audio device: %s", SDL_GetError());
    219                 return false;
     217                _samplesPerSec = 0;
     218                _mixer->setReady(false);
     219        } else {
     220                // Note: This should be the obtained output rate, but it seems that at
     221                // least on some platforms SDL will lie and claim it did get the rate
     222                // even if it didn't. Probably only happens for "weird" rates, though.
     223                _samplesPerSec = obtained.freq;
     224                _channels = obtained.channels;
     225       
     226                // Need to create mixbuffer for stereo mix to downmix
     227                if (_channels != 2) {
     228                        _stereo_mix_buffer = new byte [obtained.size*2];//*2 for stereo values
     229                }
     230       
     231                // Tell the mixer that we are ready and start the sound processing
     232                _mixer->setOutputRate(_samplesPerSec);
     233                _mixer->setReady(true);
     234                SDL_PauseAudio(0);
    220235        }
    221         // Note: This should be the obtained output rate, but it seems that at
    222         // least on some platforms SDL will lie and claim it did get the rate
    223         // even if it didn't. Probably only happens for "weird" rates, though.
    224         _samplesPerSec = obtained.freq;
    225         _channels = obtained.channels;
    226 
    227         // Need to create mixbuffer for stereo mix to downmix
    228         if (_channels != 2) {
    229                 _stereo_mix_buffer = new byte [obtained.size*2];//*2 for stereo values
    230         }
    231 
    232         SDL_PauseAudio(0);
    233         return true;
    234236}
    235237
    236238/**
    237239 * The mixer callback function, passed on to OSystem::setSoundCallback().
    238240 * This simply calls the mix() method.
    239241 */
    240 void OSystem_SDL_Symbian::symbianMixCallback(void *s, byte *samples, int len) {
    241         static_cast <OSystem_SDL_Symbian*>(s)->symbianMix(samples,len);
    242 }
     242void OSystem_SDL_Symbian::symbianMixCallback(void *sys, byte *samples, int len) {
     243        OSystem_SDL_Symbian *this_ = (OSystem_SDL_Symbian *)sys;
     244        assert(this_);
    243245
     246        if (!this_->_mixer)
     247                return;
    244248
    245 /**
    246  * Actual mixing implementation
    247  */
    248 void OSystem_SDL_Symbian::symbianMix(byte *samples, int len) {
     249#ifdef S60
    249250        // If not stereo then we need to downmix
    250251        if (_channels != 2) {
    251                 _sound_proc(_sound_proc_param, _stereo_mix_buffer, len * 2);
     252                this_->_mixer->mixCallback(_stereo_mix_buffer, len * 2);
     253
    252254                int16 *bitmixDst = (int16 *)samples;
    253255                int16 *bitmixSrc = (int16 *)_stereo_mix_buffer;
    254256
     
    258260                        bitmixSrc += 2;
    259261                }
    260262        } else
    261                 _sound_proc(_sound_proc_param, samples, len);
     263#else
     264        this_->_mixer->mixCallback(samples, len);
     265#endif
    262266}
    263267
     268
    264269/**
    265270 * This is an implementation by the remapKey function
    266271 * @param SDL_Event to remap
  • backends/platform/symbian/src/SymbianOS.h

     
    5858        // This function is overridden by the symbian port in order to provide MONO audio
    5959        // downmix is done by supplying our own audiocallback
    6060        //
    61         virtual bool setSoundCallback(SoundProc proc, void *param); // overloaded by CE backend
     61        virtual void setupMixer(); // overloaded by CE backend
    6262
    6363        // Overloaded from SDL_Commmon
    6464        void quit();
     
    7070        //
    7171        static void symbianMixCallback(void *s, byte *samples, int len);
    7272
    73         //
    74         // Actual mixing implementation
    75         //
    76         void symbianMix(byte *samples, int len);
    77 
    7873        virtual FilesystemFactory *getFilesystemFactory();
    7974public:
    8075        // vibration support
     
    121116        // Audio
    122117        int _channels;
    123118
    124         SoundProc _sound_proc;
    125         void *_sound_proc_param;
    126119        byte *_stereo_mix_buffer;
    127120
    128121        // Used to handle joystick navi zones
  • backends/platform/iphone/osys_iphone.cpp

     
    4040
    4141#include "backends/saves/default/default-saves.h"
    4242#include "backends/timer/default/default-timer.h"
    43 #include "sound/mixer.h"
     43#include "sound/mixer_intern.h"
    4444#include "gui/message.h"
    4545
    4646#include "osys_iphone.h"
     
    11281128        return true;
    11291129}
    11301130
    1131 void OSystem_IPHONE::clearSoundCallback() {
    1132         debug("clearSoundCallback()\n");
    1133 }
    1134 
    11351131int OSystem_IPHONE::getOutputSampleRate() const {
    11361132        return AUDIO_SAMPLE_RATE;
    11371133}
  • backends/platform/iphone/osys_iphone.h

     
    153153        virtual void deleteMutex(MutexRef mutex);
    154154
    155155        virtual bool setSoundCallback(SoundProc proc, void *param);
    156         virtual void clearSoundCallback();
    157156        virtual int getOutputSampleRate() const;
    158157        virtual void setTimerCallback(TimerProc callback, int interval);
    159158
  • backends/platform/wince/wince-sdl.cpp

     
    3535#include "base/main.h"
    3636#include "base/plugins.h"
    3737
    38 #include "sound/mixer.h"
     38#include "sound/mixer_intern.h"
    3939#include "sound/fmopl.h"
    4040
    4141#include "backends/timer/default/default-timer.h"
     
    404404        // Instantiate our own sound mixer
    405405        // mixer init is postponed until a game engine is selected.
    406406        if (_mixer == 0) {
    407                 _mixer = new Audio::Mixer();
     407                _mixer = new Audio::Mixer(this);
    408408        }
    409409
    410410        // Create the timer. CE SDL does not support multiple timers (SDL_AddTimer).
     
    770770        _toolbarHandler.setVisible(false);
    771771}
    772772
    773 bool OSystem_WINCE3::setSoundCallback(SoundProc proc, void *param) {
     773void OSystem_WINCE3::setupMixer(SoundProc proc, void *param) {
    774774        SDL_AudioSpec desired;
    775775        int thread_priority;
    776776
     
    785785        desired.channels = 2;
    786786        desired.samples = 128;
    787787        desired.callback = private_sound_proc;
    788         desired.userdata = param;
     788        desired.userdata = this;
    789789
     790        // Create the mixer instance
     791        assert(!_mixer);
     792        _mixer = new Audio::MixerImpl(this);
     793        assert(_mixer);
     794
    790795        // Add sound thread priority
    791         if (!ConfMan.hasKey("sound_thread_priority")) {
     796        if (!ConfMan.hasKey("sound_thread_priority"))
    792797                thread_priority = THREAD_PRIORITY_NORMAL;
    793         }
    794798        else
    795799                thread_priority = ConfMan.getInt("sound_thread_priority");
    796800
     
    799803        SDL_CloseAudio();
    800804        if (SDL_OpenAudio(&desired, NULL) != 0) {
    801805                warning("Could not open audio device: %s", SDL_GetError());
    802                 return false;
     806                _mixer->setReady(false);
     807
     808        } else {
     809                debug(1, "Sound opened OK, mixing at %d Hz", _sampleRate);
     810
     811                // Tell the mixer that we are ready and start the sound processing
     812                _mixer->setOutputRate(_sampleRate);
     813                _mixer->setReady(true);
     814                SDL_PauseAudio(0);
    803815        }
    804         else
    805                 debug(1, "Sound opened OK, mixing at %d Hz", _sampleRate);
    806         SDL_PauseAudio(0);
    807         return true;
    808816}
    809817
    810818void OSystem_WINCE3::private_sound_proc(void *param, byte *buf, int len) {
    811         (*_originalSoundProc)(param, buf, len);
     819        OSystem_WINCE3 *this_ = (OSystem_WINCE3 *)param;
     820        assert(this_);
     821
     822        if (this_->_mixer)
     823                this_->_mixer->mixCallback(buf, len);
    812824        if (!_soundMaster)
    813825                memset(buf, 0, len);
    814826}
     
    838850}
    839851#endif
    840852
    841 void OSystem_WINCE3::get_sample_rate() {
     853void OSystem_WINCE3::compute_sample_rate() {
    842854        // Force at least medium quality FM synthesis for FOTAQ
    843855        Common::String gameid(ConfMan.get("gameid"));
    844856        if (gameid == "queen") {
     
    875887
    876888        //update_game_settings();
    877889        // finalize mixer init
    878         get_sample_rate();
    879         bool result = setSoundCallback(Audio::Mixer::mixCallback, _mixer);
    880         _mixer->setReady(result);
     890        compute_sample_rate();
     891        setupMixer();
    881892
    882893        // handle the actual event
    883894        OSystem_SDL::setWindowCaption(caption);
     
    10501061                }
    10511062        }
    10521063
    1053         get_sample_rate();
     1064        compute_sample_rate();
    10541065}
    10551066
    10561067void OSystem_WINCE3::initSize(uint w, uint h) {
  • backends/platform/wince/wince-sdl.h

     
    8282        // Overloaded from SDL_Commmon
    8383        void quit();
    8484        // Overloaded from SDL_Commmon (master volume and sample rate subtleties)
    85         bool setSoundCallback(SoundProc proc, void *param);
     85        void setupMixer();
    8686        // Overloaded from OSystem
    8787        //void engineInit();
    8888        void getTimeAndDate(struct tm &t) const;
     
    160160#endif
    161161
    162162        static void private_sound_proc(void *param, byte *buf, int len);
    163         static SoundProc _originalSoundProc;
    164163
    165164        bool update_scalers();
    166165        void create_toolbar();
    167166        void update_game_settings();
    168167        void check_mappings();
    169         void get_sample_rate();
     168        void compute_sample_rate();
    170169
    171170        void retrieve_mouse_location(int &x, int &y);
    172171
  • backends/platform/PalmOS/Src/be_base.cpp

     
    2828#include "common/config-file.h"
    2929#include "common/config-manager.h"
    3030#include "backends/timer/default/default-timer.h"
    31 #include "sound/mixer.h"
     31#include "sound/mixer_intern.h"
    3232
    3333OSystem_PalmBase::OSystem_PalmBase() {
    3434        _overlayVisible = false;
     
    106106        // Create and hook up the mixer, if none exists yet (we check for this to
    107107        // allow subclasses to provide their own).
    108108        if (_mixerMgr == 0) {
    109                 _mixerMgr = new Audio::Mixer();
     109                _mixerMgr = new Audio::Mixer(this);
    110110                setSoundCallback(Audio::Mixer::mixCallback, _mixerMgr);
    111111        }
    112112