ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

mixer.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "gui/EventRecorder.h"
00024 
00025 #include "common/util.h"
00026 #include "common/textconsole.h"
00027 
00028 #include "audio/mixer_intern.h"
00029 #include "audio/rate.h"
00030 #include "audio/audiostream.h"
00031 #include "audio/timestamp.h"
00032 
00033 
00034 namespace Audio {
00035 
00036 #pragma mark -
00037 #pragma mark --- Channel classes ---
00038 #pragma mark -
00039 
00040 
00044 class Channel {
00045 public:
00046     Channel(Mixer *mixer, Mixer::SoundType type, AudioStream *stream, DisposeAfterUse::Flag autofreeStream, bool reverseStereo, int id, bool permanent);
00047     ~Channel();
00048 
00058     int mix(int16 *data, uint len);
00059 
00063     bool isFinished() const { return _stream->endOfStream(); }
00064 
00070     bool isPermanent() const { return _permanent; }
00071 
00075     int getId() const { return _id; }
00076 
00083     void pause(bool paused);
00084 
00088     bool isPaused() const { return (_pauseLevel != 0); }
00089 
00095     void setVolume(const byte volume);
00096 
00102     byte getVolume();
00103 
00109     void setBalance(const int8 balance);
00110 
00116     int8 getBalance();
00117 
00122     void notifyGlobalVolChange() { updateChannelVolumes(); }
00123 
00127     Timestamp getElapsedTime();
00128 
00132     Mixer::SoundType getType() const { return _type; }
00133 
00139     void setHandle(const SoundHandle handle) { _handle = handle; }
00140 
00144     SoundHandle getHandle() const { return _handle; }
00145 
00146 private:
00147     const Mixer::SoundType _type;
00148     SoundHandle _handle;
00149     bool _permanent;
00150     int _pauseLevel;
00151     int _id;
00152 
00153     byte _volume;
00154     int8 _balance;
00155 
00156     void updateChannelVolumes();
00157     st_volume_t _volL, _volR;
00158 
00159     Mixer *_mixer;
00160 
00161     uint32 _samplesConsumed;
00162     uint32 _samplesDecoded;
00163     uint32 _mixerTimeStamp;
00164     uint32 _pauseStartTime;
00165     uint32 _pauseTime;
00166 
00167     RateConverter *_converter;
00168     Common::DisposablePtr<AudioStream> _stream;
00169 };
00170 
00171 #pragma mark -
00172 #pragma mark --- Mixer ---
00173 #pragma mark -
00174 
00175 MixerImpl::MixerImpl(uint sampleRate)
00176     : _mutex(), _sampleRate(sampleRate), _mixerReady(false), _handleSeed(0), _soundTypeSettings() {
00177 
00178     assert(sampleRate > 0);
00179 
00180     for (int i = 0; i != NUM_CHANNELS; i++)
00181         _channels[i] = 0;
00182 }
00183 
00184 MixerImpl::~MixerImpl() {
00185     for (int i = 0; i != NUM_CHANNELS; i++)
00186         delete _channels[i];
00187 }
00188 
00189 void MixerImpl::setReady(bool ready) {
00190     _mixerReady = ready;
00191 }
00192 
00193 uint MixerImpl::getOutputRate() const {
00194     return _sampleRate;
00195 }
00196 
00197 void MixerImpl::insertChannel(SoundHandle *handle, Channel *chan) {
00198     int index = -1;
00199     for (int i = 0; i != NUM_CHANNELS; i++) {
00200         if (_channels[i] == 0) {
00201             index = i;
00202             break;
00203         }
00204     }
00205     if (index == -1) {
00206         warning("MixerImpl::out of mixer slots");
00207         delete chan;
00208         return;
00209     }
00210 
00211     _channels[index] = chan;
00212 
00213     SoundHandle chanHandle;
00214     chanHandle._val = index + (_handleSeed * NUM_CHANNELS);
00215 
00216     chan->setHandle(chanHandle);
00217     _handleSeed++;
00218     if (handle)
00219         *handle = chanHandle;
00220 }
00221 
00222 void MixerImpl::playStream(
00223             SoundType type,
00224             SoundHandle *handle,
00225             AudioStream *stream,
00226             int id, byte volume, int8 balance,
00227             DisposeAfterUse::Flag autofreeStream,
00228             bool permanent,
00229             bool reverseStereo) {
00230     Common::StackLock lock(_mutex);
00231 
00232     if (stream == 0) {
00233         warning("stream is 0");
00234         return;
00235     }
00236 
00237 
00238     assert(_mixerReady);
00239 
00240     // Prevent duplicate sounds
00241     if (id != -1) {
00242         for (int i = 0; i != NUM_CHANNELS; i++)
00243             if (_channels[i] != 0 && _channels[i]->getId() == id) {
00244                 // Delete the stream if were asked to auto-dispose it.
00245                 // Note: This could cause trouble if the client code does not
00246                 // yet expect the stream to be gone. The primary example to
00247                 // keep in mind here is QueuingAudioStream.
00248                 // Thus, as a quick rule of thumb, you should never, ever,
00249                 // try to play QueuingAudioStreams with a sound id.
00250                 if (autofreeStream == DisposeAfterUse::YES)
00251                     delete stream;
00252                 return;
00253             }
00254     }
00255 
00256 #ifdef AUDIO_REVERSE_STEREO
00257     reverseStereo = !reverseStereo;
00258 #endif
00259 
00260     // Create the channel
00261     Channel *chan = new Channel(this, type, stream, autofreeStream, reverseStereo, id, permanent);
00262     chan->setVolume(volume);
00263     chan->setBalance(balance);
00264     insertChannel(handle, chan);
00265 }
00266 
00267 int MixerImpl::mixCallback(byte *samples, uint len) {
00268     assert(samples);
00269 
00270     Common::StackLock lock(_mutex);
00271 
00272     int16 *buf = (int16 *)samples;
00273     // we store stereo, 16-bit samples
00274     assert(len % 4 == 0);
00275     len >>= 2;
00276 
00277     // Since the mixer callback has been called, the mixer must be ready...
00278     _mixerReady = true;
00279 
00280     //  zero the buf
00281     memset(buf, 0, 2 * len * sizeof(int16));
00282 
00283     // mix all channels
00284     int res = 0, tmp;
00285     for (int i = 0; i != NUM_CHANNELS; i++)
00286         if (_channels[i]) {
00287             if (_channels[i]->isFinished()) {
00288                 delete _channels[i];
00289                 _channels[i] = 0;
00290             } else if (!_channels[i]->isPaused()) {
00291                 tmp = _channels[i]->mix(buf, len);
00292 
00293                 if (tmp > res)
00294                     res = tmp;
00295             }
00296         }
00297 
00298     return res;
00299 }
00300 
00301 void MixerImpl::stopAll() {
00302     Common::StackLock lock(_mutex);
00303     for (int i = 0; i != NUM_CHANNELS; i++) {
00304         if (_channels[i] != 0 && !_channels[i]->isPermanent()) {
00305             delete _channels[i];
00306             _channels[i] = 0;
00307         }
00308     }
00309 }
00310 
00311 void MixerImpl::stopID(int id) {
00312     Common::StackLock lock(_mutex);
00313     for (int i = 0; i != NUM_CHANNELS; i++) {
00314         if (_channels[i] != 0 && _channels[i]->getId() == id) {
00315             delete _channels[i];
00316             _channels[i] = 0;
00317         }
00318     }
00319 }
00320 
00321 void MixerImpl::stopHandle(SoundHandle handle) {
00322     Common::StackLock lock(_mutex);
00323 
00324     // Simply ignore stop requests for handles of sounds that already terminated
00325     const int index = handle._val % NUM_CHANNELS;
00326     if (!_channels[index] || _channels[index]->getHandle()._val != handle._val)
00327         return;
00328 
00329     delete _channels[index];
00330     _channels[index] = 0;
00331 }
00332 
00333 void MixerImpl::muteSoundType(SoundType type, bool mute) {
00334     assert(0 <= (int)type && (int)type < ARRAYSIZE(_soundTypeSettings));
00335     _soundTypeSettings[type].mute = mute;
00336 
00337     for (int i = 0; i != NUM_CHANNELS; ++i) {
00338         if (_channels[i] && _channels[i]->getType() == type)
00339             _channels[i]->notifyGlobalVolChange();
00340     }
00341 }
00342 
00343 bool MixerImpl::isSoundTypeMuted(SoundType type) const {
00344     assert(0 <= (int)type && (int)type < ARRAYSIZE(_soundTypeSettings));
00345     return _soundTypeSettings[type].mute;
00346 }
00347 
00348 void MixerImpl::setChannelVolume(SoundHandle handle, byte volume) {
00349     Common::StackLock lock(_mutex);
00350 
00351     const int index = handle._val % NUM_CHANNELS;
00352     if (!_channels[index] || _channels[index]->getHandle()._val != handle._val)
00353         return;
00354 
00355     _channels[index]->setVolume(volume);
00356 }
00357 
00358 byte MixerImpl::getChannelVolume(SoundHandle handle) {
00359     const int index = handle._val % NUM_CHANNELS;
00360     if (!_channels[index] || _channels[index]->getHandle()._val != handle._val)
00361         return 0;
00362 
00363     return _channels[index]->getVolume();
00364 }
00365 
00366 void MixerImpl::setChannelBalance(SoundHandle handle, int8 balance) {
00367     Common::StackLock lock(_mutex);
00368 
00369     const int index = handle._val % NUM_CHANNELS;
00370     if (!_channels[index] || _channels[index]->getHandle()._val != handle._val)
00371         return;
00372 
00373     _channels[index]->setBalance(balance);
00374 }
00375 
00376 int8 MixerImpl::getChannelBalance(SoundHandle handle) {
00377     const int index = handle._val % NUM_CHANNELS;
00378     if (!_channels[index] || _channels[index]->getHandle()._val != handle._val)
00379         return 0;
00380 
00381     return _channels[index]->getBalance();
00382 }
00383 
00384 uint32 MixerImpl::getSoundElapsedTime(SoundHandle handle) {
00385     return getElapsedTime(handle).msecs();
00386 }
00387 
00388 Timestamp MixerImpl::getElapsedTime(SoundHandle handle) {
00389     Common::StackLock lock(_mutex);
00390 
00391     const int index = handle._val % NUM_CHANNELS;
00392     if (!_channels[index] || _channels[index]->getHandle()._val != handle._val)
00393         return Timestamp(0, _sampleRate);
00394 
00395     return _channels[index]->getElapsedTime();
00396 }
00397 
00398 void MixerImpl::pauseAll(bool paused) {
00399     Common::StackLock lock(_mutex);
00400     for (int i = 0; i != NUM_CHANNELS; i++) {
00401         if (_channels[i] != 0) {
00402             _channels[i]->pause(paused);
00403         }
00404     }
00405 }
00406 
00407 void MixerImpl::pauseID(int id, bool paused) {
00408     Common::StackLock lock(_mutex);
00409     for (int i = 0; i != NUM_CHANNELS; i++) {
00410         if (_channels[i] != 0 && _channels[i]->getId() == id) {
00411             _channels[i]->pause(paused);
00412             return;
00413         }
00414     }
00415 }
00416 
00417 void MixerImpl::pauseHandle(SoundHandle handle, bool paused) {
00418     Common::StackLock lock(_mutex);
00419 
00420     // Simply ignore (un)pause requests for sounds that already terminated
00421     const int index = handle._val % NUM_CHANNELS;
00422     if (!_channels[index] || _channels[index]->getHandle()._val != handle._val)
00423         return;
00424 
00425     _channels[index]->pause(paused);
00426 }
00427 
00428 bool MixerImpl::isSoundIDActive(int id) {
00429     Common::StackLock lock(_mutex);
00430 
00431 #ifdef ENABLE_EVENTRECORDER
00432     g_eventRec.updateSubsystems();
00433 #endif
00434 
00435     for (int i = 0; i != NUM_CHANNELS; i++)
00436         if (_channels[i] && _channels[i]->getId() == id)
00437             return true;
00438     return false;
00439 }
00440 
00441 int MixerImpl::getSoundID(SoundHandle handle) {
00442     Common::StackLock lock(_mutex);
00443     const int index = handle._val % NUM_CHANNELS;
00444     if (_channels[index] && _channels[index]->getHandle()._val == handle._val)
00445         return _channels[index]->getId();
00446     return 0;
00447 }
00448 
00449 bool MixerImpl::isSoundHandleActive(SoundHandle handle) {
00450     Common::StackLock lock(_mutex);
00451 
00452 #ifdef ENABLE_EVENTRECORDER
00453     g_eventRec.updateSubsystems();
00454 #endif
00455 
00456     const int index = handle._val % NUM_CHANNELS;
00457     return _channels[index] && _channels[index]->getHandle()._val == handle._val;
00458 }
00459 
00460 bool MixerImpl::hasActiveChannelOfType(SoundType type) {
00461     Common::StackLock lock(_mutex);
00462     for (int i = 0; i != NUM_CHANNELS; i++)
00463         if (_channels[i] && _channels[i]->getType() == type)
00464             return true;
00465     return false;
00466 }
00467 
00468 void MixerImpl::setVolumeForSoundType(SoundType type, int volume) {
00469     assert(0 <= (int)type && (int)type < ARRAYSIZE(_soundTypeSettings));
00470 
00471     // Check range
00472     volume = CLIP<int>(volume, 0, kMaxMixerVolume);
00473 
00474     // TODO: Maybe we should do logarithmic (not linear) volume
00475     // scaling? See also Player_V2::setMasterVolume
00476 
00477     Common::StackLock lock(_mutex);
00478     _soundTypeSettings[type].volume = volume;
00479 
00480     for (int i = 0; i != NUM_CHANNELS; ++i) {
00481         if (_channels[i] && _channels[i]->getType() == type)
00482             _channels[i]->notifyGlobalVolChange();
00483     }
00484 }
00485 
00486 int MixerImpl::getVolumeForSoundType(SoundType type) const {
00487     assert(0 <= (int)type && (int)type < ARRAYSIZE(_soundTypeSettings));
00488 
00489     return _soundTypeSettings[type].volume;
00490 }
00491 
00492 
00493 #pragma mark -
00494 #pragma mark --- Channel implementations ---
00495 #pragma mark -
00496 
00497 Channel::Channel(Mixer *mixer, Mixer::SoundType type, AudioStream *stream,
00498                  DisposeAfterUse::Flag autofreeStream, bool reverseStereo, int id, bool permanent)
00499     : _type(type), _mixer(mixer), _id(id), _permanent(permanent), _volume(Mixer::kMaxChannelVolume),
00500       _balance(0), _pauseLevel(0), _samplesConsumed(0), _samplesDecoded(0), _mixerTimeStamp(0),
00501       _pauseStartTime(0), _pauseTime(0), _converter(0), _volL(0), _volR(0),
00502       _stream(stream, autofreeStream) {
00503     assert(mixer);
00504     assert(stream);
00505 
00506     // Get a rate converter instance
00507     _converter = makeRateConverter(_stream->getRate(), mixer->getOutputRate(), _stream->isStereo(), reverseStereo);
00508 }
00509 
00510 Channel::~Channel() {
00511     delete _converter;
00512 }
00513 
00514 void Channel::setVolume(const byte volume) {
00515     _volume = volume;
00516     updateChannelVolumes();
00517 }
00518 
00519 byte Channel::getVolume() {
00520     return _volume;
00521 }
00522 
00523 void Channel::setBalance(const int8 balance) {
00524     _balance = balance;
00525     updateChannelVolumes();
00526 }
00527 
00528 int8 Channel::getBalance() {
00529     return _balance;
00530 }
00531 
00532 void Channel::updateChannelVolumes() {
00533     // From the channel balance/volume and the global volume, we compute
00534     // the effective volume for the left and right channel. Note the
00535     // slightly odd divisor: the 255 reflects the fact that the maximal
00536     // value for _volume is 255, while the 127 is there because the
00537     // balance value ranges from -127 to 127.  The mixer (music/sound)
00538     // volume is in the range 0 - kMaxMixerVolume.
00539     // Hence, the vol_l/vol_r values will be in that range, too
00540 
00541     if (!_mixer->isSoundTypeMuted(_type)) {
00542         int vol = _mixer->getVolumeForSoundType(_type) * _volume;
00543 
00544         if (_balance == 0) {
00545             _volL = vol / Mixer::kMaxChannelVolume;
00546             _volR = vol / Mixer::kMaxChannelVolume;
00547         } else if (_balance < 0) {
00548             _volL = vol / Mixer::kMaxChannelVolume;
00549             _volR = ((127 + _balance) * vol) / (Mixer::kMaxChannelVolume * 127);
00550         } else {
00551             _volL = ((127 - _balance) * vol) / (Mixer::kMaxChannelVolume * 127);
00552             _volR = vol / Mixer::kMaxChannelVolume;
00553         }
00554     } else {
00555         _volL = _volR = 0;
00556     }
00557 }
00558 
00559 void Channel::pause(bool paused) {
00560     //assert((paused && _pauseLevel >= 0) || (!paused && _pauseLevel));
00561 
00562     if (paused) {
00563         _pauseLevel++;
00564 
00565         if (_pauseLevel == 1)
00566             _pauseStartTime = g_system->getMillis(true);
00567     } else if (_pauseLevel > 0) {
00568         _pauseLevel--;
00569 
00570         if (!_pauseLevel) {
00571             _pauseTime = (g_system->getMillis(true) - _pauseStartTime);
00572             _pauseStartTime = 0;
00573         }
00574     }
00575 }
00576 
00577 Timestamp Channel::getElapsedTime() {
00578     const uint32 rate = _mixer->getOutputRate();
00579     uint32 delta = 0;
00580 
00581     Audio::Timestamp ts(0, rate);
00582 
00583     if (_mixerTimeStamp == 0)
00584         return ts;
00585 
00586     if (isPaused())
00587         delta = _pauseStartTime - _mixerTimeStamp;
00588     else
00589         delta = g_system->getMillis(true) - _mixerTimeStamp - _pauseTime;
00590 
00591     // Convert the number of samples into a time duration.
00592 
00593     ts = ts.addFrames(_samplesConsumed);
00594     ts = ts.addMsecs(delta);
00595 
00596     // In theory it would seem like a good idea to limit the approximation
00597     // so that it never exceeds the theoretical upper bound set by
00598     // _samplesDecoded. Meanwhile, back in the real world, doing so makes
00599     // the Broken Sword cutscenes noticeably jerkier. I guess the mixer
00600     // isn't invoked at the regular intervals that I first imagined.
00601 
00602     return ts;
00603 }
00604 
00605 int Channel::mix(int16 *data, uint len) {
00606     assert(_stream);
00607 
00608     int res = 0;
00609     if (_stream->endOfData()) {
00610         // TODO: call drain method
00611     } else {
00612         assert(_converter);
00613         _samplesConsumed = _samplesDecoded;
00614         _mixerTimeStamp = g_system->getMillis(true);
00615         _pauseTime = 0;
00616         res = _converter->flow(*_stream, data, len, _volL, _volR);
00617         _samplesDecoded += res;
00618     }
00619 
00620     return res;
00621 }
00622 
00623 } // End of namespace Audio


Generated on Sat Apr 4 2020 05:00:24 for ResidualVM by doxygen 1.7.1
curved edge   curved edge