mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
351 lines
9.3 KiB
C++
351 lines
9.3 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 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 <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "lastexpress/sound/queue.h"
|
|
|
|
#include "lastexpress/game/logic.h"
|
|
#include "lastexpress/game/state.h"
|
|
|
|
#include "lastexpress/sound/entry.h"
|
|
#include "lastexpress/sound/sound.h"
|
|
|
|
#include "lastexpress/helpers.h"
|
|
#include "lastexpress/lastexpress.h"
|
|
|
|
namespace LastExpress {
|
|
|
|
SoundQueue::SoundQueue(LastExpressEngine *engine) : _engine(engine) {
|
|
_ambientState = 0;
|
|
_currentTag = kSoundTagFirstNormal;
|
|
_flag = 0;
|
|
|
|
_subtitlesFlag = 0;
|
|
_currentSubtitle = nullptr;
|
|
//_soundCacheData = NULL;
|
|
}
|
|
|
|
SoundQueue::~SoundQueue() {
|
|
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i)
|
|
SAFE_DELETE(*i);
|
|
_soundList.clear();
|
|
|
|
for (Common::List<SubtitleEntry *>::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i)
|
|
SAFE_DELETE(*i);
|
|
_subtitles.clear();
|
|
|
|
_currentSubtitle = nullptr;
|
|
//SAFE_DELETE(_soundCacheData);
|
|
|
|
// Zero passed pointers
|
|
_engine = nullptr;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Sound queue management
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SoundQueue::addToQueue(SoundEntry *entry) {
|
|
_soundList.push_back(entry);
|
|
}
|
|
|
|
void SoundQueue::stop(EntityIndex entity) {
|
|
SoundEntry *entry = getEntry(entity);
|
|
if (entry)
|
|
entry->kill();
|
|
}
|
|
|
|
void SoundQueue::stop(Common::String filename) {
|
|
SoundEntry *entry = getEntry(filename);
|
|
if (entry)
|
|
entry->kill();
|
|
}
|
|
|
|
void SoundQueue::updateQueue() {
|
|
if (getAmbientState() & kAmbientSoundEnabled) {
|
|
SoundEntry *entry = getEntry(kSoundTagAmbient);
|
|
if (!entry || getFlags()->flag_3 || (entry && entry->getTime() > getSound()->getAmbientSoundDuration())) {
|
|
getSound()->playAmbientSound(0x45);
|
|
} else {
|
|
if (getSound()->needToChangeAmbientVolume()) {
|
|
entry->setVolumeSmoothly(getSound()->getChangedAmbientVolume());
|
|
getSound()->clearAmbientVolumeChange();
|
|
}
|
|
}
|
|
}
|
|
|
|
for (Common::List<SoundEntry *>::iterator it = _soundList.begin(); it != _soundList.end(); ++it) {
|
|
SoundEntry *entry = *it;
|
|
if (entry == nullptr)
|
|
error("[SoundQueue::updateQueue] Invalid entry found in sound queue");
|
|
|
|
// Original removes the entry data from the cache and sets the archive as not loaded
|
|
// and if the sound data buffer is not full, loads a new entry to be played based on
|
|
// its priority and volume
|
|
|
|
if (!entry->update() && !(entry->getStatus() & kSoundFlagKeepAfterFinish)) {
|
|
entry->close();
|
|
SAFE_DELETE(entry);
|
|
it = _soundList.reverse_erase(it);
|
|
}
|
|
}
|
|
|
|
// Original update the current entry, loading another set of samples to be decoded
|
|
|
|
getFlags()->flag_3 = false;
|
|
}
|
|
|
|
void SoundQueue::stopAmbient() {
|
|
_ambientState = 0;
|
|
|
|
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
|
|
if ((*i)->getTag() == kSoundTagAmbient) {
|
|
(*i)->kill();
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
|
|
if ((*i)->getTag() == kSoundTagOldAmbient) {
|
|
(*i)->kill();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SoundQueue::stopAllExcept(SoundTag tag1, SoundTag tag2) {
|
|
if (!tag2)
|
|
tag2 = tag1;
|
|
|
|
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
|
|
if ((*i)->getTag() != tag1 && (*i)->getTag() != tag2)
|
|
(*i)->kill();
|
|
}
|
|
}
|
|
|
|
void SoundQueue::destroyAllSound() {
|
|
_flag |= 8;
|
|
|
|
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
|
|
SoundEntry *entry = (*i);
|
|
if (entry == nullptr)
|
|
error("[SoundQueue::destroyAllSound] Invalid entry found in sound queue");
|
|
|
|
// Delete entry
|
|
entry->kill();
|
|
SAFE_DELETE(entry);
|
|
|
|
i = _soundList.reverse_erase(i);
|
|
}
|
|
|
|
updateSubtitles();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// State
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SoundQueue::stopAll() {
|
|
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i)
|
|
(*i)->close();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Entry management
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SoundQueue::assignNISLink(EntityIndex index) {
|
|
SoundEntry *entry = getEntry(kSoundTagLink);
|
|
if (entry)
|
|
entry->setEntity(index);
|
|
}
|
|
|
|
void SoundQueue::fade(EntityIndex entity) {
|
|
SoundEntry *entry = getEntry(entity);
|
|
if (entry) {
|
|
entry->fade();
|
|
entry->setEntity(kEntityPlayer);
|
|
}
|
|
}
|
|
|
|
void SoundQueue::fade(SoundTag tag) {
|
|
SoundEntry *entry = getEntry(tag);
|
|
if (entry)
|
|
entry->fade();
|
|
}
|
|
|
|
void SoundQueue::fade(Common::String filename) {
|
|
SoundEntry *entry = getEntry(filename);
|
|
if (entry) {
|
|
entry->fade();
|
|
entry->setEntity(kEntityPlayer);
|
|
}
|
|
}
|
|
|
|
void SoundQueue::endAmbient() {
|
|
_ambientState = 0;
|
|
|
|
fade(kSoundTagAmbient);
|
|
fade(kSoundTagOldAmbient);
|
|
}
|
|
|
|
SoundEntry *SoundQueue::getEntry(EntityIndex index) {
|
|
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
|
|
if ((*i)->getEntity() == index)
|
|
return *i;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
SoundEntry *SoundQueue::getEntry(Common::String name) {
|
|
if (!name.contains('.'))
|
|
name += ".SND";
|
|
|
|
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
|
|
if ((*i)->getName().equalsIgnoreCase(name))
|
|
return *i;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
SoundEntry *SoundQueue::getEntry(SoundTag tag) {
|
|
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i) {
|
|
if ((*i)->getTag() == tag)
|
|
return *i;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
uint32 SoundQueue::getEntryTime(EntityIndex index) {
|
|
SoundEntry *entry = getEntry(index);
|
|
if (entry)
|
|
return entry->getTime();
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool SoundQueue::isBuffered(EntityIndex entity) {
|
|
return (getEntry(entity) != nullptr);
|
|
}
|
|
|
|
bool SoundQueue::isBuffered(Common::String filename, bool testForEntity) {
|
|
SoundEntry *entry = getEntry(filename);
|
|
|
|
if (testForEntity)
|
|
return entry != nullptr && entry->getEntity() != kEntityPlayer;
|
|
|
|
return (entry != nullptr);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Subtitles
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SoundQueue::updateSubtitles() {
|
|
uint32 index = 0;
|
|
SubtitleEntry *subtitle = nullptr;
|
|
|
|
for (Common::List<SubtitleEntry *>::iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
|
|
uint32 current_index = 0;
|
|
SoundEntry *soundEntry = (*i)->getSoundEntry();
|
|
SoundFlag status = (SoundFlag)soundEntry->getStatus();
|
|
|
|
if (!(status & kSoundFlagPlaying)
|
|
|| status & kSoundFlagMute
|
|
|| soundEntry->getTime() == 0
|
|
|| (status & kSoundVolumeMask) < kVolume6
|
|
|| ((getFlags()->nis & 0x8000) && soundEntry->getPriority() < 90)) {
|
|
current_index = 0;
|
|
} else {
|
|
current_index = soundEntry->getPriority() + (status & kSoundVolumeMask);
|
|
|
|
if (_currentSubtitle == (*i))
|
|
current_index += 4;
|
|
}
|
|
|
|
if (index < current_index) {
|
|
index = current_index;
|
|
subtitle = (*i);
|
|
}
|
|
}
|
|
|
|
if (_currentSubtitle == subtitle) {
|
|
if (subtitle)
|
|
subtitle->setupAndDraw();
|
|
|
|
return;
|
|
}
|
|
|
|
if (!subtitle)
|
|
return;
|
|
|
|
if (_subtitlesFlag & 1)
|
|
subtitle->drawOnScreen();
|
|
|
|
subtitle->loadData();
|
|
subtitle->setupAndDraw();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Savegame
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SoundQueue::saveLoadWithSerializer(Common::Serializer &s) {
|
|
s.syncAsUint32LE(_ambientState);
|
|
s.syncAsUint32LE(_currentTag);
|
|
|
|
// Save or load each entry data
|
|
if (s.isSaving()) {
|
|
// Compute the number of entries to save
|
|
uint32 numEntries = count();
|
|
s.syncAsUint32LE(numEntries);
|
|
|
|
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i)
|
|
if ((*i)->needSaving())
|
|
(*i)->saveLoadWithSerializer(s);
|
|
} else {
|
|
uint32 numEntries;
|
|
s.syncAsUint32LE(numEntries);
|
|
for (uint32 i = 0; i < numEntries; i++) {
|
|
SoundEntry* entry = new SoundEntry(_engine);
|
|
entry->saveLoadWithSerializer(s);
|
|
addToQueue(entry);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
uint32 SoundQueue::count() {
|
|
uint32 numEntries = 0;
|
|
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i)
|
|
if ((*i)->needSaving())
|
|
++numEntries;
|
|
|
|
return numEntries;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Debug
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SoundQueue::stopAllSound() {
|
|
for (Common::List<SoundEntry *>::iterator i = _soundList.begin(); i != _soundList.end(); ++i)
|
|
(*i)->getSoundStream()->stop();
|
|
}
|
|
|
|
} // End of namespace LastExpress
|