aboutsummaryrefslogtreecommitdiff
path: root/engines/gob/sound/soundmixer.cpp
diff options
context:
space:
mode:
authorSven Hesse2008-05-08 01:27:36 +0000
committerSven Hesse2008-05-08 01:27:36 +0000
commit0c827c8cebf3709e980bb90be32b004acda058b8 (patch)
treed40c1c4561a4591c7b440a27e1fa9c99ce8e4beb /engines/gob/sound/soundmixer.cpp
parent220d6ce82f478966db6a4760b2288750212880b9 (diff)
downloadscummvm-rg350-0c827c8cebf3709e980bb90be32b004acda058b8.tar.gz
scummvm-rg350-0c827c8cebf3709e980bb90be32b004acda058b8.tar.bz2
scummvm-rg350-0c827c8cebf3709e980bb90be32b004acda058b8.zip
Split off the actual mixing part of SoundBlaster
svn-id: r31938
Diffstat (limited to 'engines/gob/sound/soundmixer.cpp')
-rw-r--r--engines/gob/sound/soundmixer.cpp205
1 files changed, 205 insertions, 0 deletions
diff --git a/engines/gob/sound/soundmixer.cpp b/engines/gob/sound/soundmixer.cpp
new file mode 100644
index 0000000000..f85073ad61
--- /dev/null
+++ b/engines/gob/sound/soundmixer.cpp
@@ -0,0 +1,205 @@
+/* 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$
+ *
+ */
+
+#include "gob/sound/soundmixer.h"
+
+namespace Gob {
+
+SoundMixer::SoundMixer(Audio::Mixer &mixer) : _mixer(&mixer) {
+ _playingSound = 0;
+
+ _rate = _mixer->getOutputRate();
+ _end = true;
+ _data = 0;
+ _length = 0;
+ _freq = 0;
+ _repCount = 0;
+
+ _offset = 0;
+ _offsetFrac = 0;
+ _offsetInc = 0;
+
+ _cur = 0;
+ _last = 0;
+
+ _fade = false;
+ _fadeVol = 65536;
+ _fadeVolStep = 0;
+ _fadeSamples = 0;
+ _curFadeSamples = 0;
+
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_handle,
+ this, -1, 255, 0, false, true);
+}
+
+SoundMixer::~SoundMixer() {
+ _mixer->stopHandle(_handle);
+}
+
+bool SoundMixer::isPlaying() const {
+ return !_end;
+}
+
+char SoundMixer::getPlayingSound() const {
+ return _playingSound;
+}
+
+void SoundMixer::stop(int16 fadeLength) {
+ Common::StackLock slock(_mutex);
+
+ if (fadeLength <= 0) {
+ _data = 0;
+ _end = true;
+ _playingSound = 0;
+ return;
+ }
+
+ _fade = true;
+ _fadeVol = 65536;
+ _fadeSamples = (int) (fadeLength * (((double) _rate) / 10.0));
+ _fadeVolStep = MAX((int32) 1, (int32) (65536 / _fadeSamples));
+ _curFadeSamples = 0;
+}
+
+void SoundMixer::setRepeating(int32 repCount) {
+ Common::StackLock slock(_mutex);
+
+ _repCount = repCount;
+}
+
+void SoundMixer::setSample(SoundDesc &sndDesc, int16 repCount, int16 frequency,
+ int16 fadeLength) {
+
+ if (frequency <= 0)
+ frequency = sndDesc._frequency;
+
+ sndDesc._repCount = repCount - 1;
+ sndDesc._frequency = frequency;
+
+ _data = (int8 *) sndDesc.getData();
+ _length = sndDesc.size();
+ _freq = frequency;
+
+ _repCount = repCount;
+ _end = false;
+ _playingSound = 1;
+
+ _offset = 0;
+ _offsetFrac = 0;
+ _offsetInc = (_freq << FRAC_BITS) / _rate;
+
+ _last = _cur;
+ _cur = _data[0];
+
+ _curFadeSamples = 0;
+ if (fadeLength == 0) {
+ _fade = false;
+ _fadeVol = 65536;
+ _fadeSamples = 0;
+ _fadeVolStep = 0;
+ } else {
+ _fade = true;
+ _fadeVol = 0;
+ _fadeSamples = (int) (fadeLength * (((double) _rate) / 10.0));
+ _fadeVolStep = - MAX((int32) 1, (int32) (65536 / _fadeSamples));
+ }
+}
+
+void SoundMixer::play(SoundDesc &sndDesc, int16 repCount, int16 frequency,
+ int16 fadeLength) {
+ Common::StackLock slock(_mutex);
+
+ if (!_end)
+ return;
+
+ setSample(sndDesc, repCount, frequency, fadeLength);
+}
+
+void SoundMixer::checkEndSample() {
+ if ((_repCount == -1) || (--_repCount > 0)) {
+ _offset = 0;
+ _offsetFrac = 0;
+ _end = false;
+ _playingSound = 1;
+ } else {
+ _end = true;
+ _playingSound = 0;
+ }
+}
+
+int SoundMixer::readBuffer(int16 *buffer, const int numSamples) {
+ Common::StackLock slock(_mutex);
+
+ for (int i = 0; i < numSamples; i++) {
+ if (!_data)
+ return i;
+ if (_end || (_offset >= _length))
+ checkEndSample();
+ if (_end)
+ return i;
+
+ // Linear interpolation. See sound/rate.cpp
+
+ int16 val = (_last + (((_cur - _last) * _offsetFrac +
+ FRAC_HALF) >> FRAC_BITS)) << 8;
+ *buffer++ = (val * _fadeVol) >> 16;
+
+ _offsetFrac += _offsetInc;
+
+ // Was there an integral change?
+ if (fracToInt(_offsetFrac) > 0) {
+ _last = _cur;
+ _cur = _data[_offset];
+ _offset += fracToInt(_offsetFrac);
+ _offsetFrac &= FRAC_LO_MASK;
+ }
+
+ if (_fade) {
+
+ if (++_curFadeSamples >= _fadeSamples)
+ endFade();
+ else
+ _fadeVol -= _fadeVolStep;
+
+ if (_fadeVol < 0)
+ _fadeVol = 0;
+
+ }
+ }
+ return numSamples;
+}
+
+void SoundMixer::endFade() {
+ if (_fadeVolStep > 0) {
+ _data = 0;
+ _end = true;
+ _playingSound = 0;
+ } else {
+ _fadeVol = 65536;
+ _fade = false;
+ }
+}
+
+} // End of namespace Gob