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:
@@ -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 {
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
136
src/level.h
136
src/level.h
@@ -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() {
|
||||||
|
Reference in New Issue
Block a user