Add test for sample format conversion.
This commit is contained in:
parent
c152ef3966
commit
0ebc551e6e
5 changed files with 275 additions and 31 deletions
|
|
@ -75,6 +75,7 @@ typedef struct PaQaTestTone_s
|
||||||
typedef struct PaQaAnalysisResult_s
|
typedef struct PaQaAnalysisResult_s
|
||||||
{
|
{
|
||||||
int valid;
|
int valid;
|
||||||
|
/** Latency in samples from output to input. */
|
||||||
double latency;
|
double latency;
|
||||||
double amplitudeRatio;
|
double amplitudeRatio;
|
||||||
double popAmplitude;
|
double popAmplitude;
|
||||||
|
|
@ -125,7 +126,6 @@ double PaQa_MeasureCrossingSlope( float *buffer, int numFrames );
|
||||||
*/
|
*/
|
||||||
void PaQa_SetupSineGenerator( PaQaSineGenerator *generator, double frequency, double amplitude, double frameRate );
|
void PaQa_SetupSineGenerator( PaQaSineGenerator *generator, double frequency, double amplitude, double frameRate );
|
||||||
|
|
||||||
|
|
||||||
/*================================================================*/
|
/*================================================================*/
|
||||||
/*================= Recordings ===================================*/
|
/*================= Recordings ===================================*/
|
||||||
/*================================================================*/
|
/*================================================================*/
|
||||||
|
|
|
||||||
|
|
@ -96,9 +96,15 @@ typedef struct LoopbackContext_s
|
||||||
PaQaSineGenerator generators[MAX_NUM_GENERATORS];
|
PaQaSineGenerator generators[MAX_NUM_GENERATORS];
|
||||||
// Record each channel individually.
|
// Record each channel individually.
|
||||||
PaQaRecording recordings[MAX_NUM_RECORDINGS];
|
PaQaRecording recordings[MAX_NUM_RECORDINGS];
|
||||||
|
// Measured at runtime.
|
||||||
int callbackCount;
|
int callbackCount;
|
||||||
|
int inputUnderflowCount;
|
||||||
|
int outputUnderflowCount;
|
||||||
|
int inputOverflowCount;
|
||||||
|
int outputOverflowCount;
|
||||||
|
int primingCount;
|
||||||
TestParameters *test;
|
TestParameters *test;
|
||||||
|
|
||||||
} LoopbackContext;
|
} LoopbackContext;
|
||||||
|
|
||||||
typedef struct UserOptions_s
|
typedef struct UserOptions_s
|
||||||
|
|
@ -115,7 +121,8 @@ typedef struct UserOptions_s
|
||||||
} UserOptions;
|
} UserOptions;
|
||||||
|
|
||||||
#define BIG_BUFFER_SIZE (sizeof(float) * 2 * 2048)
|
#define BIG_BUFFER_SIZE (sizeof(float) * 2 * 2048)
|
||||||
static unsigned char g_BigBuffer[BIG_BUFFER_SIZE];
|
static unsigned char g_ReadWriteBuffer[BIG_BUFFER_SIZE];
|
||||||
|
static unsigned char g_ConversionBuffer[BIG_BUFFER_SIZE];
|
||||||
|
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
static int RecordAndPlaySinesCallback( const void *inputBuffer, void *outputBuffer,
|
static int RecordAndPlaySinesCallback( const void *inputBuffer, void *outputBuffer,
|
||||||
|
|
@ -125,40 +132,67 @@ static int RecordAndPlaySinesCallback( const void *inputBuffer, void *outputBuff
|
||||||
void *userData )
|
void *userData )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
float *in = (float *)inputBuffer;
|
|
||||||
float *out = (float *)outputBuffer;
|
|
||||||
int done = paContinue;
|
int done = paContinue;
|
||||||
|
LoopbackContext *loopbackContext = (LoopbackContext *) userData;
|
||||||
|
|
||||||
LoopbackContext *loopbackContext = (LoopbackContext *) userData;
|
int channelsPerFrame = loopbackContext->test->inputParameters.channelCount;
|
||||||
|
|
||||||
loopbackContext->callbackCount += 1;
|
loopbackContext->callbackCount += 1;
|
||||||
|
if( statusFlags & paInputUnderflow ) loopbackContext->inputUnderflowCount += 1;
|
||||||
|
if( statusFlags & paInputOverflow ) loopbackContext->inputOverflowCount += 1;
|
||||||
|
if( statusFlags & paOutputUnderflow ) loopbackContext->outputUnderflowCount += 1;
|
||||||
|
if( statusFlags & paOutputOverflow ) loopbackContext->outputOverflowCount += 1;
|
||||||
|
if( statusFlags & paPrimingOutput ) loopbackContext->primingCount += 1;
|
||||||
|
|
||||||
/* This may get called with NULL inputBuffer during initial setup.
|
/* This may get called with NULL inputBuffer during initial setup.
|
||||||
* We may also use the same callback with output only streams.
|
* We may also use the same callback with output only streams.
|
||||||
*/
|
*/
|
||||||
if( in != NULL)
|
if( inputBuffer != NULL)
|
||||||
{
|
{
|
||||||
// Read each channel from the buffer.
|
float *in = (float *)inputBuffer;
|
||||||
for( i=0; i<loopbackContext->test->inputParameters.channelCount; i++ )
|
|
||||||
|
PaSampleFormat inFormat = loopbackContext->test->inputParameters.sampleFormat;
|
||||||
|
if( inFormat != paFloat32 )
|
||||||
{
|
{
|
||||||
|
in = (float *) g_ConversionBuffer;
|
||||||
|
PaQa_ConvertToFloat( inputBuffer, framesPerBuffer * channelsPerFrame, inFormat, (float *) g_ConversionBuffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read each channel from the buffer.
|
||||||
|
for( i=0; i<channelsPerFrame; i++ )
|
||||||
|
{
|
||||||
done |= PaQa_WriteRecording( &loopbackContext->recordings[i],
|
done |= PaQa_WriteRecording( &loopbackContext->recordings[i],
|
||||||
in + i,
|
in + i,
|
||||||
framesPerBuffer,
|
framesPerBuffer,
|
||||||
loopbackContext->test->inputParameters.channelCount );
|
channelsPerFrame );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( out != NULL )
|
if( outputBuffer != NULL )
|
||||||
{
|
{
|
||||||
|
float *out = (float *)outputBuffer;
|
||||||
|
|
||||||
|
PaSampleFormat outFormat = loopbackContext->test->outputParameters.sampleFormat;
|
||||||
|
if( outFormat != paFloat32 )
|
||||||
|
{
|
||||||
|
// If we need to convert then mix to the g_ConversionBuffer and then convert into the PA outputBuffer.
|
||||||
|
out = (float *) g_ConversionBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
PaQa_EraseBuffer( out, framesPerBuffer, loopbackContext->test->outputParameters.channelCount );
|
PaQa_EraseBuffer( out, framesPerBuffer, loopbackContext->test->outputParameters.channelCount );
|
||||||
|
for( i=0; i<channelsPerFrame; i++ )
|
||||||
|
|
||||||
for( i=0; i<loopbackContext->test->outputParameters.channelCount; i++ )
|
|
||||||
{
|
{
|
||||||
PaQa_MixSine( &loopbackContext->generators[i],
|
PaQa_MixSine( &loopbackContext->generators[i],
|
||||||
out + i,
|
out + i,
|
||||||
framesPerBuffer,
|
framesPerBuffer,
|
||||||
loopbackContext->test->outputParameters.channelCount );
|
channelsPerFrame );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( outFormat != paFloat32 )
|
||||||
|
{
|
||||||
|
PaQa_ConvertFromFloat( out, framesPerBuffer * channelsPerFrame, outFormat, outputBuffer );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return done ? paComplete : paContinue;
|
return done ? paComplete : paContinue;
|
||||||
}
|
}
|
||||||
|
|
@ -330,8 +364,8 @@ static int RecordAndPlayBlockingIO( PaStream *inStream,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
float *in = (float *)g_BigBuffer;
|
float *in = (float *)g_ReadWriteBuffer;
|
||||||
float *out = (float *)g_BigBuffer;
|
float *out = (float *)g_ReadWriteBuffer;
|
||||||
PaError err;
|
PaError err;
|
||||||
int done = 0;
|
int done = 0;
|
||||||
long available;
|
long available;
|
||||||
|
|
@ -351,6 +385,11 @@ static int RecordAndPlayBlockingIO( PaStream *inStream,
|
||||||
{
|
{
|
||||||
QA_ASSERT_EQUALS( "Pa_ReadStream failed", paNoError, err );
|
QA_ASSERT_EQUALS( "Pa_ReadStream failed", paNoError, err );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
loopbackContext->inputOverflowCount += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Save in a recording.
|
// Save in a recording.
|
||||||
for( i=0; i<loopbackContext->test->inputParameters.channelCount; i++ )
|
for( i=0; i<loopbackContext->test->inputParameters.channelCount; i++ )
|
||||||
|
|
@ -381,6 +420,11 @@ static int RecordAndPlayBlockingIO( PaStream *inStream,
|
||||||
{
|
{
|
||||||
QA_ASSERT_EQUALS( "Pa_WriteStream failed", paNoError, err );
|
QA_ASSERT_EQUALS( "Pa_WriteStream failed", paNoError, err );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
loopbackContext->outputUnderflowCount += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
loopbackContext->callbackCount += 1;
|
loopbackContext->callbackCount += 1;
|
||||||
|
|
||||||
|
|
@ -664,7 +708,7 @@ static int PaQa_SingleLoopBackTest( UserOptions *userOptions, TestParameters *te
|
||||||
err = PaQa_RunLoopback( &loopbackContext );
|
err = PaQa_RunLoopback( &loopbackContext );
|
||||||
QA_ASSERT_TRUE("loopback did not run", (loopbackContext.callbackCount > 1) );
|
QA_ASSERT_TRUE("loopback did not run", (loopbackContext.callbackCount > 1) );
|
||||||
|
|
||||||
// Analyse recording to to detect glitches.
|
// Analyse recording to detect glitches.
|
||||||
for( i=0; i<testParams->samplesPerFrame; i++ )
|
for( i=0; i<testParams->samplesPerFrame; i++ )
|
||||||
{
|
{
|
||||||
double freq = PaQa_GetNthFrequency( testParams->baseFrequency, i );
|
double freq = PaQa_GetNthFrequency( testParams->baseFrequency, i );
|
||||||
|
|
@ -674,7 +718,8 @@ static int PaQa_SingleLoopBackTest( UserOptions *userOptions, TestParameters *te
|
||||||
|
|
||||||
if( i==0 )
|
if( i==0 )
|
||||||
{
|
{
|
||||||
printf("%7.1f | ", analysisResult.latency );
|
double latencyMSec = 1000.0 * analysisResult.latency / testParams->sampleRate;
|
||||||
|
printf("%7.2f | ", latencyMSec );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( analysisResult.valid )
|
if( analysisResult.valid )
|
||||||
|
|
@ -708,6 +753,13 @@ static int PaQa_SingleLoopBackTest( UserOptions *userOptions, TestParameters *te
|
||||||
{
|
{
|
||||||
printf( "OK" );
|
printf( "OK" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf( ", %d/%d/%d/%d, ",
|
||||||
|
loopbackContext.inputOverflowCount,
|
||||||
|
loopbackContext.inputUnderflowCount,
|
||||||
|
loopbackContext.outputOverflowCount,
|
||||||
|
loopbackContext.outputUnderflowCount );
|
||||||
|
|
||||||
printf( "\n" );
|
printf( "\n" );
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -757,6 +809,7 @@ static int PaQa_AnalyzeLoopbackConnection( UserOptions *userOptions, PaDeviceInd
|
||||||
int iFlags;
|
int iFlags;
|
||||||
int iRate;
|
int iRate;
|
||||||
int iSize;
|
int iSize;
|
||||||
|
int iFormat;
|
||||||
int totalBadChannels = 0;
|
int totalBadChannels = 0;
|
||||||
TestParameters testParams;
|
TestParameters testParams;
|
||||||
const PaDeviceInfo *inputDeviceInfo;
|
const PaDeviceInfo *inputDeviceInfo;
|
||||||
|
|
@ -764,27 +817,37 @@ static int PaQa_AnalyzeLoopbackConnection( UserOptions *userOptions, PaDeviceInd
|
||||||
inputDeviceInfo = Pa_GetDeviceInfo( inputDevice );
|
inputDeviceInfo = Pa_GetDeviceInfo( inputDevice );
|
||||||
outputDeviceInfo = Pa_GetDeviceInfo( outputDevice );
|
outputDeviceInfo = Pa_GetDeviceInfo( outputDevice );
|
||||||
|
|
||||||
|
double bestSampleRate = 44100.0;
|
||||||
|
int bestBufferSize = 32;
|
||||||
|
|
||||||
|
|
||||||
printf( "=============== Analysing Loopback %d to %d ====================\n", outputDevice, inputDevice );
|
printf( "=============== Analysing Loopback %d to %d ====================\n", outputDevice, inputDevice );
|
||||||
printf( " Devices: %s => %s\n", outputDeviceInfo->name, inputDeviceInfo->name);
|
printf( " Devices: %s => %s\n", outputDeviceInfo->name, inputDeviceInfo->name);
|
||||||
|
|
||||||
int flagSettings[] = { 0, 1 };
|
// test half duplex first because it is more likely to work.
|
||||||
|
int flagSettings[] = { PAQA_FLAG_TWO_STREAMS, 0 };
|
||||||
int numFlagSettings = (sizeof(flagSettings)/sizeof(int));
|
int numFlagSettings = (sizeof(flagSettings)/sizeof(int));
|
||||||
|
|
||||||
double sampleRates[] = { 44100.0, 48000.0, 8000.0, 11025.0, 16000.0, 22050.0, 32000.0, 96000.0 };
|
double sampleRates[] = { 8000.0, 11025.0, 16000.0, 22050.0, 32000.0, 44100.0, 48000.0, 96000.0 };
|
||||||
int numRates = (sizeof(sampleRates)/sizeof(double));
|
int numRates = (sizeof(sampleRates)/sizeof(double));
|
||||||
|
|
||||||
int framesPerBuffers[] = { 256, 16, 32, 40, 64, 100, 128, 512, 1024 };
|
int framesPerBuffers[] = { 16, 32, 40, 64, 100, 128, 256, 512, 1024 };
|
||||||
int numBufferSizes = (sizeof(framesPerBuffers)/sizeof(int));
|
int numBufferSizes = (sizeof(framesPerBuffers)/sizeof(int));
|
||||||
|
|
||||||
|
PaSampleFormat sampleFormats[] = { paUInt8, paInt16, paInt32 };
|
||||||
|
int numSampleFormats = (sizeof(sampleFormats)/sizeof(PaSampleFormat));
|
||||||
|
|
||||||
// Check to see if a specific value was requested.
|
// Check to see if a specific value was requested.
|
||||||
if( userOptions->sampleRate > 0 )
|
if( userOptions->sampleRate > 0 )
|
||||||
{
|
{
|
||||||
sampleRates[0] = userOptions->sampleRate;
|
sampleRates[0] = userOptions->sampleRate;
|
||||||
|
bestSampleRate = userOptions->sampleRate;
|
||||||
numRates = 1;
|
numRates = 1;
|
||||||
}
|
}
|
||||||
if( userOptions->framesPerBuffer > 0 )
|
if( userOptions->framesPerBuffer > 0 )
|
||||||
{
|
{
|
||||||
framesPerBuffers[0] = userOptions->framesPerBuffer;
|
framesPerBuffers[0] = userOptions->framesPerBuffer;
|
||||||
|
bestBufferSize = userOptions->framesPerBuffer;
|
||||||
numBufferSizes = 1;
|
numBufferSizes = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -796,11 +859,11 @@ static int PaQa_AnalyzeLoopbackConnection( UserOptions *userOptions, PaDeviceInd
|
||||||
{
|
{
|
||||||
testParams.flags = flagSettings[iFlags];
|
testParams.flags = flagSettings[iFlags];
|
||||||
printf( "************ Mode = %s ************\n",
|
printf( "************ Mode = %s ************\n",
|
||||||
(( iFlags & 1 ) ? s_FlagOnNames[0] : s_FlagOffNames[0]) );
|
(( testParams.flags & 1 ) ? s_FlagOnNames[0] : s_FlagOffNames[0]) );
|
||||||
printf("|-sRate-|-buffer-|-latency-|-channel results--------------------|\n");
|
printf("|-sRate-|-buffer-|-latency-|-channel results--------------------|\n");
|
||||||
|
|
||||||
// Loop though combinations of audio parameters.
|
// Loop though combinations of audio parameters.
|
||||||
testParams.framesPerBuffer = framesPerBuffers[0];
|
testParams.framesPerBuffer = bestBufferSize;
|
||||||
for( iRate=0; iRate<numRates; iRate++ )
|
for( iRate=0; iRate<numRates; iRate++ )
|
||||||
{
|
{
|
||||||
// SAMPLE RATE
|
// SAMPLE RATE
|
||||||
|
|
@ -812,7 +875,7 @@ static int PaQa_AnalyzeLoopbackConnection( UserOptions *userOptions, PaDeviceInd
|
||||||
}
|
}
|
||||||
printf( "\n" );
|
printf( "\n" );
|
||||||
|
|
||||||
testParams.sampleRate = sampleRates[0];
|
testParams.sampleRate = bestSampleRate;
|
||||||
testParams.maxFrames = (int) (1.2 * testParams.sampleRate);
|
testParams.maxFrames = (int) (1.2 * testParams.sampleRate);
|
||||||
for( iSize=0; iSize<numBufferSizes; iSize++ )
|
for( iSize=0; iSize<numBufferSizes; iSize++ )
|
||||||
{
|
{
|
||||||
|
|
@ -822,10 +885,25 @@ static int PaQa_AnalyzeLoopbackConnection( UserOptions *userOptions, PaDeviceInd
|
||||||
int numBadChannels = PaQa_SingleLoopBackTest( userOptions, &testParams );
|
int numBadChannels = PaQa_SingleLoopBackTest( userOptions, &testParams );
|
||||||
totalBadChannels += numBadChannels;
|
totalBadChannels += numBadChannels;
|
||||||
}
|
}
|
||||||
printf( "\n" );
|
printf( "\n" );
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("Test Sample Formats using Half Duplex IO -----\n" );
|
||||||
|
testParams.flags = PAQA_FLAG_TWO_STREAMS;
|
||||||
|
testParams.sampleRate = bestSampleRate;
|
||||||
|
testParams.framesPerBuffer = bestBufferSize;
|
||||||
|
|
||||||
|
for( iFormat=0; iFormat<numSampleFormats; iFormat++ )
|
||||||
|
{
|
||||||
|
PaSampleFormat format = sampleFormats[ iFormat ];
|
||||||
|
testParams.inputParameters.sampleFormat = format;
|
||||||
|
testParams.outputParameters.sampleFormat = format;
|
||||||
|
printf("Sample format = %d\n", (int) format );
|
||||||
|
int numBadChannels = PaQa_SingleLoopBackTest( userOptions, &testParams );
|
||||||
|
totalBadChannels += numBadChannels;
|
||||||
|
}
|
||||||
|
printf( "\n" );
|
||||||
|
|
||||||
return totalBadChannels;
|
return totalBadChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1062,6 +1140,73 @@ error:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*==========================================================================================*/
|
||||||
|
int TestSampleFormatConversion( void )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const float floatInput[] = { 1.0, 0.5, -0.5, -1.0 };
|
||||||
|
|
||||||
|
const unsigned char ucharInput[] = { 255, 128+64, 64, 0 };
|
||||||
|
const short shortInput[] = { 32767, 32768/2, -32768/2, -32768 };
|
||||||
|
const int intInput[] = { 2147483647, 2147483647/2, -2147483648/2, -2147483648 };
|
||||||
|
|
||||||
|
float floatOutput[4];
|
||||||
|
short shortOutput[4];
|
||||||
|
int intOutput[4];
|
||||||
|
unsigned char ucharOutput[4];
|
||||||
|
|
||||||
|
QA_ASSERT_EQUALS("int must be 32-bit", 4, (int) sizeof(int) );
|
||||||
|
QA_ASSERT_EQUALS("short must be 16-bit", 2, (int) sizeof(short) );
|
||||||
|
|
||||||
|
// from Float ======
|
||||||
|
PaQa_ConvertFromFloat( floatInput, 4, paUInt8, ucharOutput );
|
||||||
|
for( i=0; i<4; i++ )
|
||||||
|
{
|
||||||
|
QA_ASSERT_CLOSE( "paFloat32 -> paUint8 -> error", ucharInput[i], ucharOutput[i], 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
PaQa_ConvertFromFloat( floatInput, 4, paInt16, shortOutput );
|
||||||
|
for( i=0; i<4; i++ )
|
||||||
|
{
|
||||||
|
QA_ASSERT_CLOSE( "paFloat32 -> paInt16 error", shortInput[i], shortOutput[i], 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
PaQa_ConvertFromFloat( floatInput, 4, paInt32, intOutput );
|
||||||
|
for( i=0; i<4; i++ )
|
||||||
|
{
|
||||||
|
QA_ASSERT_CLOSE( "paFloat32 -> paInt32 error", intInput[i], intOutput[i], 0x00010000 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// to Float ======
|
||||||
|
memset( floatOutput, 0, sizeof(floatOutput) );
|
||||||
|
PaQa_ConvertToFloat( ucharInput, 4, paUInt8, floatOutput );
|
||||||
|
for( i=0; i<4; i++ )
|
||||||
|
{
|
||||||
|
QA_ASSERT_CLOSE( "paUInt8 -> paFloat32 error", floatInput[i], floatOutput[i], 0.01 );
|
||||||
|
}
|
||||||
|
|
||||||
|
memset( floatOutput, 0, sizeof(floatOutput) );
|
||||||
|
PaQa_ConvertToFloat( shortInput, 4, paInt16, floatOutput );
|
||||||
|
for( i=0; i<4; i++ )
|
||||||
|
{
|
||||||
|
QA_ASSERT_CLOSE( "paInt16 -> paFloat32 error", floatInput[i], floatOutput[i], 0.001 );
|
||||||
|
}
|
||||||
|
|
||||||
|
memset( floatOutput, 0, sizeof(floatOutput) );
|
||||||
|
PaQa_ConvertToFloat( intInput, 4, paInt32, floatOutput );
|
||||||
|
for( i=0; i<4; i++ )
|
||||||
|
{
|
||||||
|
QA_ASSERT_CLOSE( "paInt32 -> paFloat32 error", floatInput[i], floatOutput[i], 0.00001 );
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
void usage( const char *name )
|
void usage( const char *name )
|
||||||
{
|
{
|
||||||
|
|
@ -1151,6 +1296,9 @@ int main( int argc, char **argv )
|
||||||
|
|
||||||
result = PaQa_TestAnalyzer();
|
result = PaQa_TestAnalyzer();
|
||||||
|
|
||||||
|
// Test sample format conversion tool.
|
||||||
|
result = TestSampleFormatConversion();
|
||||||
|
|
||||||
if( (result == 0) && (justMath == 0) )
|
if( (result == 0) && (justMath == 0) )
|
||||||
{
|
{
|
||||||
Pa_Initialize();
|
Pa_Initialize();
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
|
|
||||||
#include "paqa_tools.h"
|
#include "paqa_tools.h"
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
void PaQa_ListAudioDevices(void)
|
void PaQa_ListAudioDevices(void)
|
||||||
{
|
{
|
||||||
|
|
@ -54,3 +55,95 @@ void PaQa_ListAudioDevices(void)
|
||||||
printf( ", on %s\n", Pa_GetHostApiInfo( deviceInfo->hostApi )->name );
|
printf( ", on %s\n", Pa_GetHostApiInfo( deviceInfo->hostApi )->name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
void PaQa_ConvertToFloat( const void *input, int numSamples, PaSampleFormat inFormat, float *output )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
switch( inFormat )
|
||||||
|
{
|
||||||
|
case paUInt8:
|
||||||
|
{
|
||||||
|
unsigned char *data = (unsigned char *)input;
|
||||||
|
for( i=0; i<numSamples; i++ )
|
||||||
|
{
|
||||||
|
int value = *data++;
|
||||||
|
value -= 128;
|
||||||
|
*output++ = value / 128.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case paInt16:
|
||||||
|
{
|
||||||
|
short *data = (short *)input;
|
||||||
|
for( i=0; i<numSamples; i++ )
|
||||||
|
{
|
||||||
|
*output++ = *data++ / 32768.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case paInt32:
|
||||||
|
{
|
||||||
|
int *data = (int *)input;
|
||||||
|
for( i=0; i<numSamples; i++ )
|
||||||
|
{
|
||||||
|
int value = *data++;
|
||||||
|
value = value >> 8;
|
||||||
|
float fval = (float) (value / ((double) 0x00800000));
|
||||||
|
*output++ = fval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
void PaQa_ConvertFromFloat( const float *input, int numSamples, PaSampleFormat outFormat, void *output )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
switch( outFormat )
|
||||||
|
{
|
||||||
|
case paUInt8:
|
||||||
|
{
|
||||||
|
unsigned char *data = (unsigned char *)output;
|
||||||
|
for( i=0; i<numSamples; i++ )
|
||||||
|
{
|
||||||
|
float value = *input++;
|
||||||
|
int byte = ((int) (value * 127)) + 128;
|
||||||
|
*data++ = (unsigned char) byte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case paInt16:
|
||||||
|
{
|
||||||
|
short *data = (short *)output;
|
||||||
|
for( i=0; i<numSamples; i++ )
|
||||||
|
{
|
||||||
|
float value = *input++;
|
||||||
|
// Use assymmetric conversion to avoid clipping.
|
||||||
|
short sval = value * 32767.0;
|
||||||
|
*data++ = sval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case paInt32:
|
||||||
|
{
|
||||||
|
int *data = (int *)output;
|
||||||
|
for( i=0; i<numSamples; i++ )
|
||||||
|
{
|
||||||
|
float value = *input++;
|
||||||
|
// Use assymmetric conversion to avoid clipping.
|
||||||
|
int ival = value * ((double) 0x007FFFF0);
|
||||||
|
ival = ival << 8;
|
||||||
|
*data++ = ival;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,4 +45,8 @@
|
||||||
|
|
||||||
void PaQa_ListAudioDevices(void);
|
void PaQa_ListAudioDevices(void);
|
||||||
|
|
||||||
|
void PaQa_ConvertToFloat( const void *input, int numSamples, PaSampleFormat inFormat, float *output );
|
||||||
|
|
||||||
|
void PaQa_ConvertFromFloat( const float *input, int numSamples, PaSampleFormat outFormat, void *output );
|
||||||
|
|
||||||
#endif /* _PAQA_TOOLS_H */
|
#endif /* _PAQA_TOOLS_H */
|
||||||
|
|
|
||||||
|
|
@ -555,7 +555,6 @@ error:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*==========================================================================================*/
|
/*==========================================================================================*/
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue