/* 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 "common/debug.h"
#include "audio/mixer.h"
#include "audio/mixer_intern.h"
#include "audio/audiostream.h"
#include "audio/decoders/vorbis.h"
#include "audio/decoders/wave.h"
#include "twp/twp.h"
#include "twp/audio.h"
#include "twp/object.h"
#include "twp/resmanager.h"
#include "twp/room.h"
#include "twp/squtil.h"
namespace Twp {
void SoundStream::open(Common::SharedPtr sndDef) {
sndDef->load();
_stream.open(sndDef->_buffer.data(), sndDef->_buffer.size());
}
uint32 SoundStream::read(void *dataPtr, uint32 dataSize) {
return _stream.read(dataPtr, dataSize);
}
bool SoundStream::eos() const {
return _stream.eos();
}
int64 SoundStream::pos() const {
return _stream.pos();
}
int64 SoundStream::size() const {
return _stream.size();
}
bool SoundStream::seek(int64 offset, int whence) {
return _stream.seek(offset, whence);
}
SoundDefinition::SoundDefinition(const Common::String &name) : _name(name), _id(g_twp->_resManager->newSoundDefId()) {
}
void SoundDefinition::load() {
if (!_loaded) {
GGPackEntryReader entry;
entry.open(*g_twp->_pack, _name);
_buffer.resize(entry.size());
entry.read(_buffer.data(), entry.size());
}
}
bool AudioSystem::playing(int id) const {
// channel ID ?
if (id >= 1 && id <= NUM_AUDIO_SLOTS) {
if (!_slots[id - 1].busy)
return false;
id = g_twp->_mixer->getSoundID(_slots[id - 1].handle);
}
// sound definition ID ?
for (const auto &_slot : _slots) {
if (_slot.busy && ((_slot.id == id) || (_slot.sndDef->getId() == id))) {
return g_twp->_mixer->isSoundHandleActive(_slot.handle);
}
}
// sound ID ?
return g_twp->_mixer->isSoundIDActive(id);
}
bool AudioSystem::playing(Common::SharedPtr soundDef) const {
for (const auto &_slot : _slots) {
if (_slot.busy && _slot.sndDef == soundDef) {
return g_twp->_mixer->isSoundHandleActive(_slot.handle);
}
}
return false;
}
void AudioSystem::fadeOut(int id, float fadeTime) {
if (fadeTime < 0.01f) {
stop(id);
} else {
for (int i = 0; i < NUM_AUDIO_SLOTS; i++) {
if (_slots[i].busy && ((_slots[i].id == id) || (_slots[i].sndDef->getId() == id))) {
_slots[i].fadeOutTimeMs = fadeTime * 1000.f;
}
}
}
}
void AudioSystem::stop(int id) {
// channel ID ?
if (id >= 1 && id <= NUM_AUDIO_SLOTS) {
if (!_slots[id - 1].busy)
return;
_slots[id - 1].loopTimes = 0;
_slots[id - 1].busy = false;
g_twp->_mixer->stopHandle(_slots[id - 1].handle);
return;
}
// sound ID or sound definition ID ?
for (auto &slot : _slots) {
if (slot.busy && ((slot.id == id) || (slot.sndDef->getId() == id))) {
slot.loopTimes = 0;
slot.busy = false;
g_twp->_mixer->stopHandle(slot.handle);
}
}
}
void AudioSystem::setMasterVolume(float vol) {
_masterVolume = CLIP(vol, 0.f, 1.f);
// update sounds
for (auto &_slot : _slots) {
if (_slot.busy && g_twp->_mixer->isSoundHandleActive(_slot.handle)) {
g_twp->_mixer->setChannelVolume(_slot.handle, _slot.volume * _masterVolume);
}
}
}
float AudioSystem::getMasterVolume() const {
return _masterVolume;
}
void AudioSystem::updateVolume(AudioSlot *slot) {
float vol = _masterVolume;
if (slot->fadeInTimeMs) {
// apply fade time
vol *= (((float)g_twp->_mixer->getElapsedTime(slot->handle).msecs()) / slot->total);
} else {
// no fade time => use the default volume
vol *= slot->volume;
}
if (slot->fadeOutTimeMs) {
float startFade = slot->total - slot->fadeOutTimeMs;
float progress = (g_twp->_mixer->getElapsedTime(slot->handle).msecs() - startFade) / slot->fadeOutTimeMs;
if ((progress >= 0) && (progress <= 1.f)) {
vol *= (1.f - progress);
}
if (progress > 1.0f) {
slot->loopTimes = 0;
slot->busy = false;
g_twp->_mixer->stopHandle(slot->handle);
return;
}
}
if (slot->objId) {
Common::SharedPtr