scummvm/engines/dreamweb/sound.cpp
D G Turner d9983a6224 DREAMWEB: Cleanup of debugging code and formatting in sound code.
This commit removes various temporary debugging output, cleans up
some points of formatting and replaces some hexadecimal sizes and
offsets with decimal for readability.
2012-06-02 07:03:40 +01:00

288 lines
7.6 KiB
C++

/* 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.
*
*/
#include "audio/decoders/raw.h"
#include "common/config-manager.h"
#include "common/debug.h"
#include "common/file.h"
#include "dreamweb/dreamweb.h"
#include "dreamweb/sound.h"
namespace DreamWeb {
DreamWebSound::DreamWebSound(DreamWebEngine *vm) : _vm(vm) {
_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
_vm->_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
_channel0 = 0;
_channel1 = 0;
_currentSample = 0xff;
_channel0Playing = 0;
_channel0Repeat = 0;
_channel1Playing = 255;
_volume = 0;
_volumeTo = 0;
_volumeDirection = 0;
_volumeCount = 0;
}
DreamWebSound::~DreamWebSound() {
}
bool DreamWebSound::loadSpeech(byte type1, int idx1, byte type2, int idx2) {
cancelCh1();
Common::String name = Common::String::format("%c%02d%c%04d.RAW", type1, idx1, type2, idx2);
debug(2, "loadSpeech() name:%s", name.c_str());
return loadSpeech(name);
}
void DreamWebSound::volumeChange(uint8 value, int8 direction) {
_volumeTo = value;
_volumeDirection = direction;
}
void DreamWebSound::volumeAdjust() {
if (_volumeDirection == 0)
return;
if (_volume != _volumeTo) {
_volumeCount += 64;
// Only modify the volume every 256/64 = 4th time around
if (_volumeCount == 0)
_volume += _volumeDirection;
} else {
_volumeDirection = 0;
}
}
void DreamWebSound::playChannel0(uint8 index, uint8 repeat) {
debug(1, "playChannel0(index:%d, repeat:%d)", index, repeat);
_channel0Playing = index;
_channel0Repeat = repeat;
}
void DreamWebSound::playChannel1(uint8 index) {
debug(1, "playChannel1(index:%d)", index);
if (_channel1Playing == 7)
return;
_channel1Playing = index;
}
void DreamWebSound::cancelCh0() {
debug(1, "cancelCh0()");
_channel0Playing = 255;
_channel0Repeat = 0;
stopSound(0);
}
void DreamWebSound::cancelCh1() {
debug(1, "cancelCh1()");
_channel1Playing = 255;
stopSound(1);
}
void DreamWebSound::loadRoomsSample(uint8 sample) {
debug(1, "loadRoomsSample(sample:%d)", sample);
if (sample == 255 || _currentSample == sample)
return; // loaded already
assert(sample < 100);
Common::String sampleSuffix = Common::String::format("V%02d", sample);
_currentSample = sample;
uint8 ch0 = _channel0Playing;
if (ch0 >= 12 && ch0 != 255)
cancelCh0();
uint8 ch1 = _channel1Playing;
if (ch1 >= 12)
cancelCh1();
loadSounds(1, sampleSuffix.c_str());
}
void DreamWebSound::playSound(uint8 channel, uint8 id, uint8 loops) {
debug(1, "playSound(channel:%u, id:%u, loops:%u)", channel, id, loops);
int bank = 0;
bool speech = false;
Audio::Mixer::SoundType type = channel == 0?
Audio::Mixer::kMusicSoundType: Audio::Mixer::kSFXSoundType;
if (id >= 12) {
id -= 12;
bank = 1;
if (id == 50) {
speech = true;
type = Audio::Mixer::kSpeechSoundType;
}
}
const SoundData &data = _soundData[bank];
Audio::SeekableAudioStream *raw;
if (!speech) {
if (id >= data.samples.size() || data.samples[id].size == 0) {
warning("invalid sample #%u played", id);
return;
}
const Sample &sample = data.samples[id];
uint8 *buffer = (uint8 *)malloc(sample.size);
if (!buffer)
error("out of memory: cannot allocate memory for sound(%u bytes)", sample.size);
memcpy(buffer, data.data.begin() + sample.offset, sample.size);
raw = Audio::makeRawStream(buffer, sample.size, 22050, Audio::FLAG_UNSIGNED);
} else {
uint8 *buffer = (uint8 *)malloc(_speechData.size());
if (!buffer)
error("out of memory: cannot allocate memory for sound(%u bytes)", _speechData.size());
memcpy(buffer, _speechData.begin(), _speechData.size());
raw = Audio::makeRawStream(buffer, _speechData.size(), 22050, Audio::FLAG_UNSIGNED);
}
Audio::AudioStream *stream;
if (loops > 1) {
stream = new Audio::LoopingAudioStream(raw, (loops < 255) ? loops : 0);
} else
stream = raw;
if (_vm->_mixer->isSoundHandleActive(_channelHandle[channel]))
_vm->_mixer->stopHandle(_channelHandle[channel]);
_vm->_mixer->playStream(type, &_channelHandle[channel], stream);
}
void DreamWebSound::stopSound(uint8 channel) {
debug(1, "stopSound(%u)", channel);
assert(channel == 0 || channel == 1);
_vm->_mixer->stopHandle(_channelHandle[channel]);
if (channel == 0)
_channel0 = 0;
else
_channel1 = 0;
}
bool DreamWebSound::loadSpeech(const Common::String &filename) {
if (!_vm->hasSpeech())
return false;
Common::File file;
if (!file.open(_vm->getSpeechDirName() + "/" + filename))
return false;
debug(1, "loadSpeech(%s)", filename.c_str());
uint size = file.size();
_speechData.resize(size);
file.read(_speechData.begin(), size);
file.close();
return true;
}
void DreamWebSound::soundHandler() {
_vm->_subtitles = ConfMan.getBool("subtitles");
volumeAdjust();
uint volume = _volume;
//.vol file loaded into soundbuf:0x4000
//volume table at (volume * 0x100 + 0x3f00)
//volume value could be from 1 to 7
//1 - 0x10-0xff
//2 - 0x1f-0xdf
//3 - 0x2f-0xd0
//4 - 0x3e-0xc1
//5 - 0x4d-0xb2
//6 - 0x5d-0xa2
//7 - 0x6f-0x91
if (volume >= 8)
volume = 7;
volume = (8 - volume) * Audio::Mixer::kMaxChannelVolume / 8;
_vm->_mixer->setChannelVolume(_channelHandle[0], volume);
uint8 ch0 = _channel0Playing;
if (ch0 == 255)
ch0 = 0;
uint8 ch1 = _channel1Playing;
if (ch1 == 255)
ch1 = 0;
uint8 ch0loop = _channel0Repeat;
if (_channel0 != ch0) {
_channel0 = ch0;
if (ch0) {
playSound(0, ch0, ch0loop);
}
}
if (_channel1 != ch1) {
_channel1 = ch1;
if (ch1) {
playSound(1, ch1, 1);
}
}
if (!_vm->_mixer->isSoundHandleActive(_channelHandle[0])) {
_channel0Playing = 255;
_channel0 = 0;
}
if (!_vm->_mixer->isSoundHandleActive(_channelHandle[1])) {
_channel1Playing = 255;
_channel1 = 0;
}
}
void DreamWebSound::loadSounds(uint bank, const Common::String &suffix) {
Common::String filename = _vm->getDatafilePrefix() + suffix;
debug(1, "loadSounds(%u, %s)", bank, filename.c_str());
Common::File file;
if (!file.open(filename)) {
warning("cannot open %s", filename.c_str());
return;
}
uint8 header[96];
file.read(header, sizeof(header));
uint tablesize = READ_LE_UINT16(header + 50);
debug(1, "table size = %u", tablesize);
SoundData &soundData = _soundData[bank];
soundData.samples.resize(tablesize / 6);
uint total = 0;
for (uint i = 0; i < tablesize / 6; ++i) {
uint8 entry[6];
Sample &sample = soundData.samples[i];
file.read(entry, sizeof(entry));
sample.offset = entry[0] * 16384 + READ_LE_UINT16(entry + 1);
sample.size = READ_LE_UINT16(entry + 3) * 2048;
total += sample.size;
debug(1, "offset: %08x, size: %u", sample.offset, sample.size);
}
soundData.data.resize(total);
file.read(soundData.data.begin(), total);
file.close();
}
} // End of namespace DreamWeb