start_time

This commit is contained in:
Glenn Maynard
2004-01-12 03:57:11 +00:00
parent d5eded488a
commit 071ec73a04
3 changed files with 35 additions and 5 deletions
@@ -66,25 +66,52 @@ bool RageSound_ALSA9::stream::GetData(bool init)
static Sint16 *buf = NULL; static Sint16 *buf = NULL;
if ( !buf ) if ( !buf )
buf = new Sint16[max_writeahead*samples_per_frame]; buf = new Sint16[max_writeahead*samples_per_frame];
char *cbuf = (char*) buf;
unsigned len = frames_to_fill*bytes_per_frame; const int play_pos = pcm->GetPlayPos();
const int cur_play_pos = pcm->GetPosition();
int len = frames_to_fill*bytes_per_frame;
/* It might be INACTIVE, when we're prebuffering. We just don't want to /* It might be INACTIVE, when we're prebuffering. We just don't want to
* fill anything in STOPPING; in that case, we just clear the audio buffer. */ * fill anything in STOPPING; in that case, we just clear the audio buffer. */
if( state != STOPPING ) if( state != STOPPING )
{ {
const unsigned got = snd->GetPCM( (char *) buf, len, pcm->GetPlayPos() ); int bytes_read = 0;
int bytes_left = len;
if( got < len ) /* Does the sound have a start time? */
if( !start_time.IsZero() )
{
/* If the sound is supposed to start at a time past this buffer, insert silence. */
const int iFramesUntilThisBuffer = play_pos - cur_play_pos;
const float fSecondsBeforeStart = -start_time.Ago();
const int iFramesBeforeStart = int(fSecondsBeforeStart * pcm->GetSampleRate());
const int iSilentFramesInThisBuffer = iFramesBeforeStart-iFramesUntilThisBuffer;
const int iSilentBytesInThisBuffer = clamp( iSilentFramesInThisBuffer * bytes_per_frame, 0, bytes_left );
memset( cbuf+bytes_read, 0, iSilentBytesInThisBuffer );
bytes_read += iSilentBytesInThisBuffer;
bytes_left -= iSilentBytesInThisBuffer;
if( !iSilentBytesInThisBuffer )
start_time.SetZero();
}
int got = snd->GetPCM( cbuf+bytes_read, len-bytes_read, play_pos + (bytes_read/bytes_per_frame) );
bytes_read += got;
bytes_left -= got;
if( bytes_left > 0 )
{ {
/* Fill the remainder of the buffer with silence. */ /* Fill the remainder of the buffer with silence. */
memset( buf+got, 0, len-got ); memset( cbuf+bytes_read, 0, bytes_left );
/* STOPPING tells the mixer thread to release the stream once str->flush_bufs /* STOPPING tells the mixer thread to release the stream once str->flush_bufs
* buffers have been flushed. */ * buffers have been flushed. */
state = STOPPING; state = STOPPING;
/* Flush two buffers worth of data. */ /* Flush two buffers worth of data. */
flush_pos = pcm->GetPlayPos(); flush_pos = pcm->GetPlayPos() + (bytes_read / bytes_per_frame);
} }
} else { } else {
/* Silence the buffer. */ /* Silence the buffer. */
@@ -121,6 +148,7 @@ void RageSound_ALSA9::StartMixing(RageSound *snd)
/* Give the stream to the playing sound and remove it from the pool. */ /* Give the stream to the playing sound and remove it from the pool. */
stream_pool[i]->snd = snd; stream_pool[i]->snd = snd;
stream_pool[i]->pcm->SetSampleRate( snd->GetSampleRate() ); stream_pool[i]->pcm->SetSampleRate( snd->GetSampleRate() );
stream_pool[i]->start_time = snd->GetStartTime();
/* Pre-buffer the stream. */ /* Pre-buffer the stream. */
stream_pool[i]->GetData(true); stream_pool[i]->GetData(true);
@@ -18,6 +18,7 @@ private:
/* Sound object that's playing on this stream, or NULL if this /* Sound object that's playing on this stream, or NULL if this
* channel is available: */ * channel is available: */
RageSound *snd; RageSound *snd;
RageTimer start_time;
enum { enum {
INACTIVE, INACTIVE,
@@ -13,6 +13,7 @@ private:
struct sound struct sound
{ {
RageSound *snd; RageSound *snd;
RageTimer start_time;
bool stopping; bool stopping;
int flush_pos; /* state == STOPPING only */ int flush_pos; /* state == STOPPING only */
sound() { snd = NULL; stopping=false; } sound() { snd = NULL; stopping=false; }