@ -83,6 +83,9 @@ void Audio::Initialize(){
bgm . SetFadeTime ( defaultFadeTime ) ;
}
if ( data . HasProperty ( " Loop Repeat Start Point " ) ) {
bgm . SetLoopStartTime ( data [ " Loop Repeat Start Point " ] . GetReal ( ) ) ;
}
if ( data . HasProperty ( " Events " ) ) {
for ( auto & eventName : Self ( ) . events ) {
@ -175,6 +178,7 @@ void Audio::BGM::Load(){
}
Self ( ) . currentBGM = songFileName ;
Self ( ) . currentLoopIndex = 0 ;
Self ( ) . lastTimestamp = 0.f ;
BGM & newBgm = Self ( ) . bgm [ songFileName ] ;
if ( newBgm . channels . size ( ) > 0 ) ERR ( std : : format ( " WARNING! The size of the channels list is greater than zero! Size: {} " , newBgm . channels . size ( ) ) ) ;
} else {
@ -323,26 +327,38 @@ void Audio::PlayBGM(const std::string_view sound,const bool loop){
}
void Audio : : Update ( ) {
if ( Self ( ) . fadeToTargetVolumeTime = = 0.f & & Self ( ) . playBGMWaitTime > 0.f ) {
Self ( ) . playBGMWaitTime = std : : max ( Self ( ) . playBGMWaitTime - game - > GetElapsedTime ( ) , 0.f ) ;
if ( Self ( ) . playBGMWaitTime = = 0.f & & Self ( ) . immediatelyLoadAudio ) {
while ( ! Self ( ) . BGMFullyLoaded ( ) ) {
UpdateLoop ( ) ; //We immediately load the file. In a loading screen setting we would defer UpdateLoop() such that we have extra time to update the screen, UpdateLoop() is divided into many parts of the music loading process.
if ( Self ( ) . BGMFullyLoaded ( ) & & Self ( ) . BGMIsPlaying ( ) ) {
Audio : : BGM & track = Self ( ) . bgm [ Self ( ) . GetTrackName ( ) ] ;
float currentTimestamp { Engine ( ) . GetCursorMilliseconds ( track . GetChannelIDs ( ) [ 0 ] ) / 1000.f } ;
if ( Self ( ) . lastTimestamp > currentTimestamp ) {
for ( int trackID : track . GetChannelIDs ( ) ) {
Engine ( ) . Seek ( trackID , unsigned long long ( track . GetLoopStartTime ( ) ) * 1000 ) ;
}
currentTimestamp = Engine ( ) . GetCursorMilliseconds ( track . GetChannelIDs ( ) [ 0 ] ) / 1000.f ; //Update to new timestamp now that it's been shifted over.
}
Self ( ) . lastTimestamp = currentTimestamp ;
} else {
if ( Self ( ) . fadeToTargetVolumeTime = = 0.f & & Self ( ) . playBGMWaitTime > 0.f ) {
Self ( ) . playBGMWaitTime = std : : max ( Self ( ) . playBGMWaitTime - game - > GetElapsedTime ( ) , 0.f ) ;
if ( Self ( ) . playBGMWaitTime = = 0.f & & Self ( ) . immediatelyLoadAudio ) {
while ( ! Self ( ) . BGMFullyLoaded ( ) ) {
UpdateLoop ( ) ; //We immediately load the file. In a loading screen setting we would defer UpdateLoop() such that we have extra time to update the screen, UpdateLoop() is divided into many parts of the music loading process.
}
//Start playing the tracks.
Audio : : BGM & track = Self ( ) . bgm [ Self ( ) . GetTrackName ( ) ] ;
for ( int trackID : track . GetChannelIDs ( ) ) {
Engine ( ) . Play ( trackID , true ) ;
//Start playing the tracks and setup a callback to repeat at looped time.
Audio : : BGM & track = Self ( ) . bgm [ Self ( ) . GetTrackName ( ) ] ;
for ( int trackID : track . GetChannelIDs ( ) ) {
Engine ( ) . Play ( trackID , true ) ;
}
}
}
}
if ( Self ( ) . fadeToTargetVolumeTime > 0.f ) {
Self ( ) . fadeToTargetVolumeTime = std : : max ( 0.f , Self ( ) . fadeToTargetVolumeTime - game - > GetElapsedTime ( ) ) ;
for ( int counter = 0 ; float & vol : Self ( ) . prevVolumes ) {
const BGM & currentBgm = Self ( ) . bgm [ Self ( ) . currentBGM ] ;
Engine ( ) . SetVolume ( currentBgm . GetChannelIDs ( ) [ counter ] , util : : lerp ( Self ( ) . GetCalculatedBGMVolume ( vol ) , Self ( ) . GetCalculatedBGMVolume ( Self ( ) . targetVolumes [ counter ] ) , 1 - ( Self ( ) . fadeToTargetVolumeTime / currentBgm . GetFadeTime ( ) ) ) ) ;
counter + + ;
if ( Self ( ) . fadeToTargetVolumeTime > 0.f ) {
Self ( ) . fadeToTargetVolumeTime = std : : max ( 0.f , Self ( ) . fadeToTargetVolumeTime - game - > GetElapsedTime ( ) ) ;
for ( int counter = 0 ; float & vol : Self ( ) . prevVolumes ) {
const BGM & currentBgm = Self ( ) . bgm [ Self ( ) . currentBGM ] ;
Engine ( ) . SetVolume ( currentBgm . GetChannelIDs ( ) [ counter ] , util : : lerp ( Self ( ) . GetCalculatedBGMVolume ( vol ) , Self ( ) . GetCalculatedBGMVolume ( Self ( ) . targetVolumes [ counter ] ) , 1 - ( Self ( ) . fadeToTargetVolumeTime / currentBgm . GetFadeTime ( ) ) ) ) ;
counter + + ;
}
}
}
}
@ -355,6 +371,10 @@ const float&Audio::BGM::GetFadeTime()const{
return fadeTime ;
}
const float & Audio : : BGM : : GetLoopStartTime ( ) const {
return loopStartTime ;
}
void Audio : : SetBGMVolume ( float vol ) {
bgmVol = vol ;
UpdateBGMVolume ( ) ;
@ -402,4 +422,8 @@ float Audio::GetMuteMult(){
int Audio : : GetPrepareBGMLoopIterations ( std : : string_view sound ) {
BGM & newBgm = Self ( ) . bgm [ std : : string ( sound ) ] ;
return newBgm . GetChannels ( ) . size ( ) * 2 + 2 ; //The channels list gets populated by calling newBgm.Load(), which then provides the list of channels that need to be loaded and played. This is why we multiply by 2. Each of the loading phases also consist of an initialization phase, so we add 2 as well.
}
void Audio : : BGM : : SetLoopStartTime ( const float loopStartTime ) {
this - > loopStartTime = loopStartTime ;
}