_PA_DEFINE_FUNC(snd_pcm_status);
_PA_DEFINE_FUNC(snd_pcm_status_sizeof);
_PA_DEFINE_FUNC(snd_pcm_status_get_tstamp);
+_PA_DEFINE_FUNC(snd_pcm_status_get_htstamp);
_PA_DEFINE_FUNC(snd_pcm_status_get_state);
_PA_DEFINE_FUNC(snd_pcm_status_get_trigger_tstamp);
+_PA_DEFINE_FUNC(snd_pcm_status_get_trigger_htstamp);
_PA_DEFINE_FUNC(snd_pcm_status_get_delay);
#define alsa_snd_pcm_status_alloca(ptr) __alsa_snd_alloca(ptr, snd_pcm_status)
_PA_LOAD_FUNC(snd_pcm_status);
_PA_LOAD_FUNC(snd_pcm_status_sizeof);
_PA_LOAD_FUNC(snd_pcm_status_get_tstamp);
+ _PA_LOAD_FUNC(snd_pcm_status_get_htstamp);
_PA_LOAD_FUNC(snd_pcm_status_get_state);
_PA_LOAD_FUNC(snd_pcm_status_get_trigger_tstamp);
+ _PA_LOAD_FUNC(snd_pcm_status_get_trigger_htstamp);
_PA_LOAD_FUNC(snd_pcm_status_get_delay);
_PA_LOAD_FUNC(snd_card_next);
return stream->isActive;
}
+/** Extract audio/trigger htstamp from status and convert into PaTime (seconds).
+ *
+ * trigger is boolean: trigger stampstamp vs audio timestamp. If delay is non-NULL, return delay in
+ * frames. */
+static PaTime StatusToTime( const snd_pcm_status_t *status, int trigger, snd_pcm_uframes_t* delay )
+{
+ snd_htimestamp_t timestamp;
+ if ( trigger )
+ {
+ alsa_snd_pcm_status_get_trigger_htstamp( status, ×tamp );
+ }
+ else
+ {
+ alsa_snd_pcm_status_get_htstamp( status, ×tamp );
+ }
+ if ( delay )
+ {
+ *delay = alsa_snd_pcm_status_get_delay( status );
+ }
+ return timestamp.tv_sec + ( (PaTime)timestamp.tv_nsec * 1e-9 );
+}
+
static PaTime GetStreamTime( PaStream *s )
{
PaAlsaStream *stream = (PaAlsaStream*)s;
alsa_snd_pcm_status( stream->playback.pcm, status );
}
- alsa_snd_pcm_status_get_tstamp( status, ×tamp );
- return timestamp.tv_sec + (PaTime)timestamp.tv_usec / 1e6;
+ return StatusToTime( status, 0, NULL );
}
static double GetStreamCpuLoad( PaStream* s )
if( alsa_snd_pcm_status_get_state( st ) == SND_PCM_STATE_XRUN )
{
alsa_snd_pcm_status_get_trigger_tstamp( st, &t );
- self->underrun = now * 1000 - ( (PaTime)t.tv_sec * 1000 + (PaTime)t.tv_usec / 1000 );
+ self->underrun = ( now - StatusToTime( st, 1, NULL ) ) * 1000;
if( !self->playback.canMmap )
{
alsa_snd_pcm_status( self->capture.pcm, st );
if( alsa_snd_pcm_status_get_state( st ) == SND_PCM_STATE_XRUN )
{
- alsa_snd_pcm_status_get_trigger_tstamp( st, &t );
- self->overrun = now * 1000 - ((PaTime) t.tv_sec * 1000 + (PaTime) t.tv_usec / 1000);
+ self->overrun = ( now - StatusToTime( st, 1, NULL ) ) * 1000;
if (!self->capture.canMmap)
{
static void CalculateTimeInfo( PaAlsaStream *stream, PaStreamCallbackTimeInfo *timeInfo )
{
- snd_pcm_status_t *capture_status, *playback_status;
- snd_timestamp_t capture_timestamp, playback_timestamp;
+ snd_pcm_status_t *status;
PaTime capture_time = 0., playback_time = 0.;
- alsa_snd_pcm_status_alloca( &capture_status );
- alsa_snd_pcm_status_alloca( &playback_status );
+ alsa_snd_pcm_status_alloca( &status );
if( stream->capture.pcm )
{
snd_pcm_sframes_t capture_delay;
- alsa_snd_pcm_status( stream->capture.pcm, capture_status );
- alsa_snd_pcm_status_get_tstamp( capture_status, &capture_timestamp );
+ alsa_snd_pcm_status( stream->capture.pcm, status );
+ capture_time = StatusToTime( status, 0, &capture_delay );
- capture_time = capture_timestamp.tv_sec +
- ( (PaTime)capture_timestamp.tv_usec / 1000000.0 );
timeInfo->currentTime = capture_time;
-
- capture_delay = alsa_snd_pcm_status_get_delay( capture_status );
- timeInfo->inputBufferAdcTime = timeInfo->currentTime -
+ timeInfo->inputBufferAdcTime = capture_time -
(PaTime)capture_delay / stream->streamRepresentation.streamInfo.sampleRate;
}
if( stream->playback.pcm )
{
snd_pcm_sframes_t playback_delay;
+ PaTime playback_time;
- alsa_snd_pcm_status( stream->playback.pcm, playback_status );
- alsa_snd_pcm_status_get_tstamp( playback_status, &playback_timestamp );
-
- playback_time = playback_timestamp.tv_sec +
- ((PaTime)playback_timestamp.tv_usec / 1000000.0);
+ alsa_snd_pcm_status( stream->playback.pcm, status );
+ playback_time = StatusToTime( status, 0, &playback_delay );
if( stream->capture.pcm ) /* Full duplex */
{
else
timeInfo->currentTime = playback_time;
- playback_delay = alsa_snd_pcm_status_get_delay( playback_status );
timeInfo->outputBufferDacTime = timeInfo->currentTime +
(PaTime)playback_delay / stream->streamRepresentation.streamInfo.sampleRate;
}