void Inventory::Load( PlayerState* pPlayerState ) { ReloadItems(); m_pPlayerState = pPlayerState; m_iLastSeenCombo = 0; // don't load battle sounds if they're not going to be used switch( GAMESTATE->m_PlayMode ) { case PLAY_MODE_BATTLE: { m_soundAcquireItem.Load( THEME->GetPathS("Inventory","aquire item") ); for( unsigned i=0; i<g_Items.size(); i++ ) { RageSound* pSound = new RageSound; pSound->Load( THEME->GetPathS("Inventory",ssprintf("use item %u",i+1)) ); m_vpSoundUseItem.push_back( pSound ); } m_soundItemEnding.Load( THEME->GetPathS("Inventory","item ending") ); break; } default: break; } }
/* Don't hold the lock when we don't have to. We call this function from other * threads, to avoid stalling the gameplay thread. */ void RageSoundManager::PlayOnce( CString sPath ) { /* We want this to start quickly, so don't try to prebuffer it. */ RageSound *snd = new RageSound; snd->Load(sPath, false); snd->Play(); /* We're responsible for freeing it. Add it to owned_sounds *after* we start * playing, so RageSoundManager::Update doesn't free it before we actually start * it. */ DeleteSoundWhenFinished( snd ); }
bool RandomSample::LoadSound( CString sSoundFilePath ) { LOG->Trace( "RandomSample::LoadSound( %s )", sSoundFilePath.c_str() ); RageSound *pSS = new RageSound; if( !pSS->Load(sSoundFilePath) ) { LOG->Trace( "Error loading \"%s\": %s", sSoundFilePath.c_str(), pSS->GetError().c_str() ); delete pSS; return false; } m_pSamples.push_back( pSS ); return true; }
static void StartMusic( MusicToPlay &ToPlay ) { CHECKPOINT; LockMutex L( *g_Mutex ); CHECKPOINT; if( g_Playing->m_Music->IsPlaying() && !g_Playing->m_Music->GetLoadedFilePath().CompareNoCase(ToPlay.file) ) return; CHECKPOINT; if( ToPlay.file.empty() ) { /* StopPlaying() can take a while, so don't hold the lock while we stop the sound. * Be sure to leave the rest of g_Playing in place. */ RageSound *pOldSound = g_Playing->m_Music; g_Playing->m_Music = new RageSound; L.Unlock(); /* We're not allowed to delete the sound in a separate thread, because * RageSoundManager::FlushPosMapQueue might be running. Stop the sound, * and give it to RageSoundManager to delete. */ SOUNDMAN->DeleteSound( pOldSound ); return; } CHECKPOINT; /* Unlock, load the sound here, and relock. Loading may take a while if we're * reading from CD and we have to seek far, which can throw off the timing below. */ MusicPlaying *NewMusic; { g_Mutex->Unlock(); RageSound *pSound = new RageSound; pSound->Load( ToPlay.file, false ); g_Mutex->Lock(); NewMusic = new MusicPlaying( pSound ); } NewMusic->m_Timing = g_Playing->m_Timing; CHECKPOINT; /* See if we can find timing data, if it's not already loaded. */ if( !ToPlay.HasTiming && IsAFile(ToPlay.timing_file) ) { LOG->Trace("Found '%s'", ToPlay.timing_file.c_str()); if( SMLoader::LoadTimingFromFile( ToPlay.timing_file, ToPlay.timing_data ) ) ToPlay.HasTiming = true; } CHECKPOINT; if( ToPlay.HasTiming ) NewMusic->m_NewTiming = ToPlay.timing_data; if( ToPlay.align_beat && ToPlay.HasTiming && ToPlay.force_loop && ToPlay.length_sec != -1 ) { /* Extend the loop period so it always starts and ends on the same fractional * beat. That is, if it starts on beat 1.5, and ends on beat 10.2, extend it * to end on beat 10.5. This way, effects always loop cleanly. */ float fStartBeat = NewMusic->m_NewTiming.GetBeatFromElapsedTime( ToPlay.start_sec ); float fEndSec = ToPlay.start_sec + ToPlay.length_sec; float fEndBeat = NewMusic->m_NewTiming.GetBeatFromElapsedTime( fEndSec ); const float fStartBeatFraction = fmodfp( fStartBeat, 1 ); const float fEndBeatFraction = fmodfp( fEndBeat, 1 ); float fBeatDifference = fStartBeatFraction - fEndBeatFraction; if( fBeatDifference < 0 ) fBeatDifference += 1.0f; /* unwrap */ fEndBeat += fBeatDifference; const float fRealEndSec = NewMusic->m_NewTiming.GetElapsedTimeFromBeat( fEndBeat ); const float fNewLengthSec = fRealEndSec - ToPlay.start_sec; /* Extend the fade_len, so the added time is faded out. */ ToPlay.fade_len += fNewLengthSec - ToPlay.length_sec; ToPlay.length_sec = fNewLengthSec; } CHECKPOINT; bool StartImmediately = false; if( !ToPlay.HasTiming ) { /* This song has no real timing data. The offset is arbitrary. Change it so * the beat will line up to where we are now, so we don't have to delay. */ float fDestBeat = fmodfp( GAMESTATE->m_fSongBeat, 1 ); CHECKPOINT_M(ssprintf("%f",GAMESTATE->m_fSongBeat)); CHECKPOINT_M(ssprintf("%p",NewMusic)); float fTime = NewMusic->m_NewTiming.GetElapsedTimeFromBeat( fDestBeat ); NewMusic->m_NewTiming.m_fBeat0OffsetInSeconds = fTime; StartImmediately = true; } CHECKPOINT; /* If we have an active timer, try to start on the next update. Otherwise, * start now. */ if( !g_Playing->m_HasTiming && !g_UpdatingTimer ) StartImmediately = true; if( !ToPlay.align_beat ) StartImmediately = true; CHECKPOINT; RageTimer when; /* zero */ if( !StartImmediately ) { /* GetPlayLatency returns the minimum time until a sound starts. That's * common when starting a precached sound, but our sound isn't, so it'll * probably take a little longer. Nudge the latency up. */ const float PresumedLatency = SOUND->GetPlayLatency() + 0.040f; const float fCurSecond = GAMESTATE->m_fMusicSeconds + PresumedLatency; const float fCurBeat = g_Playing->m_Timing.GetBeatFromElapsedTime( fCurSecond ); const float fCurBeatFraction = fmodfp( fCurBeat,1 ); /* The beat that the new sound will start on. */ const float fStartBeat = NewMusic->m_NewTiming.GetBeatFromElapsedTime( ToPlay.start_sec ); float fStartBeatFraction = fmodfp( fStartBeat, 1 ); if( fStartBeatFraction < fCurBeatFraction ) fStartBeatFraction += 1.0f; /* unwrap */ const float fCurBeatToStartOn = truncf(fCurBeat) + fStartBeatFraction; const float fSecondToStartOn = g_Playing->m_Timing.GetElapsedTimeFromBeat( fCurBeatToStartOn ); const float fMaximumDistance = 2; const float fDistance = min( fSecondToStartOn - fCurSecond, fMaximumDistance ); when = GAMESTATE->m_LastBeatUpdate + PresumedLatency + fDistance; } CHECKPOINT; /* Important: don't hold the mutex while we load and seek the actual sound. */ L.Unlock(); { NewMusic->m_HasTiming = ToPlay.HasTiming; if( ToPlay.HasTiming ) NewMusic->m_NewTiming = ToPlay.timing_data; NewMusic->m_TimingDelayed = true; // NewMusic->m_Music->Load( ToPlay.file, false ); RageSoundParams p; p.m_StartSecond = ToPlay.start_sec; p.m_LengthSeconds = ToPlay.length_sec; p.m_FadeLength = ToPlay.fade_len; p.StartTime = when; if( ToPlay.force_loop ) p.StopMode = RageSoundParams::M_LOOP; NewMusic->m_Music->SetParams( p ); NewMusic->m_Music->SetPositionSeconds( p.m_StartSecond ); NewMusic->m_Music->StartPlaying(); } CHECKPOINT; LockMut( *g_Mutex ); delete g_Playing; g_Playing = NewMusic; CHECKPOINT; }