示例#1
0
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;
	}
}
示例#2
0
void RageSoundManager::Update(float delta)
{
	FlushPosMapQueue();

	/* Scan the owned_sounds list for sounds that are no longer playing, and delete them. */
	g_SoundManMutex.Lock(); /* lock for access to owned_sounds */
	set<RageSound *> ToDelete;
	for( set<RageSound *>::iterator it = owned_sounds.begin(); it != owned_sounds.end(); ++it )
	{
		RageSound *pSound = *it;
		if( pSound->IsPlaying() )
			continue;

		LOG->Trace("XXX: deleting '%s'", pSound->GetLoadedFilePath().c_str());

		ToDelete.insert( pSound );
	}
	
	for( set<RageSound *>::iterator it = ToDelete.begin(); it != ToDelete.end(); ++it )
		owned_sounds.erase( *it );
	g_SoundManMutex.Unlock(); /* finished with owned_sounds */

	/* Be sure to release g_SoundManMutex before deleting sounds. */
	for( set<RageSound *>::iterator it = ToDelete.begin(); it != ToDelete.end(); ++it )
		delete *it;

	if( driver != NULL )
		driver->Update(delta);
}
示例#3
0
/* 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 );
}
示例#4
0
void RageSound::PlayCopy(bool is_action, const RageSoundParams *pParams) const
{
	if(is_action && PREFSMAN->m_MuteActions)
	{
		return;
	}
	RageSound *pSound = new RageSound( *this );

	if( pParams )
		pSound->SetParams( *pParams );

	pSound->StartPlaying();
	pSound->DeleteSelfWhenFinishedPlaying();
}
示例#5
0
RageSound *RageSoundManager::PlayCopyOfSound( RageSound &snd, const RageSoundParams *params )
{
	RageSound *pSound = new RageSound(snd);
	DeleteSoundWhenFinished( pSound );

	if( params )
		pSound->SetParams( *params );

	// Move to the start position.
	pSound->SetPositionSeconds( pSound->GetParams().m_StartSecond );

	pSound->StartPlaying();

	return pSound;
}
示例#6
0
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;
}
示例#7
0
/* This is only called by RageSoundManager::Update. */
void RageSoundManager::FlushPosMapQueue()
{
	queued_pos_map_t p;

	/* We don't need to lock to access pos_map_queue. */
	while( pos_map_queue.read( &p, 1 ) )
	{
		RageSound *pSound = GetSoundByID( p.ID );

		/* If we can't find the ID, the sound was probably deleted before we got here. */
		if( pSound == NULL )
		{
			// LOG->Trace("ignored unknown (stale?) commit ID %i", p.ID);
			continue;
		}

		pSound->CommitPlayingPosition( p.frameno, p.pos, p.got_frames );
	}
}
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;
}
示例#9
0
void ScreenTestSound::Input( const InputEventPlus &input )
{
	if( input.type != IET_FIRST_PRESS )
		return;	// ignore

	switch( input.DeviceI.device )
	{
	case DEVICE_KEYBOARD:
		switch( input.DeviceI.button )
		{
		case '1':
		case '2':
		case '3':
		case '4':
		case '5': selected = input.DeviceI.button - '0'-1; break;
		case 'p':
		{
			/* We want to be able to read the position of copied sounds; if we let
			 * RageSound copy itself, then the copy will be owned by RageSoundManager
			 * and we won't be allowed to touch it.  Copy it ourself. */
			RageSound *pCopy = new RageSound( s[selected].s );
			m_sSoundCopies[selected].push_back( pCopy );
			pCopy->Play();
			break;
		}
		case 's':
			for( int i = 0; i < nsounds; ++i )
			{
				/* Stop copied sounds. */
				vector<RageSound *> &snds = m_sSoundCopies[i];
				for( unsigned j = 0; j < snds.size(); ++j )
					snds[j]->Stop();
			}
			break;
		case 'l':
			{
				RageSoundParams p = s[selected].s.GetParams();
				p.StopMode = RageSoundParams::M_LOOP;
				s[selected].s.SetParams( p );
			}

			break;
		case 'a':
			{
				RageSoundParams p = s[selected].s.GetParams();
				p.StopMode = RageSoundParams::M_STOP;
				s[selected].s.SetParams( p );
			}
			break;
		case 'c':
			{
				RageSoundParams p = s[selected].s.GetParams();
				p.StopMode = RageSoundParams::M_CONTINUE;
				s[selected].s.SetParams( p );
			}
			break;

/*		case KEY_LEFT:
			obj.SetX(obj.GetX() - 10);
			break;
		case KEY_RIGHT:
			obj.SetX(obj.GetX() + 10);
			break;
		case KEY_UP:
			obj.SetY(obj.GetY() - 10);
			break;
		case KEY_DOWN:
			obj.SetY(obj.GetY() + 10);
			break;
*/
		}

	}

}