mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-21 09:21:08 +00:00
dd2952850d
The identifiable ones have been given names.
205 lines
5.1 KiB
C++
205 lines
5.1 KiB
C++
/* ResidualVM - A 3D game interpreter
|
|
*
|
|
* ResidualVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the AUTHORS
|
|
* 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 "engines/myst3/ambient.h"
|
|
#include "engines/myst3/database.h"
|
|
#include "engines/myst3/myst3.h"
|
|
#include "engines/myst3/state.h"
|
|
#include "engines/myst3/sound.h"
|
|
|
|
namespace Myst3 {
|
|
|
|
Ambient::Ambient(Myst3Engine *vm) :
|
|
_vm(vm),
|
|
_cueStartTick(0) {
|
|
_cueSheet.reset();
|
|
}
|
|
|
|
Ambient::~Ambient() {
|
|
}
|
|
|
|
void Ambient::playCurrentNode(uint32 volume, uint32 fadeOutDelay) {
|
|
if (!fadeOutDelay) fadeOutDelay = 1;
|
|
|
|
uint32 node = _vm->_state->getLocationNode();
|
|
uint32 room = _vm->_state->getLocationRoom();
|
|
uint32 age = _vm->_state->getLocationAge();
|
|
|
|
// Load sound descriptors
|
|
loadNode(node, room, age);
|
|
|
|
// Adjust volume
|
|
scaleVolume(volume);
|
|
|
|
// Play sounds
|
|
applySounds(fadeOutDelay);
|
|
}
|
|
|
|
void Ambient::scaleVolume(uint32 volume) {
|
|
for (uint i = 0; i < _sounds.size(); i++)
|
|
_sounds[i].volume = _sounds[i].volume * volume / 100;
|
|
}
|
|
|
|
void Ambient::loadNode(uint32 node, uint32 room, uint32 age) {
|
|
_sounds.clear();
|
|
_cueSheet.reset();
|
|
|
|
if (!node)
|
|
node = _vm->_state->getLocationNode();
|
|
|
|
_vm->_state->setAmbiantPreviousFadeOutDelay(_vm->_state->getAmbiantFadeOutDelay());
|
|
|
|
_scriptAge = age;
|
|
_scriptRoom = room;
|
|
|
|
_vm->runAmbientScripts(node);
|
|
|
|
if (_sounds.size() == 0)
|
|
_vm->runAmbientScripts(32766);
|
|
}
|
|
|
|
void Ambient::addSound(uint32 id, int32 volume, int32 heading, int32 headingAngle, int32 u1, int32 fadeOutDelay) {
|
|
if (!volume)
|
|
volume = 1;
|
|
|
|
AmbientSound s;
|
|
|
|
if (volume >= 0) {
|
|
s.volume = volume;
|
|
s.volumeFlag = 0;
|
|
} else {
|
|
s.volume = -volume;
|
|
s.volumeFlag = 1;
|
|
}
|
|
|
|
s.id = id;
|
|
s.heading = heading;
|
|
s.headingAngle = headingAngle;
|
|
s.u1 = u1;
|
|
s.fadeOutDelay = fadeOutDelay;
|
|
|
|
_sounds.push_back(s);
|
|
}
|
|
|
|
void Ambient::setCueSheet(uint32 id, int32 volume, int32 heading, int32 headingAngle) {
|
|
_cueSheet.reset();
|
|
|
|
if (volume >= 0) {
|
|
_cueSheet.volume = volume;
|
|
_cueSheet.volumeFlag = 0;
|
|
} else {
|
|
_cueSheet.volume = -volume;
|
|
_cueSheet.volumeFlag = 1;
|
|
}
|
|
|
|
_cueSheet.id = id;
|
|
_cueSheet.heading = heading;
|
|
_cueSheet.headingAngle = headingAngle;
|
|
}
|
|
|
|
uint16 Ambient::delayForCue(uint32 id) {
|
|
const AmbientCue &cue = _vm->_db->getAmbientCue(id);
|
|
|
|
// Return a delay in frames inside the bounds
|
|
return _vm->_rnd->getRandomNumberRng(cue.minFrames, cue.maxFrames);
|
|
}
|
|
|
|
uint32 Ambient::nextCueSound(uint32 id) {
|
|
static uint32 lastId = 0;
|
|
const AmbientCue &cue = _vm->_db->getAmbientCue(id);
|
|
|
|
// Only one sound, no way it can be different from the previous one
|
|
if (cue.tracks.size() == 1) {
|
|
return cue.tracks[0];
|
|
}
|
|
|
|
// Make sure the new random sound is different from the last one
|
|
uint32 soundId;
|
|
do {
|
|
uint index = _vm->_rnd->getRandomNumber(cue.tracks.size() - 1);
|
|
soundId = cue.tracks[index];
|
|
} while (soundId == lastId);
|
|
|
|
lastId = soundId;
|
|
|
|
return soundId;
|
|
}
|
|
|
|
void Ambient::updateCue() {
|
|
if (_cueSheet.id) {
|
|
if (!_cueStartTick) {
|
|
_cueStartTick = _vm->_state->getTickCount() + delayForCue(_cueSheet.id);
|
|
}
|
|
if (_vm->_state->getTickCount() >= _cueStartTick) {
|
|
_cueStartTick = 0;
|
|
uint32 soundId = nextCueSound(_cueSheet.id);
|
|
|
|
uint heading;
|
|
if (_cueSheet.heading == 32766) {
|
|
heading = _vm->_rnd->getRandomNumberRng(0, 359);
|
|
} else {
|
|
heading = _cueSheet.heading;
|
|
}
|
|
_vm->_sound->playCue(soundId, _cueSheet.volume, heading, _cueSheet.headingAngle);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Ambient::applySounds(uint32 fadeOutDelay) {
|
|
// Reset the random sounds
|
|
_cueStartTick = 0;
|
|
if (!_cueSheet.id) {
|
|
_vm->_sound->stopCue(fadeOutDelay);
|
|
}
|
|
|
|
// Age all sounds
|
|
_vm->_sound->age();
|
|
|
|
// Setup the selected sounds
|
|
for (uint i = 0; i < _sounds.size(); i++) {
|
|
const AmbientSound &sound = _sounds[i];
|
|
|
|
bool existingChannel;
|
|
SoundChannel *channel = _vm->_sound->getChannelForSound(sound.id, kAmbient, &existingChannel);
|
|
|
|
// The sound was already playing
|
|
if (!existingChannel) {
|
|
uint volume = 0;
|
|
// if (sound.volumeFlag) // TODO: Used in the original
|
|
volume = sound.volume;
|
|
|
|
channel->play(sound.id, volume, sound.heading, sound.headingAngle, true, kAmbient);
|
|
}
|
|
|
|
if (channel->_playing) {
|
|
channel->fade(sound.volume, sound.heading, sound.headingAngle, fadeOutDelay);
|
|
channel->_age = 0;
|
|
channel->_ambientFadeOutDelay = sound.fadeOutDelay;
|
|
}
|
|
}
|
|
|
|
// Fade out old playing ambient sounds
|
|
_vm->_sound->fadeOutOldSounds(fadeOutDelay);
|
|
}
|
|
|
|
} // End of namespace Myst3
|