From fc14177a0528cbf5049ef034d2644ceb961deb87 Mon Sep 17 00:00:00 2001 From: rossb Date: Thu, 10 Nov 2011 05:47:50 +0000 Subject: [PATCH] tweaked dsound callback time info calculations. implemented adc time. resolves #122 --- src/hostapi/dsound/pa_win_ds.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/hostapi/dsound/pa_win_ds.c b/src/hostapi/dsound/pa_win_ds.c index c6f209c..91425c2 100644 --- a/src/hostapi/dsound/pa_win_ds.c +++ b/src/hostapi/dsound/pa_win_ds.c @@ -2348,7 +2348,8 @@ static int TimeSlice( PaWinDsStream *stream ) long bytesProcessed; HRESULT hresult; double outputLatency = 0; - PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /** @todo implement inputBufferAdcTime */ + double inputLatency = 0; + PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /* Input */ LPBYTE lpInBuf1 = NULL; @@ -2377,11 +2378,12 @@ static int TimeSlice( PaWinDsStream *stream ) filled = readPos - stream->readOffset; if( filled < 0 ) filled += stream->inputBufferSizeBytes; // unwrap offset bytesFilled = filled; + + inputLatency = ((double)bytesFilled) * stream->secondsPerHostByte; } // FIXME: what happens if IDirectSoundCaptureBuffer_GetCurrentPosition fails? framesToXfer = numInFramesReady = bytesFilled / stream->inputFrameSizeBytes; - outputLatency = ((double)bytesFilled) * stream->secondsPerHostByte; // FIXME: this doesn't look right. we're calculating output latency in input branch. also secondsPerHostByte is only initialized for the output stream /** @todo Check for overflow */ } @@ -2396,6 +2398,14 @@ static int TimeSlice( PaWinDsStream *stream ) /* Check for underflow */ if( stream->outputUnderflowCount != previousUnderflowCount ) stream->callbackFlags |= paOutputUnderflow; + + /* We are about to compute audio into the first byte of empty space in the output buffer. + This audio will reach the DAC after all of the current (non-empty) audio + in the buffer has played. Therefore the output time is the current time + plus the time it takes to play the non-empty bytes in the buffer, + computed here: + */ + outputLatency = ((double)(stream->outputBufferSizeBytes - bytesEmpty)) * stream->secondsPerHostByte; } /* if it's a full duplex stream, set framesToXfer to the minimum of input and output frames ready */ @@ -2411,8 +2421,6 @@ static int TimeSlice( PaWinDsStream *stream ) /* The outputBufferDacTime parameter should indicates the time at which the first sample of the output buffer is heard at the DACs. */ timeInfo.currentTime = PaUtil_GetTime(); - timeInfo.outputBufferDacTime = timeInfo.currentTime + outputLatency; // FIXME: QueryOutputSpace gets the playback position, we could use that (?) - PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo, stream->callbackFlags ); stream->callbackFlags = 0; @@ -2420,6 +2428,8 @@ static int TimeSlice( PaWinDsStream *stream ) /* Input */ if( stream->bufferProcessor.inputChannelCount > 0 ) { + timeInfo.inputBufferAdcTime = timeInfo.currentTime - inputLatency; + bytesToXfer = framesToXfer * stream->inputFrameSizeBytes; hresult = IDirectSoundCaptureBuffer_Lock ( stream->pDirectSoundInputBuffer, stream->readOffset, bytesToXfer, @@ -2449,6 +2459,13 @@ static int TimeSlice( PaWinDsStream *stream ) /* Output */ if( stream->bufferProcessor.outputChannelCount > 0 ) { + /* + We don't currently add outputLatency here because it appears to produce worse + results than non adding it. Need to do more testing to verify this. + */ + /* timeInfo.outputBufferDacTime = timeInfo.currentTime + outputLatency; */ + timeInfo.outputBufferDacTime = timeInfo.currentTime; + bytesToXfer = framesToXfer * stream->outputFrameSizeBytes; hresult = IDirectSoundBuffer_Lock ( stream->pDirectSoundOutputBuffer, stream->outputBufferWriteOffsetBytes, bytesToXfer, -- 2.43.0