From 9cdd56f5b4f2776ff8a62947b1eaf8fe1a2d9f6b Mon Sep 17 00:00:00 2001 From: philburk Date: Thu, 1 Sep 2011 22:08:32 +0000 Subject: [PATCH] Implement the Float32 to UInt8 converters. The loopback test now passes cleanly for the first time on my PreSonus FireStudio. Added tests for clip and dither flag combinations to loopback. --- qa/loopback/src/paqa.c | 73 ++++++++++++++++++++--------- src/common/pa_converters.c | 28 +++++++---- src/hostapi/coreaudio/pa_mac_core.c | 10 +++- test/patest_sine8.c | 27 ++++------- 4 files changed, 88 insertions(+), 50 deletions(-) diff --git a/qa/loopback/src/paqa.c b/qa/loopback/src/paqa.c index 3ac6599..ad993a9 100644 --- a/qa/loopback/src/paqa.c +++ b/qa/loopback/src/paqa.c @@ -91,7 +91,8 @@ typedef struct TestParameters_s int maxFrames; double baseFrequency; double amplitude; - int flags; + PaStreamFlags streamFlags; // paClipOff, etc + int flags; // PAQA_FLAG_TWO_STREAMS, PAQA_FLAG_USE_BLOCKING_IO } TestParameters; typedef struct LoopbackContext_s @@ -106,15 +107,19 @@ typedef struct LoopbackContext_s PaTime streamInfoOutputLatency; // Measured at runtime. - int callbackCount; // incremented for each callback - int inputBufferCount; // incremented if input buffer not NULL + volatile int callbackCount; // incremented for each callback + volatile int inputBufferCount; // incremented if input buffer not NULL int inputUnderflowCount; int inputOverflowCount; - int outputBufferCount; // incremented if output buffer not NULL + volatile int outputBufferCount; // incremented if output buffer not NULL int outputOverflowCount; int outputUnderflowCount; + // Measure whether input or output is lagging behind. + volatile int minInputOutputDelta; + volatile int maxInputOutputDelta; + int minFramesPerBuffer; int maxFramesPerBuffer; int primingCount; @@ -239,7 +244,22 @@ static int RecordAndPlaySinesCallback( const void *inputBuffer, void *outputBuff } } - + + // Measure whether the input or output are lagging behind. + // Don't measure lag at end. + if( !loopbackContext->done ) + { + int inputOutputDelta = loopbackContext->inputBufferCount - loopbackContext->outputBufferCount; + if( loopbackContext->maxInputOutputDelta < inputOutputDelta ) + { + loopbackContext->maxInputOutputDelta = inputOutputDelta; + } + if( loopbackContext->minInputOutputDelta > inputOutputDelta ) + { + loopbackContext->minInputOutputDelta = inputOutputDelta; + } + } + return loopbackContext->done ? paComplete : paContinue; } @@ -350,7 +370,7 @@ int PaQa_RunLoopbackHalfDuplex( LoopbackContext *loopbackContext ) NULL, test->sampleRate, test->framesPerBuffer, - paClipOff, /* we won't output out of range samples so don't bother clipping them */ + test->streamFlags, RecordAndPlaySinesCallback, loopbackContext ); if( err != paNoError ) goto error; @@ -360,7 +380,7 @@ int PaQa_RunLoopbackHalfDuplex( LoopbackContext *loopbackContext ) &test->outputParameters, test->sampleRate, test->framesPerBuffer, - paClipOff, /* we won't output out of range samples so don't bother clipping them */ + test->streamFlags, RecordAndPlaySinesCallback, loopbackContext ); if( err != paNoError ) goto error; @@ -870,8 +890,9 @@ static int PaQa_SingleLoopBackTest( UserOptions *userOptions, TestParameters *te { printf( "OK" ); } - + printf( "\n" ); + PaQa_TeardownLoopbackContext( &loopbackContext ); if( numBadChannels > 0 ) @@ -899,6 +920,7 @@ static void PaQa_SetDefaultTestParameters( TestParameters *testParamsPtr, PaDevi testParamsPtr->framesPerBuffer = DEFAULT_FRAMES_PER_BUFFER; testParamsPtr->baseFrequency = 200.0; testParamsPtr->flags = PAQA_FLAG_TWO_STREAMS; + testParamsPtr->streamFlags = paClipOff; /* we won't output out of range samples so don't bother clipping them */ testParamsPtr->inputParameters.device = inputDevice; testParamsPtr->inputParameters.sampleFormat = paFloat32; @@ -1038,18 +1060,27 @@ static int PaQa_AnalyzeLoopbackConnection( UserOptions *userOptions, PaDeviceInd } printf("\nTest Sample Formats using Half Duplex IO -----\n" ); - testParams.flags = PAQA_FLAG_TWO_STREAMS; - - for( iFormat=0; iFormatstreamRepresentation.magic == PA_STREAM_MAGIC ); + OSStatus osErr = UpdateSampleRateFromDeviceProperty( stream, inDevice, isInput ); if( osErr == noErr ) { @@ -1034,6 +1038,10 @@ static OSStatus AudioDevicePropertyGenericListenerProc( AudioDeviceID inDevice, { OSStatus osErr = noErr; PaMacCoreStream *stream = (PaMacCoreStream*)inClientData; + + // Make sure the callback is operating on a stream that is still valid! + assert( stream->streamRepresentation.magic == PA_STREAM_MAGIC ); + PaMacCoreDeviceProperties *deviceProperties = isInput ? &stream->inputProperties : &stream->outputProperties; UInt32 *valuePtr = NULL; switch( inPropertyID ) @@ -2107,7 +2115,7 @@ static OSStatus AudioIOProc( void *inRefCon, PaMacCoreStream *stream = (PaMacCoreStream*)inRefCon; const bool isRender = inBusNumber == OUTPUT_ELEMENT; int callbackResult = paContinue ; - double hostTimeStampInPaTime = HOST_TIME_TO_PA_TIME(inTimeStamp->mHostTime); + double hostTimeStampInPaTime = HOST_TIME_TO_PA_TIME(inTimeStamp->mHostTime); VVDBUG(("AudioIOProc()\n")); diff --git a/test/patest_sine8.c b/test/patest_sine8.c index beeae9e..c00319a 100644 --- a/test/patest_sine8.c +++ b/test/patest_sine8.c @@ -52,8 +52,12 @@ #if TEST_UNSIGNED #define TEST_FORMAT paUInt8 +typedef unsigned char sample_t; +#define SILENCE ((sample_t)0x80) #else #define TEST_FORMAT paInt8 +typedef char sample_t; +#define SILENCE ((sample_t)0x00) #endif #ifndef M_PI @@ -62,11 +66,7 @@ typedef struct { -#if TEST_UNSIGNED - unsigned char sine[TABLE_SIZE]; -#else - char sine[TABLE_SIZE]; -#endif + sample_t sine[TABLE_SIZE]; int left_phase; int right_phase; unsigned int framesToGo; @@ -84,7 +84,7 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer, void *userData ) { paTestData *data = (paTestData*)userData; - char *out = (char*)outputBuffer; + sample_t *out = (sample_t*)outputBuffer; int i; int framesToCalc; int finished = 0; @@ -114,14 +114,8 @@ static int patestCallback( const void *inputBuffer, void *outputBuffer, /* zero remainder of final buffer */ for( ; i<(int)framesPerBuffer; i++ ) { -#if TEST_UNSIGNED - *out++ = (unsigned char) 0x80; /* left */ - *out++ = (unsigned char) 0x80; /* right */ -#else - *out++ = 0; /* left */ - *out++ = 0; /* right */ -#endif - + *out++ = SILENCE; /* left */ + *out++ = SILENCE; /* right */ } return finished; } @@ -145,10 +139,7 @@ int main(void) /* initialise sinusoidal wavetable */ for( i=0; i