mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-23 04:33:09 +00:00
EMI: Move handling of pooled sounds to EMISound.
This commit is contained in:
parent
9ee420b0d0
commit
007067c7ad
@ -365,8 +365,8 @@ void Lua_V2::IsSoundPlaying() {
|
||||
}
|
||||
|
||||
PoolSound *sound = PoolSound::getPool().getObject(lua_getuserdata(idObj));
|
||||
if (sound && sound->_track) {
|
||||
if (sound->_track->isPlaying()) {
|
||||
if (sound) {
|
||||
if (sound->isPlaying()) {
|
||||
pushbool(true);
|
||||
return;
|
||||
}
|
||||
@ -454,8 +454,8 @@ void Lua_V2::GetSoundVolume() {
|
||||
return;
|
||||
}
|
||||
PoolSound *sound = PoolSound::getPool().getObject(lua_getuserdata(idObj));
|
||||
if (sound && sound->_track) {
|
||||
lua_pushnumber(sound->_track->getVolume());
|
||||
if (sound) {
|
||||
lua_pushnumber(sound->getVolume());
|
||||
} else {
|
||||
warning("Lua_V2::GetSoundVolume: can't find sound track");
|
||||
lua_pushnumber(Audio::Mixer::kMaxMixerVolume);
|
||||
|
@ -21,78 +21,85 @@
|
||||
*/
|
||||
|
||||
#include "common/str.h"
|
||||
|
||||
#include "engines/grim/emi/sound/emisound.h"
|
||||
#include "engines/grim/emi/poolsound.h"
|
||||
#include "engines/grim/resource.h"
|
||||
|
||||
|
||||
namespace Grim {
|
||||
|
||||
PoolSound::PoolSound() : _filename(""), _track(nullptr) {
|
||||
PoolSound::PoolSound() : _filename(""), _loaded(false), _soundId(0) {
|
||||
}
|
||||
|
||||
PoolSound::PoolSound(const Common::String &filename) : _filename(""), _track(nullptr) {
|
||||
PoolSound::PoolSound(const Common::String &filename) : _filename(""), _loaded(false), _soundId(0) {
|
||||
openFile(filename);
|
||||
}
|
||||
|
||||
// Called when the engine restarts or Lua code calls FreeSound
|
||||
PoolSound::~PoolSound() {
|
||||
if (!_track)
|
||||
return;
|
||||
_track->stop();
|
||||
delete _track;
|
||||
if (_loaded) {
|
||||
g_emiSound->freeLoadedSound(_soundId);
|
||||
}
|
||||
}
|
||||
|
||||
void PoolSound::setVolume(int volume) {
|
||||
if (!_track) {
|
||||
warning("PoolSound::setVolume: no track found");
|
||||
return;
|
||||
if (_loaded) {
|
||||
g_emiSound->setLoadedSoundVolume(_soundId, volume);
|
||||
}
|
||||
_track->setVolume(volume);
|
||||
}
|
||||
|
||||
void PoolSound::setBalance(int balance) {
|
||||
if (!_track) {
|
||||
warning("PoolSound::setBalance: no track found");
|
||||
return;
|
||||
if (_loaded) {
|
||||
g_emiSound->setLoadedSoundPan(_soundId, balance);
|
||||
}
|
||||
_track->setBalance(balance);
|
||||
}
|
||||
void PoolSound::play(bool looping) {
|
||||
if (!_track)
|
||||
return;
|
||||
_track->setLooping(looping);
|
||||
_track->play();
|
||||
if (_loaded) {
|
||||
g_emiSound->playLoadedSound(_soundId);
|
||||
}
|
||||
}
|
||||
|
||||
void PoolSound::stop() {
|
||||
if (!_track)
|
||||
return;
|
||||
_track->stop();
|
||||
if (_loaded) {
|
||||
g_emiSound->stopLoadedSound(_soundId);
|
||||
}
|
||||
}
|
||||
|
||||
int PoolSound::getVolume() {
|
||||
if (_loaded) {
|
||||
return g_emiSound->getLoadedSoundVolume(_soundId);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PoolSound::isPlaying() {
|
||||
if (_loaded) {
|
||||
return g_emiSound->getLoadedSoundStatus(_soundId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PoolSound::openFile(const Common::String &filename) {
|
||||
_filename = filename;
|
||||
_track = new AIFFTrack(Audio::Mixer::kSFXSoundType, DisposeAfterUse::NO);
|
||||
if (!_track->openSound(filename, filename)) {
|
||||
_loaded = g_emiSound->loadSfx(filename.c_str(), _soundId);
|
||||
if (!_loaded) {
|
||||
warning("Could not open PoolSound file %s", filename.c_str());
|
||||
delete _track;
|
||||
_track = nullptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void PoolSound::saveState(SaveGame *state) {
|
||||
if (_track && _track->isStreamOpen()) {
|
||||
state->writeBool(true);
|
||||
state->writeString(_filename);
|
||||
} else {
|
||||
state->writeBool(false);
|
||||
}
|
||||
state->writeBool(_loaded);
|
||||
state->writeLESint32(_soundId);
|
||||
}
|
||||
|
||||
void PoolSound::restoreState(SaveGame *state) {
|
||||
bool hasStream = state->readBool();
|
||||
if (hasStream)
|
||||
openFile(state->readString());
|
||||
if (state->saveMinorVersion() >= 21) {
|
||||
_loaded = state->readBool();
|
||||
_soundId = state->readLESint32();
|
||||
} else {
|
||||
bool hasStream = state->readBool();
|
||||
if (hasStream)
|
||||
openFile(state->readString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,8 @@
|
||||
#ifndef GRIM_POOLSOUND_H
|
||||
#define GRIM_POOLSOUND_H
|
||||
|
||||
#include "common/endian.h"
|
||||
#include "engines/grim/pool.h"
|
||||
#include "engines/grim/emi/sound/aifftrack.h"
|
||||
|
||||
|
||||
namespace Grim {
|
||||
@ -39,12 +39,17 @@ public:
|
||||
void setVolume(int volume);
|
||||
void setBalance(int balance);
|
||||
void stop();
|
||||
int getVolume();
|
||||
bool isPlaying();
|
||||
void saveState(SaveGame *state);
|
||||
void restoreState(SaveGame *state);
|
||||
|
||||
static int32 getStaticTag() { return MKTAG('A','I','F','F'); }
|
||||
AIFFTrack *_track;
|
||||
|
||||
private:
|
||||
Common::String _filename;
|
||||
int _soundId;
|
||||
bool _loaded;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ public:
|
||||
bool openSound(const Common::String &filename, const Common::String &soundName, const Audio::Timestamp *start = nullptr) override;
|
||||
bool isPlaying() override;
|
||||
bool isStreamOpen() { return _stream != NULL; }
|
||||
void setLooping(bool looping);
|
||||
void setLooping(bool looping) override;
|
||||
bool play() override;
|
||||
Audio::Timestamp getPos() override;
|
||||
private:
|
||||
|
@ -62,6 +62,7 @@ EMISound::EMISound(int fps) {
|
||||
}
|
||||
_curMusicState = -1;
|
||||
_musicChannel = -1;
|
||||
_curTrackId = 0;
|
||||
_callbackFps = fps;
|
||||
vimaInit(imuseDestTable);
|
||||
initMusicTable();
|
||||
@ -71,6 +72,7 @@ EMISound::EMISound(int fps) {
|
||||
EMISound::~EMISound() {
|
||||
g_system->getTimerManager()->removeTimerProc(timerHandler);
|
||||
freeAllChannels();
|
||||
freeLoadedSounds();
|
||||
delete[] _channels;
|
||||
delete[] _musicTable;
|
||||
}
|
||||
@ -102,6 +104,13 @@ void EMISound::freeAllChannels() {
|
||||
}
|
||||
}
|
||||
|
||||
void EMISound::freeLoadedSounds() {
|
||||
for (TrackMap::iterator it = _preloadedTrackMap.begin(); it != _preloadedTrackMap.end(); ++it) {
|
||||
delete it->_value;
|
||||
}
|
||||
_preloadedTrackMap.clear();
|
||||
}
|
||||
|
||||
bool EMISound::startVoice(const char *soundName, int volume, int pan) {
|
||||
return startSound(soundName, Audio::Mixer::kSpeechSoundType, volume, pan);
|
||||
}
|
||||
@ -175,13 +184,108 @@ void EMISound::setPan(const char *soundName, int pan) {
|
||||
}
|
||||
}
|
||||
|
||||
bool EMISound::loadSfx(const char *soundName, int &id) {
|
||||
Common::StackLock lock(_mutex);
|
||||
SoundTrack *track = initTrack(soundName, Audio::Mixer::kSFXSoundType);
|
||||
if (track) {
|
||||
id = _curTrackId++;
|
||||
_preloadedTrackMap[id] = track;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void EMISound::playLoadedSound(int id) {
|
||||
Common::StackLock lock(_mutex);
|
||||
TrackMap::iterator it = _preloadedTrackMap.find(id);
|
||||
if (it != _preloadedTrackMap.end()) {
|
||||
it->_value->play();
|
||||
} else {
|
||||
warning("EMISound::playLoadedSound called with invalid sound id");
|
||||
}
|
||||
}
|
||||
|
||||
void EMISound::setLoadedSoundLooping(int id, bool looping) {
|
||||
Common::StackLock lock(_mutex);
|
||||
TrackMap::iterator it = _preloadedTrackMap.find(id);
|
||||
if (it != _preloadedTrackMap.end()) {
|
||||
it->_value->setLooping(looping);
|
||||
} else {
|
||||
warning("EMISound::setLoadedSoundLooping called with invalid sound id");
|
||||
}
|
||||
}
|
||||
|
||||
void EMISound::stopLoadedSound(int id) {
|
||||
Common::StackLock lock(_mutex);
|
||||
TrackMap::iterator it = _preloadedTrackMap.find(id);
|
||||
if (it != _preloadedTrackMap.end()) {
|
||||
it->_value->stop();
|
||||
} else {
|
||||
warning("EMISound::stopLoadedSound called with invalid sound id");
|
||||
}
|
||||
}
|
||||
|
||||
void EMISound::freeLoadedSound(int id) {
|
||||
Common::StackLock lock(_mutex);
|
||||
TrackMap::iterator it = _preloadedTrackMap.find(id);
|
||||
if (it != _preloadedTrackMap.end()) {
|
||||
delete it->_value;
|
||||
_preloadedTrackMap.erase(it);
|
||||
} else {
|
||||
warning("EMISound::freeLoadedSound called with invalid sound id");
|
||||
}
|
||||
}
|
||||
|
||||
void EMISound::setLoadedSoundVolume(int id, int volume) {
|
||||
Common::StackLock lock(_mutex);
|
||||
TrackMap::iterator it = _preloadedTrackMap.find(id);
|
||||
if (it != _preloadedTrackMap.end()) {
|
||||
it->_value->setVolume(volume);
|
||||
} else {
|
||||
warning("EMISound::setLoadedSoundVolume called with invalid sound id");
|
||||
}
|
||||
}
|
||||
|
||||
void EMISound::setLoadedSoundPan(int id, int pan) {
|
||||
Common::StackLock lock(_mutex);
|
||||
TrackMap::iterator it = _preloadedTrackMap.find(id);
|
||||
if (it != _preloadedTrackMap.end()) {
|
||||
it->_value->setBalance(pan);
|
||||
} else {
|
||||
warning("EMISound::setLoadedSoundPan called with invalid sound id");
|
||||
}
|
||||
}
|
||||
|
||||
bool EMISound::getLoadedSoundStatus(int id) {
|
||||
Common::StackLock lock(_mutex);
|
||||
TrackMap::iterator it = _preloadedTrackMap.find(id);
|
||||
if (it != _preloadedTrackMap.end()) {
|
||||
return it->_value->isPlaying();
|
||||
}
|
||||
warning("EMISound::getLoadedSoundStatus called with invalid sound id");
|
||||
return false;
|
||||
}
|
||||
|
||||
int EMISound::getLoadedSoundVolume(int id) {
|
||||
Common::StackLock lock(_mutex);
|
||||
TrackMap::iterator it = _preloadedTrackMap.find(id);
|
||||
if (it != _preloadedTrackMap.end()) {
|
||||
return it->_value->getVolume();
|
||||
}
|
||||
warning("EMISound::getLoadedSoundVolume called with invalid sound id");
|
||||
return false;
|
||||
}
|
||||
|
||||
SoundTrack *EMISound::initTrack(const Common::String &soundName, Audio::Mixer::SoundType soundType, const Audio::Timestamp *start) const {
|
||||
SoundTrack *track;
|
||||
if (soundName.hasSuffix(".scx")) {
|
||||
Common::String soundNameLower(soundName);
|
||||
soundNameLower.toLowercase();
|
||||
if (soundNameLower.hasSuffix(".scx")) {
|
||||
track = new SCXTrack(soundType);
|
||||
} else if (soundName.hasSuffix(".m4b")) {
|
||||
} else if (soundNameLower.hasSuffix(".m4b")) {
|
||||
track = new MP3Track(soundType);
|
||||
} else if (soundName.hasSuffix(".aif")) {
|
||||
} else if (soundNameLower.hasSuffix(".aif")) {
|
||||
track = new AIFFTrack(soundType);
|
||||
} else {
|
||||
track = new VimaTrack();
|
||||
@ -531,12 +635,26 @@ void EMISound::updateTrack(SoundTrack *track) {
|
||||
}
|
||||
}
|
||||
|
||||
void EMISound::flushTracks() {
|
||||
Common::StackLock lock(_mutex);
|
||||
for (int i = 0; i < NUM_CHANNELS; i++) {
|
||||
SoundTrack *track = _channels[i];
|
||||
if (track == nullptr)
|
||||
continue;
|
||||
|
||||
if (!track->isPlaying()) {
|
||||
freeChannel(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EMISound::restoreState(SaveGame *savedState) {
|
||||
Common::StackLock lock(_mutex);
|
||||
// Clear any current music
|
||||
flushStack();
|
||||
setMusicState(0);
|
||||
freeAllChannels();
|
||||
freeLoadedSounds();
|
||||
// Actually load:
|
||||
savedState->beginSection('SOUN');
|
||||
_musicPrefix = savedState->readString();
|
||||
@ -599,6 +717,17 @@ void EMISound::restoreState(SaveGame *savedState) {
|
||||
_channels[i] = restoreTrack(savedState);
|
||||
}
|
||||
}
|
||||
|
||||
// Preloaded sounds:
|
||||
if (savedState->saveMinorVersion() >= 21) {
|
||||
_curTrackId = savedState->readLESint32();
|
||||
uint32 numLoaded = savedState->readLEUint32();
|
||||
for (uint32 i = 0; i < numLoaded; ++i) {
|
||||
int id = savedState->readLESint32();
|
||||
_preloadedTrackMap[id] = restoreTrack(savedState);
|
||||
}
|
||||
}
|
||||
|
||||
savedState->endSection();
|
||||
}
|
||||
|
||||
@ -633,6 +762,16 @@ void EMISound::saveState(SaveGame *savedState) {
|
||||
saveTrack(_channels[i], savedState);
|
||||
}
|
||||
}
|
||||
|
||||
// Preloaded sounds:
|
||||
savedState->writeLESint32(_curTrackId);
|
||||
uint32 numLoaded = _preloadedTrackMap.size();
|
||||
savedState->writeLEUint32(numLoaded);
|
||||
for (TrackMap::iterator it = _preloadedTrackMap.begin(); it != _preloadedTrackMap.end(); ++it) {
|
||||
savedState->writeLESint32(it->_key);
|
||||
saveTrack(it->_value, savedState);
|
||||
}
|
||||
|
||||
savedState->endSection();
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "common/str.h"
|
||||
#include "common/stack.h"
|
||||
#include "common/mutex.h"
|
||||
#include "common/hashmap.h"
|
||||
|
||||
namespace Grim {
|
||||
|
||||
@ -60,6 +61,9 @@ class EMISound {
|
||||
Common::Stack<StackEntry> _stateStack;
|
||||
Common::Mutex _mutex;
|
||||
|
||||
typedef Common::HashMap<int, SoundTrack *> TrackMap;
|
||||
TrackMap _preloadedTrackMap;
|
||||
|
||||
static void timerHandler(void *refConf);
|
||||
void removeItem(SoundTrack *item);
|
||||
int32 getFreeChannel();
|
||||
@ -78,6 +82,16 @@ public:
|
||||
void setVolume(const char *soundName, int volume);
|
||||
void setPan(const char *soundName, int pan); /* pan: 0 .. 127 */
|
||||
|
||||
bool loadSfx(const char *soundName, int &id);
|
||||
void playLoadedSound(int id);
|
||||
void setLoadedSoundLooping(int id, bool looping);
|
||||
void stopLoadedSound(int id);
|
||||
void freeLoadedSound(int id);
|
||||
void setLoadedSoundVolume(int id, int volume);
|
||||
void setLoadedSoundPan(int id, int pan);
|
||||
bool getLoadedSoundStatus(int id);
|
||||
int getLoadedSoundVolume(int id);
|
||||
|
||||
void setMusicState(int stateId);
|
||||
void selectMusicSet(int setId);
|
||||
|
||||
@ -98,7 +112,9 @@ public:
|
||||
private:
|
||||
int _curMusicState;
|
||||
int _callbackFps;
|
||||
int _curTrackId;
|
||||
void freeAllChannels();
|
||||
void freeLoadedSounds();
|
||||
SoundTrack *initTrack(const Common::String &soundName, Audio::Mixer::SoundType soundType, const Audio::Timestamp *start = nullptr) const;
|
||||
bool startSound(const char *soundName, Audio::Mixer::SoundType soundType, int volume, int pan);
|
||||
void saveTrack(SoundTrack *track, SaveGame *savedState);
|
||||
|
@ -86,6 +86,7 @@ public:
|
||||
Common::String getSoundName();
|
||||
void setSoundName(const Common::String &name);
|
||||
virtual bool hasLooped() { return false; }
|
||||
virtual void setLooping(bool looping) { }
|
||||
bool isPaused() const { return _paused; }
|
||||
Audio::Mixer::SoundType getSoundType() const { return _soundType; }
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user