/* 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 3 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, see .
*
*/
#include "lastexpress/lastexpress.h"
#include "audio/decoders/raw.h"
namespace LastExpress {
void SoundManager::soundDriverInit() {
_stream = Audio::makeQueuingAudioStream(22050, _engine->_mixer->getOutputStereo());
memset(_soundMixBuffer, 0, 1470 * sizeof(int16));
_mixer->playStream(
Audio::Mixer::kPlainSoundType,
&_channelHandle,
_stream,
-1,
Audio::Mixer::kMaxChannelVolume
);
// The following is a way to adapt the amount of buffers to the current device capabilities.
// Re-adapted from my own code found within the Digital iMUSE subsystem from the SCUMM engine.
_maxQueuedStreams = (uint32)ceil((_mixer->getOutputBufSize() / 1470) / ((float)_mixer->getOutputRate() / 44100));
if (_mixer->getOutputRate() % 44100) {
_maxQueuedStreams++;
}
_maxQueuedStreams = MAX(4, _maxQueuedStreams);
}
void SoundManager::soundDriverCopyBuffersToDevice() {
_sound30HzCounter++;
while (_stream->numQueuedStreams() < _maxQueuedStreams) {
byte *ptr = (byte *)malloc(1470 * sizeof(int16));
assert(ptr);
mixEngine();
memcpy(ptr, _soundMixBuffer, 1470 * sizeof(int16));
byte flags = Audio::FLAG_16BITS;
if (_mixer->getOutputStereo()) {
flags |= Audio::FLAG_STEREO;
}
#ifdef SCUMM_LITTLE_ENDIAN
flags |= Audio::FLAG_LITTLE_ENDIAN;
#endif
_stream->queueBuffer(ptr, 1470 * sizeof(int16), DisposeAfterUse::YES, flags);
}
}
int SoundManager::soundDriverGetVolume() {
// I know, this thing could have been a look-up table :-)
// Still, I want this to be completely clear and transparent.
int scummVMVolume = _mixer->getChannelVolume(_channelHandle);
// Convert driver volume (0-255) to DirectSound format (-10000 to 0)
double dsVolume;
if (scummVMVolume == 0) {
dsVolume = -10000; // Silence
} else {
// Convert from linear scale to dB
dsVolume = (2000 * log10((double)scummVMVolume / 255.0));
}
// Convert DirectSound scale to game scale (0-7)
int engineVolume;
if (dsVolume <= -3000) {
engineVolume = 0;
} else {
engineVolume = (int)round((7 * (dsVolume + 3000)) / 3000);
}
return engineVolume;
}
void SoundManager::soundDriverSetVolume(int volume) {
// Convert from game scale (0-7) to DirectSound scale (-10000 to 0)
int32 dsVolume;
if (volume == 0) {
dsVolume = -10000; // Silence
} else {
dsVolume = 3000 * volume / 7 - 3000;
}
// Convert DirectSound volume to ScummVM volume (0-255)
int scummVMVolume = (int)round(pow(10, dsVolume / 2000.0) * 255.0);
assert(scummVMVolume >= 0 && scummVMVolume < 256);
_mixer->setChannelVolume(_channelHandle, (byte)scummVMVolume);
}
int32 SoundManager::getSoundDriverTicks() {
Common::StackLock lock(*_engine->_soundMutex);
return _soundDriverTicks;
}
void SoundManager::setSoundDriverTicks(int32 value) {
Common::StackLock lock(*_engine->_soundMutex);
_soundDriverTicks = value;
}
int32 SoundManager::getSoundDriver30HzCounter() {
Common::StackLock lock(*_engine->_soundMutex);
return _sound30HzCounter;
}
int32 SoundManager::getSoundDriverFlags() {
Common::StackLock lock(*_engine->_soundMutex);
return _soundDriverFlags;
}
void SoundManager::addSoundDriverFlags(int32 flags) {
Common::StackLock lock(*_engine->_soundMutex);
_soundDriverFlags |= flags;
}
void SoundManager::removeSoundDriverFlags(int32 flags) {
Common::StackLock lock(*_engine->_soundMutex);
_soundDriverFlags &= ~flags;
}
bool SoundManager::isCopyingDataToSoundDriver() {
Common::StackLock lock(*_engine->_soundMutex);
return _copyingDataToSoundDriver;
}
} // End of namespace LastExpress