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


Generated on Sat Feb 16 2019 05:00:58 for ResidualVM by doxygen 1.7.1
curved edge   curved edge