code style
This commit is contained in:
@@ -21,25 +21,25 @@ static int chunksize() { return 512; }
|
||||
|
||||
static int underruns = 0, logged_underruns = 0;
|
||||
|
||||
RageSound_Generic_Software::sound::sound()
|
||||
RageSound_Generic_Software::Sound::Sound()
|
||||
{
|
||||
snd = NULL;
|
||||
state = AVAILABLE;
|
||||
paused = false;
|
||||
m_pSound = NULL;
|
||||
m_State = AVAILABLE;
|
||||
m_bPaused = false;
|
||||
}
|
||||
|
||||
void RageSound_Generic_Software::sound::Allocate( int frames )
|
||||
void RageSound_Generic_Software::Sound::Allocate( int iFrames )
|
||||
{
|
||||
/* Reserve enough blocks in the buffer to hold the buffer. Add one, to account for
|
||||
* the fact that we may have a partial block due to a previous Mix() call. */
|
||||
const int frames_per_block = samples_per_block / channels;
|
||||
const int blocks_to_prebuffer = frames / frames_per_block;
|
||||
buffer.reserve( blocks_to_prebuffer + 1 );
|
||||
const int iFramesPerBlock = samples_per_block / channels;
|
||||
const int iBlocksToPrebuffer = iFrames / iFramesPerBlock;
|
||||
m_Buffer.reserve( iBlocksToPrebuffer + 1 );
|
||||
}
|
||||
|
||||
void RageSound_Generic_Software::sound::Deallocate()
|
||||
void RageSound_Generic_Software::Sound::Deallocate()
|
||||
{
|
||||
buffer.reserve( 0 );
|
||||
m_Buffer.reserve( 0 );
|
||||
}
|
||||
|
||||
int RageSound_Generic_Software::DecodeThread_start( void *p )
|
||||
@@ -48,73 +48,73 @@ int RageSound_Generic_Software::DecodeThread_start( void *p )
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int g_TotalAhead = 0;
|
||||
static int g_TotalAheadCount = 0;
|
||||
static int g_iTotalAhead = 0;
|
||||
static int g_iTotalAheadCount = 0;
|
||||
|
||||
void RageSound_Generic_Software::Mix( int16_t *buf, int frames, int64_t frameno, int64_t current_frameno )
|
||||
void RageSound_Generic_Software::Mix( int16_t *pBuf, int iFrames, int64_t iFrameNumber, int64_t iCurrentFrame )
|
||||
{
|
||||
ASSERT_M( m_DecodeThread.IsCreated(), "RageSound_Generic_Software::StartDecodeThread() was never called" );
|
||||
|
||||
if( frameno - current_frameno + frames > 0 )
|
||||
if( iFrameNumber - iCurrentFrame + iFrames > 0 )
|
||||
{
|
||||
g_TotalAhead += (int) (frameno - current_frameno + frames);
|
||||
++g_TotalAheadCount;
|
||||
g_iTotalAhead += (int) (iFrameNumber - iCurrentFrame + iFrames);
|
||||
++g_iTotalAheadCount;
|
||||
}
|
||||
|
||||
static RageSoundMixBuffer mix;
|
||||
|
||||
for( unsigned i = 0; i < ARRAYLEN(sounds); ++i )
|
||||
for( unsigned i = 0; i < ARRAYLEN(m_Sounds); ++i )
|
||||
{
|
||||
/* s.snd can not safely be accessed from here. */
|
||||
sound &s = sounds[i];
|
||||
if( s.state == sound::HALTING )
|
||||
/* s.m_pSound can not safely be accessed from here. */
|
||||
Sound &s = m_Sounds[i];
|
||||
if( s.m_State == Sound::HALTING )
|
||||
{
|
||||
/* This indicates that this stream can be reused. */
|
||||
s.paused = false;
|
||||
s.state = sound::STOPPED;
|
||||
s.m_bPaused = false;
|
||||
s.m_State = Sound::STOPPED;
|
||||
|
||||
// LOG->Trace("set %p from HALTING to STOPPED", sounds[i].snd);
|
||||
// LOG->Trace("set %p from HALTING to STOPPED", m_Sounds[i].m_pSound);
|
||||
continue;
|
||||
}
|
||||
|
||||
if( s.state != sound::STOPPING && s.state != sound::PLAYING )
|
||||
if( s.m_State != Sound::STOPPING && s.m_State != Sound::PLAYING )
|
||||
continue;
|
||||
|
||||
/* STOPPING or PLAYING. Read sound data. */
|
||||
if( sounds[i].paused )
|
||||
if( m_Sounds[i].m_bPaused )
|
||||
continue;
|
||||
|
||||
int got_frames = 0;
|
||||
int frames_left = frames;
|
||||
int iGotFrames = 0;
|
||||
int iFramesLeft = iFrames;
|
||||
|
||||
/* Does the sound have a start time? */
|
||||
if( !s.start_time.IsZero() && current_frameno != -1 )
|
||||
if( !s.m_StartTime.IsZero() && iCurrentFrame != -1 )
|
||||
{
|
||||
/* If the sound is supposed to start at a time past this buffer, insert silence. */
|
||||
const int64_t iFramesUntilThisBuffer = frameno - current_frameno;
|
||||
const float fSecondsBeforeStart = -s.start_time.Ago();
|
||||
const int64_t iFramesUntilThisBuffer = iFrameNumber - iCurrentFrame;
|
||||
const float fSecondsBeforeStart = -s.m_StartTime.Ago();
|
||||
const int64_t iFramesBeforeStart = int64_t(fSecondsBeforeStart * GetSampleRate(0));
|
||||
const int iSilentFramesInThisBuffer = clamp( int(iFramesBeforeStart-iFramesUntilThisBuffer), 0, frames_left );
|
||||
const int iSilentFramesInThisBuffer = clamp( int(iFramesBeforeStart-iFramesUntilThisBuffer), 0, iFramesLeft );
|
||||
|
||||
got_frames += iSilentFramesInThisBuffer;
|
||||
frames_left -= iSilentFramesInThisBuffer;
|
||||
iGotFrames += iSilentFramesInThisBuffer;
|
||||
iFramesLeft -= iSilentFramesInThisBuffer;
|
||||
|
||||
/* If we didn't completely fill the buffer, then we've written all of the silence. */
|
||||
if( frames_left )
|
||||
s.start_time.SetZero();
|
||||
if( iFramesLeft )
|
||||
s.m_StartTime.SetZero();
|
||||
}
|
||||
|
||||
/* Fill actual data. */
|
||||
sound_block *p[2];
|
||||
unsigned pSize[2];
|
||||
s.buffer.get_read_pointers( p, pSize );
|
||||
s.m_Buffer.get_read_pointers( p, pSize );
|
||||
|
||||
while( frames_left && pSize[0] )
|
||||
while( iFramesLeft && pSize[0] )
|
||||
{
|
||||
if( !p[0]->frames_in_buffer )
|
||||
if( !p[0]->m_FramesInBuffer )
|
||||
{
|
||||
/* We've processed all of the sound in this block. Mark it read. */
|
||||
s.buffer.advance_read_pointer( 1 );
|
||||
s.m_Buffer.advance_read_pointer( 1 );
|
||||
++p[0];
|
||||
--pSize[0];
|
||||
|
||||
@@ -129,31 +129,31 @@ void RageSound_Generic_Software::Mix( int16_t *buf, int frames, int64_t frameno,
|
||||
}
|
||||
|
||||
/* Note that, until we call advance_read_pointer, we can safely write to p[0]. */
|
||||
const int frames_to_read = min( frames_left, p[0]->frames_in_buffer );
|
||||
mix.SetVolume( s.volume );
|
||||
mix.SetWriteOffset( got_frames*channels );
|
||||
mix.write( p[0]->p, frames_to_read * channels );
|
||||
const int frames_to_read = min( iFramesLeft, p[0]->m_FramesInBuffer );
|
||||
mix.SetVolume( s.m_fVolume );
|
||||
mix.SetWriteOffset( iGotFrames*channels );
|
||||
mix.write( p[0]->m_BufferNext, frames_to_read * channels );
|
||||
|
||||
SOUNDMAN->CommitPlayingPosition( s.sound_id, frameno+got_frames, p[0]->position, frames_to_read );
|
||||
SOUNDMAN->CommitPlayingPosition( s.m_iSoundID, iFrameNumber+iGotFrames, p[0]->m_iPosition, frames_to_read );
|
||||
|
||||
p[0]->p += frames_to_read*channels;
|
||||
p[0]->frames_in_buffer -= frames_to_read;
|
||||
p[0]->position += frames_to_read;
|
||||
p[0]->m_BufferNext += frames_to_read*channels;
|
||||
p[0]->m_FramesInBuffer -= frames_to_read;
|
||||
p[0]->m_iPosition += frames_to_read;
|
||||
|
||||
// LOG->Trace( "incr fr rd += %i (state %i) (%p)",
|
||||
// (int) frames_to_read, s.state, s.snd );
|
||||
// (int) frames_to_read, s.m_State, s.m_pSound );
|
||||
|
||||
got_frames += frames_to_read;
|
||||
frames_left -= frames_to_read;
|
||||
iGotFrames += frames_to_read;
|
||||
iFramesLeft -= frames_to_read;
|
||||
}
|
||||
|
||||
/* If we don't have enough to fill the buffer, we've underrun. */
|
||||
if( got_frames < frames && s.state == sound::PLAYING )
|
||||
if( iGotFrames < iFrames && s.m_State == Sound::PLAYING )
|
||||
++underruns;
|
||||
}
|
||||
|
||||
memset( buf, 0, frames*bytes_per_frame );
|
||||
mix.read( buf );
|
||||
memset( pBuf, 0, iFrames*bytes_per_frame );
|
||||
mix.read( pBuf );
|
||||
}
|
||||
|
||||
|
||||
@@ -161,12 +161,12 @@ void RageSound_Generic_Software::DecodeThread()
|
||||
{
|
||||
/* SOUNDMAN will be set once RageSoundManager's ctor returns and
|
||||
* assigns it; we might get here before that happens, though. */
|
||||
while( !SOUNDMAN && !shutdown_decode_thread )
|
||||
while( !SOUNDMAN && !m_bShutdownDecodeThread )
|
||||
usleep( 10000 );
|
||||
|
||||
SetupDecodingThread();
|
||||
|
||||
while( !shutdown_decode_thread )
|
||||
while( !m_bShutdownDecodeThread )
|
||||
{
|
||||
/* Fill each playing sound, round-robin. */
|
||||
{
|
||||
@@ -179,13 +179,13 @@ void RageSound_Generic_Software::DecodeThread()
|
||||
LockMut( m_Mutex );
|
||||
// LOG->Trace("begin mix");
|
||||
|
||||
for( unsigned i = 0; i < ARRAYLEN(sounds); ++i )
|
||||
for( unsigned i = 0; i < ARRAYLEN(m_Sounds); ++i )
|
||||
{
|
||||
/* The volume can change while the sound is playing; update it. */
|
||||
/* XXX: We can't access snd when in STOPPING; it doesn't exist anymore. */
|
||||
// if( sounds[i].state == sound::PLAYING || sounds[i].state == sound::STOPPING )
|
||||
if( sounds[i].state == sound::PLAYING )
|
||||
sounds[i].volume = sounds[i].snd->GetAbsoluteVolume();
|
||||
/* XXX: We can't access m_pSound when in STOPPING; it doesn't exist anymore. */
|
||||
// if( m_Sounds[i].m_State == Sound::PLAYING || m_Sounds[i].m_State == Sound::STOPPING )
|
||||
if( m_Sounds[i].m_State == Sound::PLAYING )
|
||||
m_Sounds[i].m_fVolume = m_Sounds[i].m_pSound->GetAbsoluteVolume();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -200,38 +200,38 @@ void RageSound_Generic_Software::DecodeThread()
|
||||
* causing major CPU bursts when the stream starts or underruns. (Filling 32k
|
||||
* takes more CPU than filling 4k frames, and may cause a gameplay skip.)
|
||||
*/
|
||||
for( unsigned i = 0; i < ARRAYLEN(sounds); ++i )
|
||||
for( unsigned i = 0; i < ARRAYLEN(m_Sounds); ++i )
|
||||
{
|
||||
if( sounds[i].state != sound::PLAYING )
|
||||
if( m_Sounds[i].m_State != Sound::PLAYING )
|
||||
continue;
|
||||
|
||||
sound *pSound = &sounds[i];
|
||||
Sound *pSound = &m_Sounds[i];
|
||||
|
||||
CHECKPOINT;
|
||||
int frames_filled = 0;
|
||||
while( pSound->buffer.num_writable() )
|
||||
int iFramesFilled = 0;
|
||||
while( pSound->m_Buffer.num_writable() )
|
||||
{
|
||||
/* If there are more than min_fill_frames available, check for
|
||||
* rate clamping. */
|
||||
if( pSound->buffer.num_readable()*samples_per_block >= unsigned(min_fill_frames) )
|
||||
if( pSound->m_Buffer.num_readable()*samples_per_block >= unsigned(min_fill_frames) )
|
||||
{
|
||||
/* Don't write more than two chunks worth of data in one
|
||||
* iteration. Since we delay for one chunk period per loop,
|
||||
* this means we'll fill at no more than 4x realtime. */
|
||||
if( frames_filled >= chunksize()*4 )
|
||||
if( iFramesFilled >= chunksize()*4 )
|
||||
break;
|
||||
}
|
||||
|
||||
int wrote = GetDataForSound( *pSound );
|
||||
if( !wrote )
|
||||
int iWrote = GetDataForSound( *pSound );
|
||||
if( !iWrote )
|
||||
{
|
||||
/* This sound is finishing. */
|
||||
pSound->state = sound::STOPPING;
|
||||
pSound->m_State = Sound::STOPPING;
|
||||
break;
|
||||
// LOG->Trace("mixer: (#%i) eof (%p)", i, pSound->snd );
|
||||
// LOG->Trace("mixer: (#%i) eof (%p)", i, pSound->m_pSound );
|
||||
}
|
||||
|
||||
frames_filled += wrote;
|
||||
iFramesFilled += iWrote;
|
||||
}
|
||||
}
|
||||
// LOG->Trace("end mix");
|
||||
@@ -240,26 +240,26 @@ void RageSound_Generic_Software::DecodeThread()
|
||||
|
||||
/* Buffer a block of sound data for the given sound. Return the number of
|
||||
* frames buffered. If end of file is reached, return 0. */
|
||||
int RageSound_Generic_Software::GetDataForSound( sound &s )
|
||||
int RageSound_Generic_Software::GetDataForSound( Sound &s )
|
||||
{
|
||||
sound_block *p[2];
|
||||
unsigned psize[2];
|
||||
s.buffer.get_write_pointers( p, psize );
|
||||
s.m_Buffer.get_write_pointers( p, psize );
|
||||
|
||||
/* If we have no open buffer slot, we have a buffer overflow. */
|
||||
ASSERT( psize[0] > 0 );
|
||||
|
||||
sound_block *b = p[0];
|
||||
int size = ARRAYLEN(b->buf)/channels;
|
||||
s.snd->GetDataToPlay( b->buf, size, b->position, b->frames_in_buffer );
|
||||
b->p = b->buf;
|
||||
sound_block *pBlock = p[0];
|
||||
int size = ARRAYLEN(pBlock->m_Buffer)/channels;
|
||||
s.m_pSound->GetDataToPlay( pBlock->m_Buffer, size, pBlock->m_iPosition, pBlock->m_FramesInBuffer );
|
||||
pBlock->m_BufferNext = pBlock->m_Buffer;
|
||||
|
||||
s.buffer.advance_write_pointer( 1 );
|
||||
s.m_Buffer.advance_write_pointer( 1 );
|
||||
|
||||
// LOG->Trace( "incr fr wr %i (state %i) (%p)",
|
||||
// (int) b->frames_in_buffer, s.state, s.snd );
|
||||
// (int) pBlock->m_FramesInBuffer, s.m_State, s.m_pSound );
|
||||
|
||||
return b->frames_in_buffer;
|
||||
return pBlock->m_FramesInBuffer;
|
||||
}
|
||||
|
||||
|
||||
@@ -268,33 +268,33 @@ void RageSound_Generic_Software::Update()
|
||||
/* We must not lock here, since the decoder thread might hold the lock for a
|
||||
* while at a time. This is threadsafe, because once a sound is in STOPPING,
|
||||
* this is the only place it'll be changed (to STOPPED). */
|
||||
for( unsigned i = 0; i < ARRAYLEN(sounds); ++i )
|
||||
for( unsigned i = 0; i < ARRAYLEN(m_Sounds); ++i )
|
||||
{
|
||||
switch( sounds[i].state )
|
||||
switch( m_Sounds[i].m_State )
|
||||
{
|
||||
case sound::STOPPED:
|
||||
sounds[i].Deallocate();
|
||||
sounds[i].state = sound::AVAILABLE;
|
||||
case Sound::STOPPED:
|
||||
m_Sounds[i].Deallocate();
|
||||
m_Sounds[i].m_State = Sound::AVAILABLE;
|
||||
continue;
|
||||
case sound::STOPPING:
|
||||
case Sound::STOPPING:
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
if( sounds[i].buffer.num_readable() != 0 )
|
||||
if( m_Sounds[i].m_Buffer.num_readable() != 0 )
|
||||
continue;
|
||||
|
||||
// LOG->Trace("finishing sound %i", i);
|
||||
|
||||
sounds[i].snd->SoundIsFinishedPlaying();
|
||||
sounds[i].snd = NULL;
|
||||
m_Sounds[i].m_pSound->SoundIsFinishedPlaying();
|
||||
m_Sounds[i].m_pSound = NULL;
|
||||
|
||||
/* This sound is done. Set it to HALTING, since the mixer thread might
|
||||
* be accessing it; it'll change it back to STOPPED once it's ready to
|
||||
* be used again. */
|
||||
sounds[i].state = sound::HALTING;
|
||||
// LOG->Trace("set (#%i) %p from STOPPING to HALTING", i, sounds[i].snd);
|
||||
m_Sounds[i].m_State = Sound::HALTING;
|
||||
// LOG->Trace("set (#%i) %p from STOPPING to HALTING", i, m_Sounds[i].m_pSound);
|
||||
}
|
||||
|
||||
static float fNext = 0;
|
||||
@@ -315,33 +315,33 @@ void RageSound_Generic_Software::Update()
|
||||
}
|
||||
}
|
||||
|
||||
void RageSound_Generic_Software::StartMixing( RageSoundBase *snd )
|
||||
void RageSound_Generic_Software::StartMixing( RageSoundBase *pSound )
|
||||
{
|
||||
/* Lock available sounds[], and reserve a slot. */
|
||||
/* Lock available m_Sounds[], and reserve a slot. */
|
||||
m_SoundListMutex.Lock();
|
||||
|
||||
unsigned i;
|
||||
for( i = 0; i < ARRAYLEN(sounds); ++i )
|
||||
if( sounds[i].state == sound::AVAILABLE )
|
||||
for( i = 0; i < ARRAYLEN(m_Sounds); ++i )
|
||||
if( m_Sounds[i].m_State == Sound::AVAILABLE )
|
||||
break;
|
||||
if( i == ARRAYLEN(sounds) )
|
||||
if( i == ARRAYLEN(m_Sounds) )
|
||||
{
|
||||
m_SoundListMutex.Unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
sound &s = sounds[i];
|
||||
s.state = sound::BUFFERING;
|
||||
Sound &s = m_Sounds[i];
|
||||
s.m_State = Sound::BUFFERING;
|
||||
|
||||
/* We've reserved our slot; we can safely unlock now. Don't hold onto it longer
|
||||
* than needed, since prebuffering might take some time. */
|
||||
m_SoundListMutex.Unlock();
|
||||
|
||||
s.snd = snd;
|
||||
s.start_time = snd->GetStartTime();
|
||||
s.sound_id = snd->GetID();
|
||||
s.volume = snd->GetAbsoluteVolume();
|
||||
s.buffer.clear();
|
||||
s.m_pSound = pSound;
|
||||
s.m_StartTime = pSound->GetStartTime();
|
||||
s.m_iSoundID = pSound->GetID();
|
||||
s.m_fVolume = pSound->GetAbsoluteVolume();
|
||||
s.m_Buffer.clear();
|
||||
|
||||
/* Initialize the sound buffer. */
|
||||
int BufferSize = frames_to_buffer;
|
||||
@@ -352,90 +352,90 @@ void RageSound_Generic_Software::StartMixing( RageSoundBase *snd )
|
||||
* is less of a problem, since the music position isn't based on those. It could
|
||||
* be fixed by having two decoding threads; one for streaming sounds and one for
|
||||
* non-streaming sounds. */
|
||||
if( s.snd->IsStreamingFromDisk() )
|
||||
if( s.m_pSound->IsStreamingFromDisk() )
|
||||
BufferSize = max( BufferSize, min_streaming_buffer_size );
|
||||
s.Allocate( BufferSize );
|
||||
|
||||
// LOG->Trace("StartMixing(%s) (%p)", s.snd->GetLoadedFilePath().c_str(), s.snd );
|
||||
// LOG->Trace("StartMixing(%s) (%p)", s.m_pSound->GetLoadedFilePath().c_str(), s.m_pSound );
|
||||
|
||||
/* Prebuffer some frames before changing the sound to PLAYING. */
|
||||
bool ReachedEOF = false;
|
||||
int frames_filled = 0;
|
||||
while( !ReachedEOF && frames_filled < min_fill_frames && frames_filled < BufferSize )
|
||||
int iFramesFilled = 0;
|
||||
while( !ReachedEOF && iFramesFilled < min_fill_frames && iFramesFilled < BufferSize )
|
||||
{
|
||||
// LOG->Trace("StartMixing: (#%i) buffering %i (%i writable) (%p)", i, (int) frames_to_buffer, s.buffer.num_writable(), s.snd );
|
||||
int wrote = GetDataForSound( s );
|
||||
frames_filled += wrote;
|
||||
if( !wrote )
|
||||
// LOG->Trace("StartMixing: (#%i) buffering %i (%i writable) (%p)", i, (int) frames_to_buffer, s.buffer.num_writable(), s.m_pSound );
|
||||
int iWrote = GetDataForSound( s );
|
||||
iFramesFilled += iWrote;
|
||||
if( !iWrote )
|
||||
{
|
||||
// LOG->Trace("StartMixing: XXX hit EOF (%p)", s.snd );
|
||||
// LOG->Trace("StartMixing: XXX hit EOF (%p)", s.m_pSound );
|
||||
ReachedEOF = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we hit EOF already, while prebuffering, then go right to STOPPING. */
|
||||
s.state = ReachedEOF? sound::STOPPING: sound::PLAYING;
|
||||
s.m_State = ReachedEOF? Sound::STOPPING: Sound::PLAYING;
|
||||
|
||||
// LOG->Trace("StartMixing: (#%i) finished prebuffering(%s) (%p)", i, s.snd->GetLoadedFilePath().c_str(), s.snd );
|
||||
// LOG->Trace("StartMixing: (#%i) finished prebuffering(%s) (%p)", i, s.m_pSound->GetLoadedFilePath().c_str(), s.m_pSound );
|
||||
}
|
||||
|
||||
void RageSound_Generic_Software::StopMixing( RageSoundBase *snd )
|
||||
void RageSound_Generic_Software::StopMixing( RageSoundBase *pSound )
|
||||
{
|
||||
/* Lock, to make sure the decoder thread isn't running on this sound while we do this. */
|
||||
LockMut( m_Mutex );
|
||||
|
||||
/* Find the sound. */
|
||||
unsigned i;
|
||||
for( i = 0; i < ARRAYLEN(sounds); ++i )
|
||||
if( sounds[i].state != sound::AVAILABLE && sounds[i].snd == snd )
|
||||
for( i = 0; i < ARRAYLEN(m_Sounds); ++i )
|
||||
if( m_Sounds[i].m_State != Sound::AVAILABLE && m_Sounds[i].m_pSound == pSound )
|
||||
break;
|
||||
if( i == ARRAYLEN(sounds) )
|
||||
if( i == ARRAYLEN(m_Sounds) )
|
||||
{
|
||||
LOG->Trace( "not stopping a sound because it's not playing" );
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we're already in STOPPED, there's nothing to do. */
|
||||
if( sounds[i].state == sound::STOPPED )
|
||||
if( m_Sounds[i].m_State == Sound::STOPPED )
|
||||
{
|
||||
LOG->Trace( "not stopping a sound because it's already in STOPPED" );
|
||||
return;
|
||||
}
|
||||
|
||||
// LOG->Trace("StopMixing: set %p (%s) to HALTING", sounds[i].snd, sounds[i].snd->GetLoadedFilePath().c_str());
|
||||
// LOG->Trace("StopMixing: set %p (%s) to HALTING", m_Sounds[i].m_pSound, m_Sounds[i].m_pSound->GetLoadedFilePath().c_str());
|
||||
|
||||
/* Tell the mixing thread to flush the buffer. We don't have to worry about
|
||||
* the decoding thread, since we've locked m_Mutex. */
|
||||
sounds[i].state = sound::HALTING;
|
||||
m_Sounds[i].m_State = Sound::HALTING;
|
||||
|
||||
/* Invalidate the snd pointer to guarantee we don't make any further references to
|
||||
/* Invalidate the m_pSound pointer to guarantee we don't make any further references to
|
||||
* it. Once this call returns, the sound may no longer exist. */
|
||||
sounds[i].snd = NULL;
|
||||
m_Sounds[i].m_pSound = NULL;
|
||||
// LOG->Trace("end StopMixing");
|
||||
}
|
||||
|
||||
|
||||
bool RageSound_Generic_Software::PauseMixing( RageSoundBase *snd, bool bStop )
|
||||
bool RageSound_Generic_Software::PauseMixing( RageSoundBase *pSound, bool bStop )
|
||||
{
|
||||
LockMut( m_Mutex );
|
||||
|
||||
/* Find the sound. */
|
||||
unsigned i;
|
||||
for( i = 0; i < ARRAYLEN(sounds); ++i )
|
||||
if( sounds[i].state != sound::AVAILABLE && sounds[i].snd == snd )
|
||||
for( i = 0; i < ARRAYLEN(m_Sounds); ++i )
|
||||
if( m_Sounds[i].m_State != Sound::AVAILABLE && m_Sounds[i].m_pSound == pSound )
|
||||
break;
|
||||
|
||||
/* A sound can be paused in PLAYING or STOPPING. (STOPPING means the sound
|
||||
* has been decoded to the end, and we're waiting for that data to finish, so
|
||||
* externally it looks and acts like PLAYING.) */
|
||||
if( i == ARRAYLEN(sounds) ||
|
||||
(sounds[i].state != sound::PLAYING && sounds[i].state != sound::STOPPING) )
|
||||
if( i == ARRAYLEN(m_Sounds) ||
|
||||
(m_Sounds[i].m_State != Sound::PLAYING && m_Sounds[i].m_State != Sound::STOPPING) )
|
||||
{
|
||||
LOG->Trace( "not pausing a sound because it's not playing" );
|
||||
return false;
|
||||
}
|
||||
|
||||
sounds[i].paused = bStop;
|
||||
m_Sounds[i].m_bPaused = bStop;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -447,18 +447,18 @@ void RageSound_Generic_Software::StartDecodeThread()
|
||||
m_DecodeThread.Create( DecodeThread_start, this );
|
||||
}
|
||||
|
||||
void RageSound_Generic_Software::SetDecodeBufferSize( int frames )
|
||||
void RageSound_Generic_Software::SetDecodeBufferSize( int iFrames )
|
||||
{
|
||||
ASSERT( !m_DecodeThread.IsCreated() );
|
||||
|
||||
frames_to_buffer = frames;
|
||||
frames_to_buffer = iFrames;
|
||||
}
|
||||
|
||||
RageSound_Generic_Software::RageSound_Generic_Software():
|
||||
m_Mutex("RageSound_Generic_Software"),
|
||||
m_SoundListMutex("SoundListMutex")
|
||||
{
|
||||
shutdown_decode_thread = false;
|
||||
m_bShutdownDecodeThread = false;
|
||||
SetDecodeBufferSize( 4096 );
|
||||
|
||||
m_DecodeThread.SetName("Decode thread");
|
||||
@@ -469,7 +469,7 @@ RageSound_Generic_Software::~RageSound_Generic_Software()
|
||||
/* Signal the decoding thread to quit. */
|
||||
if( m_DecodeThread.IsCreated() )
|
||||
{
|
||||
shutdown_decode_thread = true;
|
||||
m_bShutdownDecodeThread = true;
|
||||
LOG->Trace("Shutting down decode thread ...");
|
||||
LOG->Flush();
|
||||
m_DecodeThread.Wait();
|
||||
@@ -477,7 +477,7 @@ RageSound_Generic_Software::~RageSound_Generic_Software()
|
||||
LOG->Flush();
|
||||
|
||||
LOG->Info( "Mixing %f ahead in %i Mix() calls",
|
||||
float(g_TotalAhead) / max( g_TotalAheadCount, 1 ), g_TotalAheadCount );
|
||||
float(g_iTotalAhead) / max( g_iTotalAheadCount, 1 ), g_iTotalAheadCount );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ class RageSound_Generic_Software: public RageSoundDriver
|
||||
public:
|
||||
virtual void Update();
|
||||
|
||||
void StartMixing( RageSoundBase *snd ); /* used by RageSound */
|
||||
void StopMixing( RageSoundBase *snd ); /* used by RageSound */
|
||||
bool PauseMixing( RageSoundBase *snd, bool bStop );
|
||||
void StartMixing( RageSoundBase *pSound ); /* used by RageSound */
|
||||
void StopMixing( RageSoundBase *pSound ); /* used by RageSound */
|
||||
bool PauseMixing( RageSoundBase *pSound, bool bStop );
|
||||
|
||||
RageSound_Generic_Software();
|
||||
virtual ~RageSound_Generic_Software();
|
||||
@@ -37,17 +37,17 @@ protected:
|
||||
/*
|
||||
* Read mixed data.
|
||||
*
|
||||
* frames: buffer to read into
|
||||
* nframes: number of frames (not samples) to read
|
||||
* pBuf: buffer to read into
|
||||
* iFrames: number of frames (not samples) to read
|
||||
* frameno: frame number at which this sound will be heard
|
||||
* current_frameno: frame number that is currently being heard
|
||||
* iCurrentFrame: frame number that is currently being heard
|
||||
*
|
||||
* current_frameno is used for handling start timing.
|
||||
* iCurrentFrame is used for handling start timing.
|
||||
*
|
||||
* This function only mixes data; it will not lock any mutexes or do any file access, and
|
||||
* is safe to call from a realtime thread.
|
||||
*/
|
||||
void Mix( int16_t *frames, int nframes, int64_t frameno, int64_t current_frameno );
|
||||
void Mix( int16_t *pBuf, int iFrame, int64_t iFrameNumber, int64_t iCurrentFrame );
|
||||
|
||||
/* This mutex is used for serializing with the decoder thread. Locking this mutex
|
||||
* can take a while. */
|
||||
@@ -101,24 +101,25 @@ private:
|
||||
*/
|
||||
struct sound_block
|
||||
{
|
||||
int16_t buf[samples_per_block];
|
||||
int16_t *p; // beginning of the unread data
|
||||
int frames_in_buffer; // total number of frames (not samples) at p
|
||||
int64_t position; // position value of p
|
||||
sound_block() { frames_in_buffer = position = 0; p = buf; }
|
||||
int16_t m_Buffer[samples_per_block];
|
||||
int16_t *m_BufferNext; // beginning of the unread data
|
||||
int m_FramesInBuffer; // total number of frames at m_BufferNext
|
||||
int64_t m_iPosition; // stream frame of m_BufferNext
|
||||
sound_block() { m_FramesInBuffer = m_iPosition = 0; m_BufferNext = m_Buffer; }
|
||||
};
|
||||
|
||||
struct sound
|
||||
struct Sound
|
||||
{
|
||||
RageSoundBase *snd;
|
||||
int sound_id;
|
||||
RageTimer start_time;
|
||||
float volume;
|
||||
CircBuf<sound_block> buffer;
|
||||
Sound();
|
||||
void Allocate( int iFrames );
|
||||
void Deallocate();
|
||||
|
||||
/* If true, this sound is in STOPPED and available for use. */
|
||||
|
||||
bool paused;
|
||||
RageSoundBase *m_pSound;
|
||||
int m_iSoundID;
|
||||
RageTimer m_StartTime;
|
||||
float m_fVolume;
|
||||
CircBuf<sound_block> m_Buffer;
|
||||
bool m_bPaused;
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -133,23 +134,19 @@ private:
|
||||
|
||||
HALTING, /* stop immediately */
|
||||
PLAYING
|
||||
} state;
|
||||
|
||||
sound();
|
||||
void Allocate( int frames );
|
||||
void Deallocate();
|
||||
} m_State;
|
||||
};
|
||||
|
||||
/* List of currently playing sounds: XXX no vector */
|
||||
sound sounds[32];
|
||||
Sound m_Sounds[32];
|
||||
|
||||
bool shutdown_decode_thread;
|
||||
bool m_bShutdownDecodeThread;
|
||||
|
||||
static int DecodeThread_start(void *p);
|
||||
static int DecodeThread_start( void *p );
|
||||
void DecodeThread();
|
||||
RageThread m_DecodeThread;
|
||||
|
||||
int GetDataForSound( sound &s );
|
||||
int GetDataForSound( Sound &s );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user