1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-14 09:04:31 +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 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 stopTrack() {}
virtual void playTrack(uint8 track) {}
virtual void stopTrack() {}
};
struct Controller {

View File

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

View File

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