1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-16 18:14:05 +02:00

looped background soundtrack, playing both underwater and soundtrack at the same time

This commit is contained in:
XProger
2018-03-11 04:51:13 +03:00
parent 406c89e6cf
commit 13e8442ffd
3 changed files with 69 additions and 75 deletions

View File

@@ -91,8 +91,8 @@ struct IGame {
virtual bool invChooseKey(int playerIndex, TR::Entity::Type hole) { return false; } virtual bool invChooseKey(int playerIndex, TR::Entity::Type hole) { return false; }
virtual Sound::Sample* playSound(int id, const vec3 &pos = vec3(0.0f), int flags = 0) const { return NULL; } virtual Sound::Sample* playSound(int id, const vec3 &pos = vec3(0.0f), int flags = 0) const { return NULL; }
virtual void playTrack(uint8 track, bool restart = false) {} virtual void playTrack(uint8 track) {}
virtual void stopTrack() {} virtual void stopTrack() {}
}; };
struct Controller { struct Controller {

View File

@@ -57,9 +57,9 @@ namespace Game {
shaderCache = NULL; shaderCache = NULL;
level = NULL; level = NULL;
Core::init();
Sound::callback = stopChannel; Sound::callback = stopChannel;
Core::init();
Core::settings.version = SETTINGS_READING; Core::settings.version = SETTINGS_READING;
Stream::cacheRead("settings", loadSettings, lvl); Stream::cacheRead("settings", loadSettings, lvl);
} }

View File

@@ -41,11 +41,8 @@ struct Level : IGame {
AmbientCache *ambientCache; AmbientCache *ambientCache;
WaterCache *waterCache; WaterCache *waterCache;
Sound::Sample *sndSoundtrack; Sound::Sample *sndTrack, *sndWater;
Sound::Sample *sndUnderwater; bool waitTrack;
Sound::Sample *sndCurrent;
bool waitSoundtrack;
bool playNextTrack;
bool lastTitle; bool lastTitle;
bool isEnded; bool isEnded;
@@ -62,7 +59,7 @@ struct Level : IGame {
virtual void loadLevel(TR::LevelID id) { virtual void loadLevel(TR::LevelID id) {
if (isEnded) return; if (isEnded) return;
sndCurrent = sndUnderwater = sndSoundtrack = NULL; sndWater = sndTrack = NULL;
Sound::stopAll(); Sound::stopAll();
isEnded = true; isEnded = true;
@@ -190,7 +187,7 @@ struct Level : IGame {
uint8 track = level.state.flags.track; uint8 track = level.state.flags.track;
level.state.flags.track = 0; level.state.flags.track = 0;
playTrack(track, true); playTrack(track);
} }
delete[] data; delete[] data;
@@ -572,54 +569,64 @@ struct Level : IGame {
} }
void stopChannel(Sound::Sample *channel) { void stopChannel(Sound::Sample *channel) {
if (channel == sndSoundtrack) { if (channel == sndTrack) {
if (sndCurrent == sndSoundtrack) sndTrack = NULL;
sndCurrent = NULL; if (level.state.flags.track == TR::LEVEL_INFO[level.id].ambientTrack) // play ambient track
sndSoundtrack = NULL; playTrack(0);
playNextTrack = true;
} }
} }
struct TrackRequest {
Level *level;
int flags;
TrackRequest(Level *level, int flags) : level(level), flags(flags) {}
};
static void playAsync(Stream *stream, void *userData) { static void playAsync(Stream *stream, void *userData) {
Level *level = (Level*)userData; TrackRequest *req = (TrackRequest*)userData;
level->waitSoundtrack = false; Level *level = req->level;
if (!stream) return; level->waitTrack = false;
if (stream) {
level->sndSoundtrack = Sound::play(stream, vec3(0.0f), 0.01f, 1.0f, Sound::MUSIC); level->sndTrack = Sound::play(stream, vec3(0.0f), 0.01f, 1.0f, req->flags);
if (level->sndSoundtrack) { if (level->sndTrack) {
if (level->level.isCutsceneLevel()) { if (level->level.isCutsceneLevel()) {
// level->sndSoundtrack->setVolume(0.0f, 0.0f); Core::resetTime();
// level->sndCurrent = level->sndSoundtrack; }
Core::resetTime(); level->sndTrack->volume = level->sndTrack->volumeTarget = 0.0f;
} }
level->sndSoundtrack->setVolume(1.0f, 0.2f);
} }
delete req;
} }
virtual void playTrack(uint8 track, bool restart = false) { virtual void playTrack(uint8 track) {
if (track == 0) if (track == 0)
track = TR::LEVEL_INFO[level.id].ambientTrack; track = TR::LEVEL_INFO[level.id].ambientTrack;
if (level.state.flags.track == track) { if (level.state.flags.track == track) {
if (restart && sndSoundtrack) { if (sndTrack) {
sndSoundtrack->replay(); sndTrack->replay();
sndSoundtrack->setVolume(1.0f, 0.2f); sndTrack->setVolume(1.0f, 0.2f);
} }
return; return;
} }
level.state.flags.track = track; level.state.flags.track = track;
if (sndSoundtrack) { if (sndTrack) {
sndSoundtrack->setVolume(-1.0f, 0.2f); sndTrack->setVolume(-1.0f, 0.2f);
if (sndCurrent == sndSoundtrack) sndTrack = NULL;
sndCurrent = NULL;
sndSoundtrack = NULL;
} }
if (track == 0xFF) return; if (track == 0xFF) return;
waitSoundtrack = true; int flags = Sound::MUSIC;
getGameTrack(level.version, track, playAsync, this); if (track == TR::LEVEL_INFO[level.id].ambientTrack)
flags |= Sound::LOOP;
waitTrack = true;
getGameTrack(level.version, track, playAsync, new TrackRequest(this, flags));
} }
virtual void stopTrack() { virtual void stopTrack() {
@@ -627,7 +634,7 @@ struct Level : IGame {
} }
//============================== //==============================
Level(Stream &stream) : level(stream), inventory(this), isEnded(false), cutsceneWaitTimer(0.0f), animTexTimer(0.0f) { Level(Stream &stream) : level(stream), inventory(this), waitTrack(false), isEnded(false), cutsceneWaitTimer(0.0f), animTexTimer(0.0f) {
#ifdef _PSP #ifdef _PSP
Core::freeEDRAM(); Core::freeEDRAM();
#endif #endif
@@ -657,7 +664,6 @@ struct Level : IGame {
player = players[0]; player = players[0];
camera = player->camera; camera = player->camera;
zoneCache = new ZoneCache(this); zoneCache = new ZoneCache(this);
ambientCache = Core::settings.detail.lighting > Core::Settings::MEDIUM ? new AmbientCache(this) : NULL; ambientCache = Core::settings.detail.lighting > Core::Settings::MEDIUM ? new AmbientCache(this) : NULL;
waterCache = Core::settings.detail.water > Core::Settings::LOW ? new WaterCache(this) : NULL; waterCache = Core::settings.detail.water > Core::Settings::LOW ? new WaterCache(this) : NULL;
@@ -665,11 +671,6 @@ struct Level : IGame {
initReflections(); initReflections();
// init sounds
//sndSoundtrack = Sound::play(Sound::openWAD("05_Lara's_Themes.wav"), vec3(0.0f), 1, 1, Sound::Flags::LOOP);
sndUnderwater = NULL;
for (int i = 0; i < level.soundSourcesCount; i++) { for (int i = 0; i < level.soundSourcesCount; i++) {
TR::SoundSource &src = level.soundSources[i]; TR::SoundSource &src = level.soundSources[i];
int flags = Sound::PAN; int flags = Sound::PAN;
@@ -685,9 +686,6 @@ struct Level : IGame {
waterCache = NULL; waterCache = NULL;
zoneCache = NULL; zoneCache = NULL;
shadow = NULL; shadow = NULL;
sndSoundtrack = NULL;
sndUnderwater = NULL;
sndCurrent = NULL;
lastTitle = true; lastTitle = true;
inventory.toggle(0, Inventory::PAGE_OPTION); inventory.toggle(0, Inventory::PAGE_OPTION);
} }
@@ -695,9 +693,9 @@ struct Level : IGame {
effect = TR::Effect::NONE; effect = TR::Effect::NONE;
cube360 = NULL; cube360 = NULL;
sndSoundtrack = NULL; sndWater = sndTrack = NULL;
playNextTrack = true;
sndCurrent = sndSoundtrack; playTrack(0);
/* /*
if (level.id == TR::LVL_TR2_RIG) { if (level.id == TR::LVL_TR2_RIG) {
lara->animation.setAnim(level.models[level.extra.laraSpec].animation); lara->animation.setAnim(level.models[level.extra.laraSpec].animation);
@@ -1436,13 +1434,8 @@ struct Level : IGame {
} }
void update() { void update() {
if (playNextTrack) { if (level.isCutsceneLevel() && waitTrack) {
playTrack(0); if (!sndTrack && TR::LEVEL_INFO[level.id].ambientTrack != TR::NO_TRACK) {
playNextTrack = false;
}
if (level.isCutsceneLevel() && waitSoundtrack) {
if (!sndSoundtrack && TR::LEVEL_INFO[level.id].ambientTrack != TR::NO_TRACK) {
if (camera->timer > 0.0f) // for the case that audio stops before animation ends if (camera->timer > 0.0f) // for the case that audio stops before animation ends
loadNextLevel(); loadNextLevel();
return; return;
@@ -1452,8 +1445,8 @@ struct Level : IGame {
cutsceneWaitTimer -= Core::deltaTime; cutsceneWaitTimer -= Core::deltaTime;
if (cutsceneWaitTimer > 0.0f) if (cutsceneWaitTimer > 0.0f)
return; return;
if (sndSoundtrack) if (sndTrack)
sndSoundtrack->setVolume(1.0f, 0.0f); sndTrack->setVolume(1.0f, 0.0f);
cutsceneWaitTimer = 0.0f; cutsceneWaitTimer = 0.0f;
Core::resetTime(); Core::resetTime();
LOG("reset timer - %d\n", Core::getTime()); LOG("reset timer - %d\n", Core::getTime());
@@ -1475,8 +1468,6 @@ struct Level : IGame {
inventory.toggle(playerIndex); inventory.toggle(playerIndex);
} }
Sound::Sample *sndChanged = sndCurrent;
inventory.update(); inventory.update();
if (inventory.titleTimer > 1.0f) if (inventory.titleTimer > 1.0f)
@@ -1484,10 +1475,11 @@ struct Level : IGame {
UI::update(); UI::update();
float volWater, volTrack;
if (inventory.isActive() || level.isTitle()) { if (inventory.isActive() || level.isTitle()) {
Sound::reverb.setRoomSize(vec3(1.0f)); Sound::reverb.setRoomSize(vec3(1.0f));
if (!level.isTitle()) volWater = volTrack = 0.0f;
sndChanged = NULL;
} else { } else {
params->time += Core::deltaTime; params->time += Core::deltaTime;
animTexTimer += Core::deltaTime; animTexTimer += Core::deltaTime;
@@ -1511,22 +1503,24 @@ struct Level : IGame {
Controller::clearInactive(); Controller::clearInactive();
// underwater ambient sound volume control
if (camera->isUnderwater()) { if (camera->isUnderwater()) {
if (!sndUnderwater) { if (!sndWater) {
sndUnderwater = playSound(TR::SND_UNDERWATER, vec3(0.0f), Sound::LOOP | Sound::MUSIC); sndWater = playSound(TR::SND_UNDERWATER, vec3(0.0f), Sound::LOOP | Sound::MUSIC);
if (sndUnderwater) if (sndWater)
sndUnderwater->volume = sndUnderwater->volumeTarget = 0.0f; sndWater->volume = sndWater->volumeTarget = 0.0f;
} }
sndChanged = sndUnderwater; volWater = 1.0f;
} else } else
sndChanged = sndSoundtrack; volWater = 0.0f;
volTrack = 1.0f;
} }
if (sndChanged != sndCurrent) { if (sndWater && sndWater->volumeTarget != volWater)
if (sndCurrent) sndCurrent->setVolume(0.0f, 0.2f); sndWater->setVolume(volWater, 0.2f);
if (sndChanged) sndChanged->setVolume(1.0f, 0.2f); if (sndTrack && sndTrack->volumeTarget != volTrack)
sndCurrent = sndChanged; sndTrack->setVolume(volTrack, 0.2f);
}
} }
void updateEffect() { void updateEffect() {