first commit

This commit is contained in:
sanya
2025-09-01 14:20:39 +00:00
committed by ExternPointer
commit 490fc11f6a
4328 changed files with 1796224 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
# Test projects
# Use the macro to add test projects
MACRO(ADD_TEST appl_name)
ADD_EXECUTABLE(${appl_name} "${appl_name}.c")
TARGET_LINK_LIBRARIES(${appl_name} portaudio_static)
SET_TARGET_PROPERTIES(${appl_name}
PROPERTIES
FOLDER "Test"
)
ENDMACRO(ADD_TEST)
ADD_TEST(patest_longsine)

52
third_party/portaudio/test/README.txt vendored Normal file
View File

@@ -0,0 +1,52 @@
TODO - This should be moved into a doxydoc page.
For more information on the TestPlan please visit:
http://www.portaudio.com/trac/wiki/TestPlan
This directory contains various programs to test PortAudio. The files
named patest_* are tests.
All following tests are up to date with the V19 API. They should all compile
(without any warnings on GCC 3.3). Note that this does not necessarily mean that
the tests pass, just that they compile.
x- paqa_devs.c
x- paqa_errs.c (needs reviewing)
x- patest1.c
x- patest_buffer.c
x- patest_callbackstop.c
x- patest_clip.c (last test fails, dither doesn't currently force clip in V19)
x- patest_dither.c
x- patest_hang.c
x- patest_latency.c
x- patest_leftright.c
x- patest_longsine.c
x- patest_many.c
x- patest_maxsines.c
x- patest_mono.c
x- patest_multi_sine.c
x- patest_pink.c
x- patest_prime.c
x- patest_read_record.c
x- patest_record.c
x- patest_ringmix.c
x- patest_saw.c
x- patest_sine.c
x- patest_sine8.c
x- patest_sine_formats.c
x- patest_sine_time.c
x- patest_start_stop.c
x- patest_stop.c
x- patest_sync.c
x- patest_toomanysines.c
x- patest_two_rates.c
x- patest_underflow.c
x- patest_wire.c
x- patest_write_sine.c
x- pa_devs.c
x- pa_fuzz.c
x- pa_minlat.c
Note that Phil Burk deleted the debug_* tests on 2/26/11. They were just hacked
versions of old V18 tests. If we need to debug then we can just hack a working V19 test.

205
third_party/portaudio/test/pa_minlat.c vendored Normal file
View File

@@ -0,0 +1,205 @@
/** @file pa_minlat.c
@ingroup test_src
@brief Experiment with different numbers of buffers to determine the
minimum latency for a computer.
@author Phil Burk http://www.softsynth.com
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "portaudio.h"
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TWOPI (M_PI * 2.0)
#define DEFAULT_BUFFER_SIZE (32)
typedef struct
{
double left_phase;
double right_phase;
}
paTestData;
/* Very simple synthesis routine to generate two sine waves. */
static int paminlatCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned int i;
double left_phaseInc = 0.02;
double right_phaseInc = 0.06;
double left_phase = data->left_phase;
double right_phase = data->right_phase;
for( i=0; i<framesPerBuffer; i++ )
{
left_phase += left_phaseInc;
if( left_phase > TWOPI ) left_phase -= TWOPI;
*out++ = (float) sin( left_phase );
right_phase += right_phaseInc;
if( right_phase > TWOPI ) right_phase -= TWOPI;
*out++ = (float) sin( right_phase );
}
data->left_phase = left_phase;
data->right_phase = right_phase;
return 0;
}
int main( int argc, char **argv );
int main( int argc, char **argv )
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
paTestData data;
int go;
int outLatency = 0;
int minLatency = DEFAULT_BUFFER_SIZE * 2;
int framesPerBuffer;
double sampleRate = 44100.0;
char str[256];
char *line;
printf("pa_minlat - Determine minimum latency for your computer.\n");
printf(" usage: pa_minlat {userBufferSize}\n");
printf(" for example: pa_minlat 64\n");
printf("Adjust your stereo until you hear a smooth tone in each speaker.\n");
printf("Then try to find the smallest number of frames that still sounds smooth.\n");
printf("Note that the sound will stop momentarily when you change the number of buffers.\n");
/* Get bufferSize from command line. */
framesPerBuffer = ( argc > 1 ) ? atol( argv[1] ) : DEFAULT_BUFFER_SIZE;
printf("Frames per buffer = %d\n", framesPerBuffer );
data.left_phase = data.right_phase = 0.0;
err = Pa_Initialize();
if( err != paNoError ) goto error;
outLatency = sampleRate * 200.0 / 1000.0; /* 200 msec. */
/* Try different numBuffers in a loop. */
go = 1;
while( go )
{
outputParameters.device = Pa_GetDefaultOutputDevice(); /* Default output device. */
outputParameters.channelCount = 2; /* Stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output. */
outputParameters.suggestedLatency = (double)outLatency / sampleRate; /* In seconds. */
outputParameters.hostApiSpecificStreamInfo = NULL;
printf("Latency = %d frames = %6.1f msec.\n", outLatency, outputParameters.suggestedLatency * 1000.0 );
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
sampleRate,
framesPerBuffer,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
paminlatCallback,
&data );
if( err != paNoError ) goto error;
if( stream == NULL ) goto error;
/* Start audio. */
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
/* Ask user for a new nlatency. */
printf("\nMove windows around to see if the sound glitches.\n");
printf("Latency now %d, enter new number of frames, or 'q' to quit: ", outLatency );
line = fgets( str, 256, stdin );
if( line == NULL )
{
go = 0;
}
else
{
{
/* Get rid of newline */
size_t l = strlen( str ) - 1;
if( str[ l ] == '\n')
str[ l ] = '\0';
}
if( str[0] == 'q' ) go = 0;
else
{
outLatency = atol( str );
if( outLatency < minLatency )
{
printf( "Latency below minimum of %d! Set to minimum!!!\n", minLatency );
outLatency = minLatency;
}
}
}
/* Stop sound until ENTER hit. */
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
}
printf("A good setting for latency would be somewhat higher than\n");
printf("the minimum latency that worked.\n");
printf("PortAudio: Test finished.\n");
Pa_Terminate();
return 0;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return 1;
}

208
third_party/portaudio/test/patest1.c vendored Normal file
View File

@@ -0,0 +1,208 @@
/** @file patest1.c
@ingroup test_src
@brief Ring modulate the audio input with a sine wave for 20 seconds.
@author Ross Bencina <rossb@audiomulch.com>
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define SAMPLE_RATE (44100)
typedef struct
{
float sine[100];
int phase;
int sampsToGo;
}
patest1data;
static int patest1Callback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
patest1data *data = (patest1data*)userData;
float *in = (float*)inputBuffer;
float *out = (float*)outputBuffer;
int framesToCalc = framesPerBuffer;
unsigned long i = 0;
int finished;
if( data->sampsToGo < framesPerBuffer )
{
framesToCalc = data->sampsToGo;
finished = paComplete;
}
else
{
finished = paContinue;
}
for( ; i<framesToCalc; i++ )
{
*out++ = *in++ * data->sine[data->phase]; /* left */
*out++ = *in++ * data->sine[data->phase++]; /* right */
if( data->phase >= 100 )
data->phase = 0;
}
data->sampsToGo -= framesToCalc;
/* zero remainder of final buffer if not already done */
for( ; i<framesPerBuffer; i++ )
{
*out++ = 0; /* left */
*out++ = 0; /* right */
}
return finished;
}
int main(int argc, char* argv[]);
int main(int argc, char* argv[])
{
PaStream *stream;
PaError err;
patest1data data;
int i;
PaStreamParameters inputParameters, outputParameters;
const PaHostErrorInfo* herr;
printf("patest1.c\n"); fflush(stdout);
printf("Ring modulate input for 20 seconds.\n"); fflush(stdout);
/* initialise sinusoidal wavetable */
for( i=0; i<100; i++ )
data.sine[i] = sin( ((double)i/100.) * M_PI * 2. );
data.phase = 0;
data.sampsToGo = SAMPLE_RATE * 20; /* 20 seconds. */
/* initialise portaudio subsystem */
err = Pa_Initialize();
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (inputParameters.device == paNoDevice) {
fprintf(stderr, "Error: No input default device.\n");
goto done;
}
inputParameters.channelCount = 2; /* stereo input */
inputParameters.sampleFormat = paFloat32; /* 32 bit floating point input */
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto done;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&stream,
&inputParameters,
&outputParameters,
(double)SAMPLE_RATE, /* Samplerate in Hertz. */
512, /* Small buffers */
paClipOff, /* We won't output out of range samples so don't bother clipping them. */
patest1Callback,
&data );
if( err != paNoError ) goto done;
err = Pa_StartStream( stream );
if( err != paNoError ) goto done;
printf( "Press any key to end.\n" ); fflush(stdout);
getc( stdin ); /* wait for input before exiting */
err = Pa_AbortStream( stream );
if( err != paNoError ) goto done;
printf( "Waiting for stream to complete...\n" );
/* sleep until playback has finished */
while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) Pa_Sleep(1000);
if( err < 0 ) goto done;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto done;
done:
Pa_Terminate();
if( err != paNoError )
{
fprintf( stderr, "An error occurred while using portaudio\n" );
if( err == paUnanticipatedHostError )
{
fprintf( stderr, " unanticipated host error.\n");
herr = Pa_GetLastHostErrorInfo();
if (herr)
{
fprintf( stderr, " Error number: %ld\n", herr->errorCode );
if (herr->errorText)
fprintf( stderr, " Error text: %s\n", herr->errorText );
}
else
fprintf( stderr, " Pa_GetLastHostErrorInfo() failed!\n" );
}
else
{
fprintf( stderr, " Error number: %d\n", err );
fprintf( stderr, " Error text: %s\n", Pa_GetErrorText( err ) );
}
err = 1; /* Always return 0 or 1, but no other return codes. */
}
printf( "bye\n" );
return err;
}

View File

@@ -0,0 +1,206 @@
/** @file patest_buffer.c
@ingroup test_src
@brief Test opening streams with different buffer sizes.
@author Phil Burk http://www.softsynth.com
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "portaudio.h"
#define NUM_SECONDS (3)
#define SAMPLE_RATE (44100)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
#define BUFFER_TABLE 14
long buffer_table[] = {paFramesPerBufferUnspecified,16,32,64,128,200,256,500,512,600,723,1000,1024,2345};
typedef struct
{
short sine[TABLE_SIZE];
int left_phase;
int right_phase;
unsigned int sampsToGo;
}
paTestData;
PaError TestOnce( int buffersize, PaDeviceIndex );
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patest1Callback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
short *out = (short*)outputBuffer;
unsigned int i;
int finished = 0;
(void) inputBuffer; /* Prevent "unused variable" warnings. */
if( data->sampsToGo < framesPerBuffer )
{
/* final buffer... */
for( i=0; i<data->sampsToGo; i++ )
{
*out++ = data->sine[data->left_phase]; /* left */
*out++ = data->sine[data->right_phase]; /* right */
data->left_phase += 1;
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
}
/* zero remainder of final buffer */
for( ; i<framesPerBuffer; i++ )
{
*out++ = 0; /* left */
*out++ = 0; /* right */
}
finished = 1;
}
else
{
for( i=0; i<framesPerBuffer; i++ )
{
*out++ = data->sine[data->left_phase]; /* left */
*out++ = data->sine[data->right_phase]; /* right */
data->left_phase += 1;
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
}
data->sampsToGo -= framesPerBuffer;
}
return finished;
}
/*******************************************************************/
int main(int argc, char **args);
int main(int argc, char **args)
{
int i;
int device = -1;
PaError err;
printf("Test opening streams with different buffer sizes\n");
if( argc > 1 ) {
device=atoi( args[1] );
printf("Using device number %d.\n\n", device );
} else {
printf("Using default device.\n\n" );
}
for (i = 0 ; i < BUFFER_TABLE; i++)
{
printf("Buffer size %ld\n", buffer_table[i]);
err = TestOnce(buffer_table[i], device);
if( err < 0 ) return 0;
}
return 0;
}
PaError TestOnce( int buffersize, PaDeviceIndex device )
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
paTestData data;
int i;
int totalSamps;
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (short) (32767.0 * sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ));
}
data.left_phase = data.right_phase = 0;
data.sampsToGo = totalSamps = NUM_SECONDS * SAMPLE_RATE; /* Play for a few seconds. */
err = Pa_Initialize();
if( err != paNoError ) goto error;
if( device == -1 )
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
else
outputParameters.device = device ;
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paInt16; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
buffersize, /* frames per buffer */
(paClipOff | paDitherOff),
patest1Callback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Waiting for sound to finish.\n");
Pa_Sleep(1000*NUM_SECONDS);
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
return paNoError;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
fprintf( stderr, "Host Error message: %s\n", Pa_GetLastHostErrorInfo()->errorText );
return err;
}

View File

@@ -0,0 +1,252 @@
/** @file patest_callbackstop.c
@ingroup test_src
@brief Test the paComplete callback result code.
@author Ross Bencina <rossb@audiomulch.com>
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define NUM_SECONDS (5)
#define NUM_LOOPS (4)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (67)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
typedef struct
{
float sine[TABLE_SIZE];
int phase;
unsigned long generatedFramesCount;
volatile int callbackReturnedPaComplete;
volatile int callbackInvokedAfterReturningPaComplete;
char message[100];
}
TestData;
/*
This routine will be called by the PortAudio stream when audio is needed.
It may be called at interrupt level on some machines so don't do anything
that could mess up the system like calling malloc() or free().
*/
static int TestCallback( const void *input, void *output,
unsigned long frameCount,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
TestData *data = (TestData*)userData;
float *out = (float*)output;
unsigned long i;
float x;
(void) input; /* Prevent unused variable warnings. */
(void) timeInfo;
(void) statusFlags;
if( data->callbackReturnedPaComplete )
data->callbackInvokedAfterReturningPaComplete = 1;
for( i=0; i<frameCount; i++ )
{
/* generate tone */
x = data->sine[ data->phase++ ];
if( data->phase >= TABLE_SIZE )
data->phase -= TABLE_SIZE;
*out++ = x; /* left */
*out++ = x; /* right */
}
data->generatedFramesCount += frameCount;
if( data->generatedFramesCount >= (NUM_SECONDS * SAMPLE_RATE) )
{
data->callbackReturnedPaComplete = 1;
return paComplete;
}
else
{
return paContinue;
}
}
/*
* This routine is called by portaudio when playback is done.
*/
static void StreamFinished( void* userData )
{
TestData *data = (TestData *) userData;
printf( "Stream Completed: %s\n", data->message );
}
/*----------------------------------------------------------------------------*/
int main(void);
int main(void)
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
TestData data;
int i, j;
printf( "PortAudio Test: output sine wave. SR = %d, BufSize = %d\n",
SAMPLE_RATE, FRAMES_PER_BUFFER );
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = Pa_GetDefaultOutputDevice();
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* output will be in-range, so no need to clip */
TestCallback,
&data );
if( err != paNoError ) goto error;
sprintf( data.message, "Loop: XX" );
err = Pa_SetStreamFinishedCallback( stream, &StreamFinished );
if( err != paNoError ) goto error;
printf("Repeating test %d times.\n", NUM_LOOPS );
for( i=0; i < NUM_LOOPS; ++i )
{
data.phase = 0;
data.generatedFramesCount = 0;
data.callbackReturnedPaComplete = 0;
data.callbackInvokedAfterReturningPaComplete = 0;
sprintf( data.message, "Loop: %d", i );
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Play for %d seconds.\n", NUM_SECONDS );
/* wait for the callback to complete generating NUM_SECONDS of tone */
do
{
Pa_Sleep( 500 );
}
while( !data.callbackReturnedPaComplete );
printf( "Callback returned paComplete.\n" );
printf( "Waiting for buffers to finish playing...\n" );
/* wait for stream to become inactive,
or for a timeout of approximately NUM_SECONDS
*/
j = 0;
while( (err = Pa_IsStreamActive( stream )) == 1 && j < NUM_SECONDS * 2 )
{
printf(".\n" );
Pa_Sleep( 500 );
++j;
}
if( err < 0 )
{
goto error;
}
else if( err == 1 )
{
printf( "TEST FAILED: Timed out waiting for buffers to finish playing.\n" );
}
else
{
printf("Buffers finished.\n" );
}
if( data.callbackInvokedAfterReturningPaComplete )
{
printf( "TEST FAILED: Callback was invoked after returning paComplete.\n" );
}
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
printf( "sleeping for 1 second...\n" );
Pa_Sleep( 1000 );
}
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

190
third_party/portaudio/test/patest_clip.c vendored Normal file
View File

@@ -0,0 +1,190 @@
/** @file patest_clip.c
@ingroup test_src
@brief Play a sine wave for several seconds at an amplitude
that would require clipping.
@author Phil Burk http://www.softsynth.com
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define NUM_SECONDS (4)
#define SAMPLE_RATE (44100)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
typedef struct paTestData
{
float sine[TABLE_SIZE];
float amplitude;
int left_phase;
int right_phase;
}
paTestData;
PaError PlaySine( paTestData *data, unsigned long flags, float amplitude );
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int sineCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
float amplitude = data->amplitude;
unsigned int i;
(void) inputBuffer; /* Prevent "unused variable" warnings. */
(void) timeInfo;
(void) statusFlags;
for( i=0; i<framesPerBuffer; i++ )
{
*out++ = amplitude * data->sine[data->left_phase]; /* left */
*out++ = amplitude * data->sine[data->right_phase]; /* right */
data->left_phase += 1;
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
}
return 0;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaError err;
paTestData data;
int i;
printf("PortAudio Test: output sine wave with and without clipping.\n");
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
printf("\nHalf amplitude. Should sound like sine wave.\n"); fflush(stdout);
err = PlaySine( &data, paClipOff | paDitherOff, 0.5f );
if( err < 0 ) goto error;
printf("\nFull amplitude. Should sound like sine wave.\n"); fflush(stdout);
err = PlaySine( &data, paClipOff | paDitherOff, 0.999f );
if( err < 0 ) goto error;
printf("\nOver range with clipping and dithering turned OFF. Should sound very nasty.\n");
fflush(stdout);
err = PlaySine( &data, paClipOff | paDitherOff, 1.1f );
if( err < 0 ) goto error;
printf("\nOver range with clipping and dithering turned ON. Should sound smoother than previous.\n");
fflush(stdout);
err = PlaySine( &data, paNoFlag, 1.1f );
if( err < 0 ) goto error;
printf("\nOver range with paClipOff but dithering ON.\n"
"That forces clipping ON so it should sound the same as previous.\n");
fflush(stdout);
err = PlaySine( &data, paClipOff, 1.1f );
if( err < 0 ) goto error;
return 0;
error:
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return 1;
}
/*****************************************************************************/
PaError PlaySine( paTestData *data, unsigned long flags, float amplitude )
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
data->left_phase = data->right_phase = 0;
data->amplitude = amplitude;
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
1024,
flags,
sineCallback,
data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
Pa_Sleep( NUM_SECONDS * 1000 );
printf("CPULoad = %8.6f\n", Pa_GetStreamCpuLoad( stream ) );
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
return paNoError;
error:
return err;
}

View File

@@ -0,0 +1,395 @@
/** @file patest_converters.c
@ingroup test_src
@brief Tests the converter functions in pa_converters.c
@author Ross Bencina <rossb@audiomulch.com>
Link with pa_dither.c and pa_converters.c
see http://www.portaudio.com/trac/wiki/V19ConvertersStatus for a discussion of this.
*/
/*
* $Id: $
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com/
* Copyright (c) 1999-2008 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "portaudio.h"
#include "pa_converters.h"
#include "pa_dither.h"
#include "pa_types.h"
#include "pa_endianness.h"
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define MAX_PER_CHANNEL_FRAME_COUNT (2048)
#define MAX_CHANNEL_COUNT (8)
#define SAMPLE_FORMAT_COUNT (6)
static PaSampleFormat sampleFormats_[ SAMPLE_FORMAT_COUNT ] =
{ paFloat32, paInt32, paInt24, paInt16, paInt8, paUInt8 }; /* all standard PA sample formats */
static const char* sampleFormatNames_[SAMPLE_FORMAT_COUNT] =
{ "paFloat32", "paInt32", "paInt24", "paInt16", "paInt8", "paUInt8" };
static const char* abbreviatedSampleFormatNames_[SAMPLE_FORMAT_COUNT] =
{ "f32", "i32", "i24", "i16", " i8", "ui8" };
PaError My_Pa_GetSampleSize( PaSampleFormat format );
/*
available flags are paClipOff and paDitherOff
clipping is usually applied for float -> int conversions
dither is usually applied for all downconversions (ie anything but 8bit->8bit conversions
*/
static int CanClip( PaSampleFormat sourceFormat, PaSampleFormat destinationFormat )
{
if( sourceFormat == paFloat32 && destinationFormat != sourceFormat )
return 1;
else
return 0;
}
static int CanDither( PaSampleFormat sourceFormat, PaSampleFormat destinationFormat )
{
if( sourceFormat < destinationFormat && sourceFormat != paInt8 )
return 1;
else
return 0;
}
static void GenerateOneCycleSineReference( double *out, int frameCount, int strideFrames )
{
int i;
for( i=0; i < frameCount; ++i ){
*out = sin( ((double)i/(double)frameCount) * 2. * M_PI );
out += strideFrames;
}
}
static void GenerateOneCycleSine( PaSampleFormat format, void *buffer, int frameCount, int strideFrames )
{
switch( format ){
case paFloat32:
{
int i;
float *out = (float*)buffer;
for( i=0; i < frameCount; ++i ){
*out = (float).9 * sin( ((double)i/(double)frameCount) * 2. * M_PI );
out += strideFrames;
}
}
break;
case paInt32:
{
int i;
PaInt32 *out = (PaInt32*)buffer;
for( i=0; i < frameCount; ++i ){
*out = (PaInt32)(.9 * sin( ((double)i/(double)frameCount) * 2. * M_PI ) * 0x7FFFFFFF);
out += strideFrames;
}
}
break;
case paInt24:
{
int i;
unsigned char *out = (unsigned char*)buffer;
for( i=0; i < frameCount; ++i ){
signed long temp = (PaInt32)(.9 * sin( ((double)i/(double)frameCount) * 2. * M_PI ) * 0x7FFFFFFF);
#if defined(PA_LITTLE_ENDIAN)
out[0] = (unsigned char)(temp >> 8) & 0xFF;
out[1] = (unsigned char)(temp >> 16) & 0xFF;
out[2] = (unsigned char)(temp >> 24) & 0xFF;
#elif defined(PA_BIG_ENDIAN)
out[0] = (unsigned char)(temp >> 24) & 0xFF;
out[1] = (unsigned char)(temp >> 16) & 0xFF;
out[2] = (unsigned char)(temp >> 8) & 0xFF;
#endif
out += 3;
}
}
break;
case paInt16:
{
int i;
PaInt16 *out = (PaInt16*)buffer;
for( i=0; i < frameCount; ++i ){
*out = (PaInt16)(.9 * sin( ((double)i/(double)frameCount) * 2. * M_PI ) * 0x7FFF );
out += strideFrames;
}
}
break;
case paInt8:
{
int i;
signed char *out = (signed char*)buffer;
for( i=0; i < frameCount; ++i ){
*out = (signed char)(.9 * sin( ((double)i/(double)frameCount) * 2. * M_PI ) * 0x7F );
out += strideFrames;
}
}
break;
case paUInt8:
{
int i;
unsigned char *out = (unsigned char*)buffer;
for( i=0; i < frameCount; ++i ){
*out = (unsigned char)( .5 * (1. + (.9 * sin( ((double)i/(double)frameCount) * 2. * M_PI ))) * 0xFF );
out += strideFrames;
}
}
break;
}
}
int TestNonZeroPresent( void *buffer, int size )
{
char *p = (char*)buffer;
int i;
for( i=0; i < size; ++i ){
if( *p != 0 )
return 1;
++p;
}
return 0;
}
float MaximumAbsDifference( float* sourceBuffer, float* referenceBuffer, int count )
{
float result = 0;
float difference;
while( count-- ){
difference = fabs( *sourceBuffer++ - *referenceBuffer++ );
if( difference > result )
result = difference;
}
return result;
}
int main( const char **argv, int argc )
{
PaUtilTriangularDitherGenerator ditherState;
PaUtilConverter *converter;
void *destinationBuffer, *sourceBuffer;
double *referenceBuffer;
int sourceFormatIndex, destinationFormatIndex;
PaSampleFormat sourceFormat, destinationFormat;
PaStreamFlags flags;
int passFailMatrix[SAMPLE_FORMAT_COUNT][SAMPLE_FORMAT_COUNT]; // [source][destination]
float noiseAmplitudeMatrix[SAMPLE_FORMAT_COUNT][SAMPLE_FORMAT_COUNT]; // [source][destination]
float amp;
#define FLAG_COMBINATION_COUNT (4)
PaStreamFlags flagCombinations[FLAG_COMBINATION_COUNT] = { paNoFlag, paClipOff, paDitherOff, paClipOff | paDitherOff };
const char *flagCombinationNames[FLAG_COMBINATION_COUNT] = { "paNoFlag", "paClipOff", "paDitherOff", "paClipOff | paDitherOff" };
int flagCombinationIndex;
PaUtil_InitializeTriangularDitherState( &ditherState );
/* allocate more than enough space, we use sizeof(float) but we need to fit any 32 bit datum */
destinationBuffer = (void*)malloc( MAX_PER_CHANNEL_FRAME_COUNT * MAX_CHANNEL_COUNT * sizeof(float) );
sourceBuffer = (void*)malloc( MAX_PER_CHANNEL_FRAME_COUNT * MAX_CHANNEL_COUNT * sizeof(float) );
referenceBuffer = (void*)malloc( MAX_PER_CHANNEL_FRAME_COUNT * MAX_CHANNEL_COUNT * sizeof(float) );
/* the first round of tests simply iterates through the buffer combinations testing
that putting something in gives something out */
printf( "= Sine wave in, something out =\n" );
printf( "\n" );
GenerateOneCycleSine( paFloat32, referenceBuffer, MAX_PER_CHANNEL_FRAME_COUNT, 1 );
for( flagCombinationIndex = 0; flagCombinationIndex < FLAG_COMBINATION_COUNT; ++flagCombinationIndex ){
flags = flagCombinations[flagCombinationIndex];
printf( "\n" );
printf( "== flags = %s ==\n", flagCombinationNames[flagCombinationIndex] );
for( sourceFormatIndex = 0; sourceFormatIndex < SAMPLE_FORMAT_COUNT; ++sourceFormatIndex ){
for( destinationFormatIndex = 0; destinationFormatIndex < SAMPLE_FORMAT_COUNT; ++destinationFormatIndex ){
sourceFormat = sampleFormats_[sourceFormatIndex];
destinationFormat = sampleFormats_[destinationFormatIndex];
//printf( "%s -> %s ", sampleFormatNames_[ sourceFormatIndex ], sampleFormatNames_[ destinationFormatIndex ] );
converter = PaUtil_SelectConverter( sourceFormat, destinationFormat, flags );
/* source is a sinewave */
GenerateOneCycleSine( sourceFormat, sourceBuffer, MAX_PER_CHANNEL_FRAME_COUNT, 1 );
/* zero destination */
memset( destinationBuffer, 0, MAX_PER_CHANNEL_FRAME_COUNT * My_Pa_GetSampleSize( destinationFormat ) );
(*converter)( destinationBuffer, 1, sourceBuffer, 1, MAX_PER_CHANNEL_FRAME_COUNT, &ditherState );
/*
Other ways we could test this would be:
- pass a constant, check for a constant (wouldn't work with dither)
- pass alternating +/-, check for the same...
*/
if( TestNonZeroPresent( destinationBuffer, MAX_PER_CHANNEL_FRAME_COUNT * My_Pa_GetSampleSize( destinationFormat ) ) ){
//printf( "PASSED\n" );
passFailMatrix[sourceFormatIndex][destinationFormatIndex] = 1;
}else{
//printf( "FAILED\n" );
passFailMatrix[sourceFormatIndex][destinationFormatIndex] = 0;
}
/* try to measure the noise floor (comparing output signal to a float32 sine wave) */
if( passFailMatrix[sourceFormatIndex][destinationFormatIndex] ){
/* convert destination back to paFloat32 into source */
converter = PaUtil_SelectConverter( destinationFormat, paFloat32, paNoFlag );
memset( sourceBuffer, 0, MAX_PER_CHANNEL_FRAME_COUNT * My_Pa_GetSampleSize( paFloat32 ) );
(*converter)( sourceBuffer, 1, destinationBuffer, 1, MAX_PER_CHANNEL_FRAME_COUNT, &ditherState );
if( TestNonZeroPresent( sourceBuffer, MAX_PER_CHANNEL_FRAME_COUNT * My_Pa_GetSampleSize( paFloat32 ) ) ){
noiseAmplitudeMatrix[sourceFormatIndex][destinationFormatIndex] = MaximumAbsDifference( (float*)sourceBuffer, (float*)referenceBuffer, MAX_PER_CHANNEL_FRAME_COUNT );
}else{
/* can't test noise floor because there is no conversion from dest format to float available */
noiseAmplitudeMatrix[sourceFormatIndex][destinationFormatIndex] = -1; // mark as failed
}
}else{
noiseAmplitudeMatrix[sourceFormatIndex][destinationFormatIndex] = -1; // mark as failed
}
}
}
printf( "\n" );
printf( "=== Output contains non-zero data ===\n" );
printf( "Key: . - pass, X - fail\n" );
printf( "{{{\n" ); // trac preformated text tag
printf( "in| out: " );
for( destinationFormatIndex = 0; destinationFormatIndex < SAMPLE_FORMAT_COUNT; ++destinationFormatIndex ){
printf( " %s ", abbreviatedSampleFormatNames_[destinationFormatIndex] );
}
printf( "\n" );
for( sourceFormatIndex = 0; sourceFormatIndex < SAMPLE_FORMAT_COUNT; ++sourceFormatIndex ){
printf( "%s ", abbreviatedSampleFormatNames_[sourceFormatIndex] );
for( destinationFormatIndex = 0; destinationFormatIndex < SAMPLE_FORMAT_COUNT; ++destinationFormatIndex ){
printf( " %s ", (passFailMatrix[sourceFormatIndex][destinationFormatIndex])? " ." : " X" );
}
printf( "\n" );
}
printf( "}}}\n" ); // trac preformated text tag
printf( "\n" );
printf( "=== Combined dynamic range (src->dest->float32) ===\n" );
printf( "Key: Noise amplitude in dBfs, X - fail (either above failed or dest->float32 failed)\n" );
printf( "{{{\n" ); // trac preformated text tag
printf( "in| out: " );
for( destinationFormatIndex = 0; destinationFormatIndex < SAMPLE_FORMAT_COUNT; ++destinationFormatIndex ){
printf( " %s ", abbreviatedSampleFormatNames_[destinationFormatIndex] );
}
printf( "\n" );
for( sourceFormatIndex = 0; sourceFormatIndex < SAMPLE_FORMAT_COUNT; ++sourceFormatIndex ){
printf( " %s ", abbreviatedSampleFormatNames_[sourceFormatIndex] );
for( destinationFormatIndex = 0; destinationFormatIndex < SAMPLE_FORMAT_COUNT; ++destinationFormatIndex ){
amp = noiseAmplitudeMatrix[sourceFormatIndex][destinationFormatIndex];
if( amp < 0. )
printf( " X " );
else
printf( " % 6.1f ", 20.*log10(amp) );
}
printf( "\n" );
}
printf( "}}}\n" ); // trac preformated text tag
}
free( destinationBuffer );
free( sourceBuffer );
free( referenceBuffer );
}
// copied here for now otherwise we need to include the world just for this function.
PaError My_Pa_GetSampleSize( PaSampleFormat format )
{
int result;
switch( format & ~paNonInterleaved )
{
case paUInt8:
case paInt8:
result = 1;
break;
case paInt16:
result = 2;
break;
case paInt24:
result = 3;
break;
case paFloat32:
case paInt32:
result = 4;
break;
default:
result = paSampleFormatNotSupported;
break;
}
return (PaError) result;
}

View File

@@ -0,0 +1,190 @@
/** @file patest_dither.c
@ingroup test_src
@brief Attempt to hear difference between dithered and non-dithered signal.
This only has an effect if the native format is 16 bit.
@author Phil Burk http://www.softsynth.com
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define NUM_SECONDS (5)
#define SAMPLE_RATE (44100)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
typedef struct paTestData
{
float sine[TABLE_SIZE];
float amplitude;
int left_phase;
int right_phase;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int sineCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo *timeInfo,
PaStreamCallbackFlags statusFlags, void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
float amplitude = data->amplitude;
unsigned int i;
(void) inputBuffer;
for( i=0; i<framesPerBuffer; i++ )
{
*out++ = amplitude * data->sine[data->left_phase]; /* left */
*out++ = amplitude * data->sine[data->right_phase]; /* right */
data->left_phase += 1;
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
}
return 0;
}
/*****************************************************************************/
/*
V18 version did not call Pa_Terminate() if Pa_Initialize() failed.
This V19 version ALWAYS calls Pa_Terminate(). PS.
*/
PaError PlaySine( paTestData *data, PaStreamFlags flags, float amplitude );
PaError PlaySine( paTestData *data, PaStreamFlags flags, float amplitude )
{
PaStream* stream;
PaStreamParameters outputParameters;
PaError err;
data->left_phase = data->right_phase = 0;
data->amplitude = amplitude;
err = Pa_Initialize();
if (err != paNoError)
goto done;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto done;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.hostApiSpecificStreamInfo = NULL;
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output. */
/* When you change this, also */
/* adapt the callback routine! */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )
->defaultLowOutputLatency; /* Low latency. */
err = Pa_OpenStream( &stream,
NULL, /* No input. */
&outputParameters,
SAMPLE_RATE,
1024, /* frames per buffer */
flags,
sineCallback,
(void*)data );
if (err != paNoError)
goto done;
err = Pa_StartStream( stream );
if (err != paNoError)
goto done;
Pa_Sleep( NUM_SECONDS * 1000 );
printf("CPULoad = %8.6f\n", Pa_GetStreamCpuLoad(stream));
err = Pa_CloseStream( stream );
done:
Pa_Sleep( 250 ); /* Just a small silence. */
Pa_Terminate();
return err;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaError err;
paTestData DATA;
int i;
float amplitude = 4.0 / (1<<15);
printf("PortAudio Test: output EXTREMELY QUIET sine wave with and without dithering.\n");
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
DATA.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
printf("\nNo treatment..\n"); fflush(stdout);
err = PlaySine( &DATA, paClipOff | paDitherOff, amplitude );
if( err < 0 ) goto done;
printf("\nClip..\n");
fflush(stdout);
err = PlaySine( &DATA, paDitherOff, amplitude );
if( err < 0 ) goto done;
printf("\nClip and Dither..\n");
fflush(stdout);
err = PlaySine( &DATA, paNoFlag, amplitude );
done:
if (err)
{
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
err = 1; /* Though PlaySine() already called Pa_Terminate(), */
} /* we may still call Pa_GetErrorText(). */
else
printf("\n(Don't forget to turn the VOLUME DOWN after listening so carefully.)\n");
return err; /* 0 or 1. */
}

View File

@@ -0,0 +1,513 @@
/*
* $Id: $
* Portable Audio I/O Library
* Windows DirectSound low level buffer user guided parameters search
*
* Copyright (c) 2010-2011 Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <time.h>
#include <math.h>
#define _WIN32_WINNT 0x0501 /* for GetNativeSystemInfo */
#include <windows.h>
//#include <mmsystem.h> /* required when using pa_win_wmme.h */
#include <conio.h> /* for _getch */
#include "portaudio.h"
#include "pa_win_ds.h"
#define DEFAULT_SAMPLE_RATE (44100.)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (2048)
#define CHANNEL_COUNT (2)
/*******************************************************************/
/* functions to query and print Windows version information */
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
LPFN_ISWOW64PROCESS fnIsWow64Process;
static BOOL IsWow64()
{
BOOL bIsWow64 = FALSE;
//IsWow64Process is not available on all supported versions of Windows.
//Use GetModuleHandle to get a handle to the DLL that contains the function
//and GetProcAddress to get a pointer to the function if available.
fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
GetModuleHandle(TEXT("kernel32")),"IsWow64Process" );
if(NULL != fnIsWow64Process)
{
if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
{
//handle error
}
}
return bIsWow64;
}
static void printWindowsVersionInfo( FILE *fp )
{
OSVERSIONINFOEX osVersionInfoEx;
SYSTEM_INFO systemInfo;
const char *osName = "Unknown";
const char *osProductType = "";
const char *processorArchitecture = "Unknown";
memset( &osVersionInfoEx, 0, sizeof(OSVERSIONINFOEX) );
osVersionInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx( &osVersionInfoEx );
if( osVersionInfoEx.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ){
switch( osVersionInfoEx.dwMinorVersion ){
case 0: osName = "Windows 95"; break;
case 10: osName = "Windows 98"; break; // could also be 98SE (I've seen code discriminate based
// on osInfo.Version.Revision.ToString() == "2222A")
case 90: osName = "Windows Me"; break;
}
}else if( osVersionInfoEx.dwPlatformId == VER_PLATFORM_WIN32_NT ){
switch( osVersionInfoEx.dwMajorVersion ){
case 3: osName = "Windows NT 3.51"; break;
case 4: osName = "Windows NT 4.0"; break;
case 5: switch( osVersionInfoEx.dwMinorVersion ){
case 0: osName = "Windows 2000"; break;
case 1: osName = "Windows XP"; break;
case 2:
if( osVersionInfoEx.wSuiteMask & 0x00008000 /*VER_SUITE_WH_SERVER*/ ){
osName = "Windows Home Server";
}else{
if( osVersionInfoEx.wProductType == VER_NT_WORKSTATION ){
osName = "Windows XP Professional x64 Edition (?)";
}else{
if( GetSystemMetrics(/*SM_SERVERR2*/89) == 0 )
osName = "Windows Server 2003";
else
osName = "Windows Server 2003 R2";
}
}break;
}break;
case 6:switch( osVersionInfoEx.dwMinorVersion ){
case 0:
if( osVersionInfoEx.wProductType == VER_NT_WORKSTATION )
osName = "Windows Vista";
else
osName = "Windows Server 2008";
break;
case 1:
if( osVersionInfoEx.wProductType == VER_NT_WORKSTATION )
osName = "Windows 7";
else
osName = "Windows Server 2008 R2";
break;
}break;
}
}
if(osVersionInfoEx.dwMajorVersion == 4)
{
if(osVersionInfoEx.wProductType == VER_NT_WORKSTATION)
osProductType = "Workstation";
else if(osVersionInfoEx.wProductType == VER_NT_SERVER)
osProductType = "Server";
}
else if(osVersionInfoEx.dwMajorVersion == 5)
{
if(osVersionInfoEx.wProductType == VER_NT_WORKSTATION)
{
if((osVersionInfoEx.wSuiteMask & VER_SUITE_PERSONAL) == VER_SUITE_PERSONAL)
osProductType = "Home Edition"; // Windows XP Home Edition
else
osProductType = "Professional"; // Windows XP / Windows 2000 Professional
}
else if(osVersionInfoEx.wProductType == VER_NT_SERVER)
{
if(osVersionInfoEx.dwMinorVersion == 0)
{
if((osVersionInfoEx.wSuiteMask & VER_SUITE_DATACENTER) == VER_SUITE_DATACENTER)
osProductType = "Datacenter Server"; // Windows 2000 Datacenter Server
else if((osVersionInfoEx.wSuiteMask & VER_SUITE_ENTERPRISE) == VER_SUITE_ENTERPRISE)
osProductType = "Advanced Server"; // Windows 2000 Advanced Server
else
osProductType = "Server"; // Windows 2000 Server
}
}
else
{
if((osVersionInfoEx.wSuiteMask & VER_SUITE_DATACENTER) == VER_SUITE_DATACENTER)
osProductType = "Datacenter Edition"; // Windows Server 2003 Datacenter Edition
else if((osVersionInfoEx.wSuiteMask & VER_SUITE_ENTERPRISE) == VER_SUITE_ENTERPRISE)
osProductType = "Enterprise Edition"; // Windows Server 2003 Enterprise Edition
else if((osVersionInfoEx.wSuiteMask & VER_SUITE_BLADE) == VER_SUITE_BLADE)
osProductType = "Web Edition"; // Windows Server 2003 Web Edition
else
osProductType = "Standard Edition"; // Windows Server 2003 Standard Edition
}
}
memset( &systemInfo, 0, sizeof(SYSTEM_INFO) );
GetNativeSystemInfo( &systemInfo );
if( systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL )
processorArchitecture = "x86";
else if( systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 )
processorArchitecture = "x64";
else if( systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 )
processorArchitecture = "Itanium";
fprintf( fp, "OS name and edition: %s %s\n", osName, osProductType );
fprintf( fp, "OS version: %d.%d.%d %S\n",
osVersionInfoEx.dwMajorVersion, osVersionInfoEx.dwMinorVersion,
osVersionInfoEx.dwBuildNumber, osVersionInfoEx.szCSDVersion );
fprintf( fp, "Processor architecture: %s\n", processorArchitecture );
fprintf( fp, "WoW64 process: %s\n", IsWow64() ? "Yes" : "No" );
}
static void printTimeAndDate( FILE *fp )
{
struct tm *local;
time_t t;
t = time(NULL);
local = localtime(&t);
fprintf(fp, "Local time and date: %s", asctime(local));
local = gmtime(&t);
fprintf(fp, "UTC time and date: %s", asctime(local));
}
/*******************************************************************/
typedef struct
{
float sine[TABLE_SIZE];
double phase;
double phaseIncrement;
volatile int fadeIn;
volatile int fadeOut;
double amp;
}
paTestData;
static paTestData data;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i,j;
(void) timeInfo; /* Prevent unused variable warnings. */
(void) statusFlags;
(void) inputBuffer;
for( i=0; i<framesPerBuffer; i++ )
{
float x = data->sine[(int)data->phase];
data->phase += data->phaseIncrement;
if( data->phase >= TABLE_SIZE ){
data->phase -= TABLE_SIZE;
}
x *= data->amp;
if( data->fadeIn ){
data->amp += .001;
if( data->amp >= 1. )
data->fadeIn = 0;
}else if( data->fadeOut ){
if( data->amp > 0 )
data->amp -= .001;
}
for( j = 0; j < CHANNEL_COUNT; ++j ){
*out++ = x;
}
}
if( data->amp > 0 )
return paContinue;
else
return paComplete;
}
#define YES 1
#define NO 0
static int playUntilKeyPress( int deviceIndex, float sampleRate,
int framesPerUserBuffer, int framesPerDSoundBuffer )
{
PaStreamParameters outputParameters;
PaWinDirectSoundStreamInfo directSoundStreamInfo;
PaStream *stream;
PaError err;
int c;
outputParameters.device = deviceIndex;
outputParameters.channelCount = CHANNEL_COUNT;
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point processing */
outputParameters.suggestedLatency = 0; /*Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;*/
outputParameters.hostApiSpecificStreamInfo = NULL;
directSoundStreamInfo.size = sizeof(PaWinDirectSoundStreamInfo);
directSoundStreamInfo.hostApiType = paDirectSound;
directSoundStreamInfo.version = 2;
directSoundStreamInfo.flags = paWinDirectSoundUseLowLevelLatencyParameters;
directSoundStreamInfo.framesPerBuffer = framesPerDSoundBuffer;
outputParameters.hostApiSpecificStreamInfo = &directSoundStreamInfo;
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
sampleRate,
framesPerUserBuffer,
paClipOff | paPrimeOutputBuffersUsingStreamCallback, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
data.amp = 0;
data.fadeIn = 1;
data.fadeOut = 0;
data.phase = 0;
data.phaseIncrement = 15 + ((rand()%100) / 10); // randomise pitch
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
do{
printf( "Trying buffer size %d.\nIf it sounds smooth (without clicks or glitches) press 'y', if it sounds bad press 'n' ('q' to quit)\n", framesPerDSoundBuffer );
c = tolower(_getch());
if( c == 'q' ){
Pa_Terminate();
exit(0);
}
}while( c != 'y' && c != 'n' );
data.fadeOut = 1;
while( Pa_IsStreamActive(stream) == 1 )
Pa_Sleep( 100 );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
return (c == 'y') ? YES : NO;
error:
return err;
}
/*******************************************************************/
static void usage( int dsoundHostApiIndex )
{
int i;
fprintf( stderr, "PortAudio DirectSound output latency user guided test\n" );
fprintf( stderr, "Usage: x.exe dsound-device-index [sampleRate]\n" );
fprintf( stderr, "Invalid device index. Use one of these:\n" );
for( i=0; i < Pa_GetDeviceCount(); ++i ){
if( Pa_GetDeviceInfo(i)->hostApi == dsoundHostApiIndex && Pa_GetDeviceInfo(i)->maxOutputChannels > 0 )
fprintf( stderr, "%d (%s)\n", i, Pa_GetDeviceInfo(i)->name );
}
Pa_Terminate();
exit(-1);
}
/*
ideas:
o- could be testing with 80% CPU load
o- could test with different channel counts
*/
int main(int argc, char* argv[])
{
PaError err;
int i;
int deviceIndex;
int dsoundBufferSize, smallestWorkingBufferSize;
int smallestWorkingBufferingLatencyFrames;
int min, max, mid;
int testResult;
FILE *resultsFp;
int dsoundHostApiIndex;
const PaHostApiInfo *dsoundHostApiInfo;
double sampleRate = DEFAULT_SAMPLE_RATE;
err = Pa_Initialize();
if( err != paNoError ) goto error;
dsoundHostApiIndex = Pa_HostApiTypeIdToHostApiIndex( paDirectSound );
dsoundHostApiInfo = Pa_GetHostApiInfo( dsoundHostApiIndex );
if( argc > 3 )
usage(dsoundHostApiIndex);
deviceIndex = dsoundHostApiInfo->defaultOutputDevice;
if( argc >= 2 ){
deviceIndex = -1;
if( sscanf( argv[1], "%d", &deviceIndex ) != 1 )
usage(dsoundHostApiInfo);
if( deviceIndex < 0 || deviceIndex >= Pa_GetDeviceCount() || Pa_GetDeviceInfo(deviceIndex)->hostApi != dsoundHostApiIndex ){
usage(dsoundHostApiInfo);
}
}
printf( "Using device id %d (%s)\n", deviceIndex, Pa_GetDeviceInfo(deviceIndex)->name );
if( argc >= 3 ){
if( sscanf( argv[2], "%lf", &sampleRate ) != 1 )
usage(dsoundHostApiIndex);
}
printf( "Testing with sample rate %f.\n", (float)sampleRate );
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data.phase = 0;
resultsFp = fopen( "results.txt", "at" );
fprintf( resultsFp, "*** DirectSound smallest working output buffer sizes\n" );
printTimeAndDate( resultsFp );
printWindowsVersionInfo( resultsFp );
fprintf( resultsFp, "audio device: %s\n", Pa_GetDeviceInfo( deviceIndex )->name );
fflush( resultsFp );
fprintf( resultsFp, "Sample rate: %f\n", (float)sampleRate );
fprintf( resultsFp, "Smallest working buffer size (frames), Smallest working buffering latency (frames), Smallest working buffering latency (Seconds)\n" );
/*
Binary search after Niklaus Wirth
from http://en.wikipedia.org/wiki/Binary_search_algorithm#The_algorithm
*/
min = 1;
max = (int)(sampleRate * .3); /* we assume that this size works 300ms */
smallestWorkingBufferSize = 0;
do{
mid = min + ((max - min) / 2);
dsoundBufferSize = mid;
testResult = playUntilKeyPress( deviceIndex, sampleRate, 0, dsoundBufferSize );
if( testResult == YES ){
max = mid - 1;
smallestWorkingBufferSize = dsoundBufferSize;
}else{
min = mid + 1;
}
}while( (min <= max) && (testResult == YES || testResult == NO) );
smallestWorkingBufferingLatencyFrames = smallestWorkingBufferSize; /* not strictly true, but we're using an unspecified callback size, so kind of */
printf( "Smallest working buffer size is: %d\n", smallestWorkingBufferSize );
printf( "Corresponding to buffering latency of %d frames, or %f seconds.\n", smallestWorkingBufferingLatencyFrames, smallestWorkingBufferingLatencyFrames / sampleRate );
fprintf( resultsFp, "%d, %d, %f\n", smallestWorkingBufferSize, smallestWorkingBufferingLatencyFrames, smallestWorkingBufferingLatencyFrames / sampleRate );
fflush( resultsFp );
/* power of 2 test. iterate to the smallest power of two that works */
smallestWorkingBufferSize = 0;
dsoundBufferSize = 64;
do{
testResult = playUntilKeyPress( deviceIndex, sampleRate, 0, dsoundBufferSize );
if( testResult == YES ){
smallestWorkingBufferSize = dsoundBufferSize;
}else{
dsoundBufferSize *= 2;
}
}while( (dsoundBufferSize <= (int)(sampleRate * .3)) && testResult == NO );
smallestWorkingBufferingLatencyFrames = smallestWorkingBufferSize; /* not strictly true, but we're using an unspecified callback size, so kind of */
fprintf( resultsFp, "%d, %d, %f\n", smallestWorkingBufferSize, smallestWorkingBufferingLatencyFrames, smallestWorkingBufferingLatencyFrames / sampleRate );
fflush( resultsFp );
fprintf( resultsFp, "###\n" );
fclose( resultsFp );
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the PortAudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,186 @@
/*
* $Id: $
* Portable Audio I/O Library
* Windows DirectSound low level buffer parameters test
*
* Copyright (c) 2011 Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#include "pa_win_ds.h"
#define NUM_SECONDS (6)
#define SAMPLE_RATE (44100)
#define DSOUND_FRAMES_PER_HOST_BUFFER (256*2) //(440*10)
#define FRAMES_PER_BUFFER 256
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (2048)
#define CHANNEL_COUNT (2)
typedef struct
{
float sine[TABLE_SIZE];
double phase;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i,j;
(void) timeInfo; /* Prevent unused variable warnings. */
(void) statusFlags;
(void) inputBuffer;
for( i=0; i<framesPerBuffer; i++ )
{
float x = data->sine[(int)data->phase];
data->phase += 20;
if( data->phase >= TABLE_SIZE ){
data->phase -= TABLE_SIZE;
}
for( j = 0; j < CHANNEL_COUNT; ++j ){
*out++ = x;
}
}
return paContinue;
}
/*******************************************************************/
int main(int argc, char* argv[])
{
PaStreamParameters outputParameters;
PaWinDirectSoundStreamInfo dsoundStreamInfo;
PaStream *stream;
PaError err;
paTestData data;
int i;
int deviceIndex;
printf("PortAudio Test: output a sine blip on each channel. SR = %d, BufSize = %d, Chans = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER, CHANNEL_COUNT);
err = Pa_Initialize();
if( err != paNoError ) goto error;
deviceIndex = Pa_GetHostApiInfo( Pa_HostApiTypeIdToHostApiIndex( paDirectSound ) )->defaultOutputDevice;
if( argc == 2 ){
sscanf( argv[1], "%d", &deviceIndex );
}
printf( "using device id %d (%s)\n", deviceIndex, Pa_GetDeviceInfo(deviceIndex)->name );
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data.phase = 0;
outputParameters.device = deviceIndex;
outputParameters.channelCount = CHANNEL_COUNT;
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point processing */
outputParameters.suggestedLatency = 0; /*Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;*/
outputParameters.hostApiSpecificStreamInfo = NULL;
dsoundStreamInfo.size = sizeof(PaWinDirectSoundStreamInfo);
dsoundStreamInfo.hostApiType = paDirectSound;
dsoundStreamInfo.version = 2;
dsoundStreamInfo.flags = paWinDirectSoundUseLowLevelLatencyParameters;
dsoundStreamInfo.framesPerBuffer = DSOUND_FRAMES_PER_HOST_BUFFER;
outputParameters.hostApiSpecificStreamInfo = &dsoundStreamInfo;
if( Pa_IsFormatSupported( 0, &outputParameters, SAMPLE_RATE ) == paFormatIsSupported ){
printf( "Pa_IsFormatSupported reports device will support %d channels.\n", CHANNEL_COUNT );
}else{
printf( "Pa_IsFormatSupported reports device will not support %d channels.\n", CHANNEL_COUNT );
}
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Play for %d seconds.\n", NUM_SECONDS );
Pa_Sleep( NUM_SECONDS * 1000 );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,204 @@
/*
* $Id: $
* Portable Audio I/O Library
* Windows DirectSound surround sound output test
*
* Copyright (c) 2007 Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include <windows.h> /* required when using pa_win_wmme.h */
#include <mmsystem.h> /* required when using pa_win_wmme.h */
#include "portaudio.h"
#include "pa_win_ds.h"
#define NUM_SECONDS (12)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (64)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (100)
#define CHANNEL_COUNT (6)
typedef struct
{
float sine[TABLE_SIZE];
int phase;
int currentChannel;
int cycleCount;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i,j;
(void) timeInfo; /* Prevent unused variable warnings. */
(void) statusFlags;
(void) inputBuffer;
for( i=0; i<framesPerBuffer; i++ )
{
for( j = 0; j < CHANNEL_COUNT; ++j ){
if( j == data->currentChannel && data->cycleCount < 4410 ){
*out++ = data->sine[data->phase];
data->phase += 1 + j; // play each channel at a different pitch so they can be distinguished
if( data->phase >= TABLE_SIZE ){
data->phase -= TABLE_SIZE;
}
}else{
*out++ = 0;
}
}
data->cycleCount++;
if( data->cycleCount > 44100 ){
data->cycleCount = 0;
++data->currentChannel;
if( data->currentChannel >= CHANNEL_COUNT )
data->currentChannel -= CHANNEL_COUNT;
}
}
return paContinue;
}
/*******************************************************************/
int main(int argc, char* argv[])
{
PaStreamParameters outputParameters;
PaWinDirectSoundStreamInfo directSoundStreamInfo;
PaStream *stream;
PaError err;
paTestData data;
int i;
int deviceIndex;
printf("PortAudio Test: output a sine blip on each channel. SR = %d, BufSize = %d, Chans = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER, CHANNEL_COUNT);
err = Pa_Initialize();
if( err != paNoError ) goto error;
deviceIndex = Pa_GetHostApiInfo( Pa_HostApiTypeIdToHostApiIndex( paDirectSound ) )->defaultOutputDevice;
if( argc == 2 ){
sscanf( argv[1], "%d", &deviceIndex );
}
printf( "using device id %d (%s)\n", deviceIndex, Pa_GetDeviceInfo(deviceIndex)->name );
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data.phase = 0;
data.currentChannel = 0;
data.cycleCount = 0;
outputParameters.device = deviceIndex;
outputParameters.channelCount = CHANNEL_COUNT;
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point processing */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
/* it's not strictly necessary to provide a channelMask for surround sound
output. But if you want to be sure which channel mask PortAudio will use
then you should supply one */
directSoundStreamInfo.size = sizeof(PaWinDirectSoundStreamInfo);
directSoundStreamInfo.hostApiType = paDirectSound;
directSoundStreamInfo.version = 1;
directSoundStreamInfo.flags = paWinDirectSoundUseChannelMask;
directSoundStreamInfo.channelMask = PAWIN_SPEAKER_5POINT1; /* request 5.1 output format */
outputParameters.hostApiSpecificStreamInfo = &directSoundStreamInfo;
if( Pa_IsFormatSupported( 0, &outputParameters, SAMPLE_RATE ) == paFormatIsSupported ){
printf( "Pa_IsFormatSupported reports device will support %d channels.\n", CHANNEL_COUNT );
}else{
printf( "Pa_IsFormatSupported reports device will not support %d channels.\n", CHANNEL_COUNT );
}
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Play for %d seconds.\n", NUM_SECONDS );
Pa_Sleep( NUM_SECONDS * 1000 );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

164
third_party/portaudio/test/patest_hang.c vendored Normal file
View File

@@ -0,0 +1,164 @@
/** @file patest_hang.c
@ingroup test_src
@brief Play a sine then hang audio callback to test watchdog.
@author Ross Bencina <rossb@audiomulch.com>
@author Phil Burk <philburk@softsynth.com>
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (1024)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TWOPI (M_PI * 2.0)
typedef struct paTestData
{
int sleepFor;
double phase;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i;
int finished = 0;
double phaseInc = 0.02;
double phase = data->phase;
(void) inputBuffer; /* Prevent unused argument warning. */
for( i=0; i<framesPerBuffer; i++ )
{
phase += phaseInc;
if( phase > TWOPI ) phase -= TWOPI;
/* This is not a very efficient way to calc sines. */
*out++ = (float) sin( phase ); /* mono */
}
if( data->sleepFor > 0 )
{
Pa_Sleep( data->sleepFor );
}
data->phase = phase;
return finished;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStream* stream;
PaStreamParameters outputParameters;
PaError err;
int i;
paTestData data = {0};
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n",
SAMPLE_RATE, FRAMES_PER_BUFFER );
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* Default output device. */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 1; /* Mono output. */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point. */
outputParameters.hostApiSpecificStreamInfo = NULL;
outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)
->defaultLowOutputLatency;
err = Pa_OpenStream(&stream,
NULL, /* No input. */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* No out of range samples. */
patestCallback,
&data);
if (err != paNoError) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
/* Gradually increase sleep time. */
/* Was: for( i=0; i<10000; i+= 1000 ) */
for(i=0; i <= 1000; i += 100)
{
printf("Sleep for %d milliseconds in audio callback.\n", i );
data.sleepFor = i;
Pa_Sleep( ((i<1000) ? 1000 : i) );
}
printf("Suffer for 10 seconds.\n");
Pa_Sleep( 10000 );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,236 @@
/** @file patest_in_overflow.c
@ingroup test_src
@brief Count input overflows (using paInputOverflow flag) under
overloaded and normal conditions.
This test uses the same method to overload the stream as does
patest_out_underflow.c -- it generates sine waves until the cpu load
exceeds a certain level. However this test is only concerned with
input and so doesn't output any sound.
@author Ross Bencina <rossb@audiomulch.com>
@author Phil Burk <philburk@softsynth.com>
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2004 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define MAX_SINES (500)
#define MAX_LOAD (1.2)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (512)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TWOPI (M_PI * 2.0)
typedef struct paTestData
{
int sineCount;
double phases[MAX_SINES];
int countOverflows;
int inputOverflowCount;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float out; /* variable to hold dummy output */
unsigned long i;
int j;
int finished = paContinue;
(void) timeInfo; /* Prevent unused variable warning. */
(void) inputBuffer; /* Prevent unused variable warning. */
(void) outputBuffer; /* Prevent unused variable warning. */
if( data->countOverflows && (statusFlags & paInputOverflow) )
data->inputOverflowCount++;
for( i=0; i<framesPerBuffer; i++ )
{
float output = 0.0;
double phaseInc = 0.02;
double phase;
for( j=0; j<data->sineCount; j++ )
{
/* Advance phase of next oscillator. */
phase = data->phases[j];
phase += phaseInc;
if( phase > TWOPI ) phase -= TWOPI;
phaseInc *= 1.02;
if( phaseInc > 0.5 ) phaseInc *= 0.5;
/* This is not a very efficient way to calc sines. */
output += (float) sin( phase );
data->phases[j] = phase;
}
/* this is an input-only stream so we don't actually use the output */
out = (float) (output / data->sineCount);
(void) out; /* suppress unused variable warning*/
}
return finished;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters inputParameters;
PaStream *stream;
PaError err;
int safeSineCount, stressedSineCount;
int safeOverflowCount, stressedOverflowCount;
paTestData data = {0};
double load;
printf("PortAudio Test: input only, no sound output. Load callback by performing calculations, count input overflows. SR = %d, BufSize = %d. MAX_LOAD = %f\n",
SAMPLE_RATE, FRAMES_PER_BUFFER, (float)MAX_LOAD );
err = Pa_Initialize();
if( err != paNoError ) goto error;
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device.\n");
goto error;
}
inputParameters.channelCount = 1; /* mono output */
inputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&stream,
&inputParameters,
NULL, /* no output */
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Establishing load conditions...\n" );
/* Determine number of sines required to get to 50% */
do
{
data.sineCount++;
Pa_Sleep( 100 );
load = Pa_GetStreamCpuLoad( stream );
printf("sineCount = %d, CPU load = %f\n", data.sineCount, load );
}
while( load < 0.5 && data.sineCount < (MAX_SINES-1));
safeSineCount = data.sineCount;
/* Calculate target stress value then ramp up to that level*/
stressedSineCount = (int) (2.0 * data.sineCount * MAX_LOAD );
if( stressedSineCount > MAX_SINES )
stressedSineCount = MAX_SINES;
for( ; data.sineCount < stressedSineCount; data.sineCount++ )
{
Pa_Sleep( 100 );
load = Pa_GetStreamCpuLoad( stream );
printf("STRESSING: sineCount = %d, CPU load = %f\n", data.sineCount, load );
}
printf("Counting overflows for 5 seconds.\n");
data.countOverflows = 1;
Pa_Sleep( 5000 );
stressedOverflowCount = data.inputOverflowCount;
data.countOverflows = 0;
data.sineCount = safeSineCount;
printf("Resuming safe load...\n");
Pa_Sleep( 1500 );
data.inputOverflowCount = 0;
Pa_Sleep( 1500 );
load = Pa_GetStreamCpuLoad( stream );
printf("sineCount = %d, CPU load = %f\n", data.sineCount, load );
printf("Counting overflows for 5 seconds.\n");
data.countOverflows = 1;
Pa_Sleep( 5000 );
safeOverflowCount = data.inputOverflowCount;
printf("Stop stream.\n");
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
if( stressedOverflowCount == 0 )
printf("Test failed, no input overflows detected under stress.\n");
else if( safeOverflowCount != 0 )
printf("Test failed, %d unexpected overflows detected under safe load.\n", safeOverflowCount);
else
printf("Test passed, %d expected input overflows detected under stress, 0 unexpected overflows detected under safe load.\n", stressedOverflowCount );
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,343 @@
/** @file pa_test_jack_wasapi.c
@ingroup test_src
@brief Print out jack information for WASAPI endpoints
@author Reid Bishop <rbish@attglobal.net>
*/
/*
* $Id: pa_test_jack_wasapi.c 1368 2008-03-01 00:38:27Z rbishop $
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com/
* Copyright (c) 1999-2010 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include "portaudio.h"
#include "pa_win_wasapi.h"
/*
* Helper function to determine if a given enum is present in mask variable
*
*/
static int IsInMask(int val, int val2)
{
return ((val & val2) == val2);
}
/*
* This routine enumerates through the ChannelMapping for the IJackDescription
*/
static void EnumIJackChannels(int channelMapping)
{
printf("Channel Mapping: ");
if(channelMapping == PAWIN_SPEAKER_DIRECTOUT)
{
printf("DIRECTOUT\n");
return;
}
if(IsInMask(channelMapping, PAWIN_SPEAKER_FRONT_LEFT))
printf("FRONT_LEFT, ");
if(IsInMask(channelMapping, PAWIN_SPEAKER_FRONT_RIGHT))
printf("FRONT_RIGHT, ");
if(IsInMask(channelMapping, PAWIN_SPEAKER_FRONT_CENTER))
printf("FRONT_CENTER, ");
if(IsInMask(channelMapping, PAWIN_SPEAKER_LOW_FREQUENCY))
printf("LOW_FREQUENCY, ");
if(IsInMask(channelMapping, PAWIN_SPEAKER_BACK_LEFT))
printf("BACK_LEFT, ");
if(IsInMask(channelMapping,PAWIN_SPEAKER_BACK_RIGHT))
printf("BACK_RIGHT, ");
if(IsInMask(channelMapping, PAWIN_SPEAKER_FRONT_LEFT_OF_CENTER))
printf("FRONT_LEFT_OF_CENTER, ");
if(IsInMask(channelMapping, PAWIN_SPEAKER_FRONT_RIGHT_OF_CENTER))
printf("FRONT_RIGHT_OF_CENTER, ");
if(IsInMask(channelMapping, PAWIN_SPEAKER_BACK_CENTER))
printf("BACK_CENTER, ");
if(IsInMask(channelMapping,PAWIN_SPEAKER_SIDE_LEFT))
printf("SIDE_LEFT, ");
if(IsInMask(channelMapping,PAWIN_SPEAKER_SIDE_RIGHT))
printf("SIDE_RIGHT, ");
if(IsInMask(channelMapping, PAWIN_SPEAKER_TOP_CENTER))
printf("TOP_CENTER, ");
if(IsInMask(channelMapping, PAWIN_SPEAKER_TOP_FRONT_LEFT))
printf("TOP_FRONT_LEFT, ");
if(IsInMask(channelMapping, PAWIN_SPEAKER_TOP_FRONT_CENTER))
printf("TOP_FRONT_CENTER, ");
if(IsInMask(channelMapping, PAWIN_SPEAKER_TOP_FRONT_RIGHT))
printf("TOP_FRONT_RIGHT, ");
if(IsInMask(channelMapping, PAWIN_SPEAKER_TOP_BACK_LEFT))
printf("TOP_BACK_LEFT, ");
if(IsInMask(channelMapping, PAWIN_SPEAKER_TOP_BACK_CENTER))
printf("TOP_BACK_CENTER, ");
if(IsInMask(channelMapping, PAWIN_SPEAKER_TOP_BACK_RIGHT))
printf("TOP_BACK_RIGHT, ");
printf("\n");
}
/*
* This routine enumerates through the Jack Connection Types enums for IJackDescription
*/
static void EnumIJackConnectionType(int cType)
{
printf("Connection Type: ");
switch(cType)
{
case eJackConnTypeUnknown:
printf("eJackConnTypeUnknown");
break;
case eJackConnType3Point5mm:
printf("eJackConnType3Point5mm");
break;
case eJackConnTypeQuarter:
printf("eJackConnTypeQuarter");
break;
case eJackConnTypeAtapiInternal:
printf("eJackConnTypeAtapiInternal");
break;
case eJackConnTypeRCA:
printf("eJackConnTypeRCA");
break;
case eJackConnTypeOptical:
printf("eJackConnTypeOptical");
break;
case eJackConnTypeOtherDigital:
printf("eJackConnTypeOtherDigital");
break;
case eJackConnTypeOtherAnalog:
printf("eJackConnTypeOtherAnalog");
break;
case eJackConnTypeMultichannelAnalogDIN:
printf("eJackConnTypeMultichannelAnalogDIN");
break;
case eJackConnTypeXlrProfessional:
printf("eJackConnTypeXlrProfessional");
break;
case eJackConnTypeRJ11Modem:
printf("eJackConnTypeRJ11Modem");
break;
case eJackConnTypeCombination:
printf("eJackConnTypeCombination");
break;
}
printf("\n");
}
/*
* This routine enumerates through the GeoLocation enums for the IJackDescription
*/
static void EnumIJackGeoLocation(int iVal)
{
printf("Geometric Location: ");
switch(iVal)
{
case eJackGeoLocRear:
printf("eJackGeoLocRear");
break;
case eJackGeoLocFront:
printf("eJackGeoLocFront");
break;
case eJackGeoLocLeft:
printf("eJackGeoLocLeft");
break;
case eJackGeoLocRight:
printf("eJackGeoLocRight");
break;
case eJackGeoLocTop:
printf("eJackGeoLocTop");
break;
case eJackGeoLocBottom:
printf("eJackGeoLocBottom");
break;
case eJackGeoLocRearPanel:
printf("eJackGeoLocRearPanel");
break;
case eJackGeoLocRiser:
printf("eJackGeoLocRiser");
break;
case eJackGeoLocInsideMobileLid:
printf("eJackGeoLocInsideMobileLid");
break;
case eJackGeoLocDrivebay:
printf("eJackGeoLocDrivebay");
break;
case eJackGeoLocHDMI:
printf("eJackGeoLocHDMI");
break;
case eJackGeoLocOutsideMobileLid:
printf("eJackGeoLocOutsideMobileLid");
break;
case eJackGeoLocATAPI:
printf("eJackGeoLocATAPI");
break;
}
printf("\n");
}
/*
* This routine enumerates through the GenLocation enums for the IJackDescription
*/
static void EnumIJackGenLocation(int iVal)
{
printf("General Location: ");
switch(iVal)
{
case eJackGenLocPrimaryBox:
printf("eJackGenLocPrimaryBox");
break;
case eJackGenLocInternal:
printf("eJackGenLocInternal");
break;
case eJackGenLocSeparate:
printf("eJackGenLocSeparate");
break;
case eJackGenLocOther:
printf("eJackGenLocOther");
break;
}
printf("\n");
}
/*
* This routine enumerates through the PortConnection enums for the IJackDescription
*/
static void EnumIJackPortConnection(int iVal)
{
printf("Port Type: ");
switch(iVal)
{
case eJackPortConnJack:
printf("eJackPortConnJack");
break;
case eJackPortConnIntegratedDevice:
printf("eJackPortConnIntegratedDevice");
break;
case eJackPortConnBothIntegratedAndJack:
printf("eJackPortConnBothIntegratedAndJack");
break;
case eJackPortConnUnknown:
printf("eJackPortConnUnknown");
break;
}
printf("\n");
}
/*
* This routine retrieves and parses the KSJACK_DESCRIPTION structure for
* the provided device ID.
*/
static PaError GetJackInformation(int deviceId)
{
PaError err;
int i;
int jackCount = 0;
PaWasapiJackDescription jackDesc;
err = PaWasapi_GetJackCount(deviceId, &jackCount);
if( err != paNoError ) return err;
fprintf( stderr,"Number of Jacks: %d \n", jackCount );
for( i = 0; i<jackCount; i++ )
{
fprintf( stderr,"Jack #%d:\n", i );
err = PaWasapi_GetJackDescription(deviceId, i, &jackDesc);
if( err != paNoError )
{
fprintf( stderr,"Failed getting description." );
continue;
}
else
{
printf("Is connected: %s\n",(jackDesc.isConnected)?"true":"false");
EnumIJackChannels(jackDesc.channelMapping);
EnumIJackConnectionType(jackDesc.connectionType);
EnumIJackGeoLocation(jackDesc.geoLocation);
EnumIJackGenLocation(jackDesc.genLocation);
EnumIJackPortConnection(jackDesc.portConnection);
printf("Jack Color: 0x%06X\n", jackDesc.color);
printf("\n");
}
}
return 0;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaError err;
const PaDeviceInfo *device;
int i;
int jackCount = 0;
int isInput = 0;
printf("PortAudio Test: WASAPI Jack Configuration");
err = Pa_Initialize();
if( err != paNoError ) goto error;
/* Find all WASAPI devices */
for( i = 0; i < Pa_GetDeviceCount(); ++i )
{
device = Pa_GetDeviceInfo(i);
if( Pa_GetDeviceInfo(i)->hostApi == Pa_HostApiTypeIdToHostApiIndex(paWASAPI) )
{
if( device->maxOutputChannels == 0 )
{
isInput = 1;
}
printf("------------------------------------------\n");
printf("Device: %s",device->name);
if(isInput)
printf(" (Input) %d Channels\n",device->maxInputChannels);
else
printf(" (Output) %d Channels\n",device->maxOutputChannels);
// Try to see if this WASAPI device can provide Jack information
err = GetJackInformation(i);
if( err != paNoError ) goto error;
}
}
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,193 @@
/** @file
@ingroup test_src
@brief Hear the latency caused by big buffers.
Play a sine wave and change frequency based on letter input.
@author Phil Burk <philburk@softsynth.com>, and Darren Gibbs
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define OUTPUT_DEVICE (Pa_GetDefaultOutputDevice())
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (64)
#define MIN_FREQ (100.0f)
#define CalcPhaseIncrement(freq) ((freq)/SAMPLE_RATE)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (400)
typedef struct
{
float sine[TABLE_SIZE + 1]; /* add one for guard point for interpolation */
float phase_increment;
float left_phase;
float right_phase;
}
paTestData;
float LookupSine( paTestData *data, float phase );
/* Convert phase between and 1.0 to sine value
* using linear interpolation.
*/
float LookupSine( paTestData *data, float phase )
{
float fIndex = phase*TABLE_SIZE;
int index = (int) fIndex;
float fract = fIndex - index;
float lo = data->sine[index];
float hi = data->sine[index+1];
float val = lo + fract*(hi-lo);
return val;
}
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
int i;
(void) inputBuffer; /* Prevent unused variable warning. */
for( i=0; i<framesPerBuffer; i++ )
{
*out++ = LookupSine(data, data->left_phase); /* left */
*out++ = LookupSine(data, data->right_phase); /* right */
data->left_phase += data->phase_increment;
if( data->left_phase >= 1.0f ) data->left_phase -= 1.0f;
data->right_phase += (data->phase_increment * 1.5f); /* fifth above */
if( data->right_phase >= 1.0f ) data->right_phase -= 1.0f;
}
return 0;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStream *stream;
PaStreamParameters outputParameters;
PaError err;
paTestData data;
int i;
int done = 0;
printf("PortAudio Test: enter letter then hit ENTER.\n" );
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = 0.90f * (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data.sine[TABLE_SIZE] = data.sine[0]; /* set guard point. */
data.left_phase = data.right_phase = 0.0;
data.phase_increment = CalcPhaseIncrement(MIN_FREQ);
err = Pa_Initialize();
if( err != paNoError ) goto error;
printf("PortAudio Test: output device = %d\n", OUTPUT_DEVICE );
outputParameters.device = OUTPUT_DEVICE;
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
printf("Requested output latency = %.4f seconds.\n", outputParameters.suggestedLatency );
printf("%d frames per buffer.\n.", FRAMES_PER_BUFFER );
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff|paDitherOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Play ASCII keyboard. Hit 'q' to stop. (Use RETURN key on Mac)\n");
fflush(stdout);
while ( !done )
{
float freq;
int index;
char c;
do
{
c = getchar();
}
while( c < ' '); /* Strip white space and control chars. */
if( c == 'q' ) done = 1;
index = c % 26;
freq = MIN_FREQ + (index * 40.0);
data.phase_increment = CalcPhaseIncrement(freq);
}
printf("Call Pa_StopStream()\n");
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,185 @@
/** @file patest_leftright.c
@ingroup test_src
@brief Play different tone sine waves that
alternate between left and right channel.
The low tone should be on the left channel.
@author Ross Bencina <rossb@audiomulch.com>
@author Phil Burk <philburk@softsynth.com>
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define NUM_SECONDS (8)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (512)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
#define BALANCE_DELTA (0.001)
typedef struct
{
float sine[TABLE_SIZE];
int left_phase;
int right_phase;
float targetBalance; // 0.0 = left, 1.0 = right
float currentBalance;
} paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer,
void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i;
int finished = 0;
/* Prevent unused variable warnings. */
(void) inputBuffer;
for( i=0; i<framesPerBuffer; i++ )
{
// Smoothly pan between left and right.
if( data->currentBalance < data->targetBalance )
{
data->currentBalance += BALANCE_DELTA;
}
else if( data->currentBalance > data->targetBalance )
{
data->currentBalance -= BALANCE_DELTA;
}
// Apply left/right balance.
*out++ = data->sine[data->left_phase] * (1.0f - data->currentBalance); /* left */
*out++ = data->sine[data->right_phase] * data->currentBalance; /* right */
data->left_phase += 1;
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
}
return finished;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStream *stream;
PaStreamParameters outputParameters;
PaError err;
paTestData data;
int i;
printf("Play different tone sine waves that alternate between left and right channel.\n");
printf("The low tone should be on the left channel.\n");
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data.left_phase = data.right_phase = 0;
data.currentBalance = 0.0;
data.targetBalance = 0.0;
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream( &stream,
NULL, /* No input. */
&outputParameters, /* As above. */
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Play for several seconds.\n");
for( i=0; i<4; i++ )
{
printf("Hear low sound on left side.\n");
data.targetBalance = 0.01;
Pa_Sleep( 1000 );
printf("Hear high sound on right side.\n");
data.targetBalance = 0.99;
Pa_Sleep( 1000 );
}
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,151 @@
/** @file patest_longsine.c
@ingroup test_src
@brief Play a sine wave until ENTER hit.
@author Phil Burk http://www.softsynth.com
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define SAMPLE_RATE (44100)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
typedef struct
{
float sine[TABLE_SIZE];
int left_phase;
int right_phase;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback(const void* inputBuffer,
void* outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void* userData)
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned int i;
(void) inputBuffer; /* Prevent unused argument warning. */
for( i=0; i<framesPerBuffer; i++ )
{
*out++ = data->sine[data->left_phase]; /* left */
*out++ = data->sine[data->right_phase]; /* right */
data->left_phase += 1;
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
}
return 0;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
paTestData data;
int i;
printf("PortAudio Test: output sine wave.\n");
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data.left_phase = data.right_phase = 0;
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream( &stream,
NULL, /* No input. */
&outputParameters, /* As above. */
SAMPLE_RATE,
256, /* Frames per buffer. */
paClipOff, /* No out of range samples expected. */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Hit ENTER to stop program.\n");
getchar();
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

210
third_party/portaudio/test/patest_many.c vendored Normal file
View File

@@ -0,0 +1,210 @@
/** @file patest_many.c
@ingroup test_src
@brief Start and stop the PortAudio Driver multiple times.
@author Phil Burk http://www.softsynth.com
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "portaudio.h"
#define NUM_SECONDS (1)
#define SAMPLE_RATE (44100)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
typedef struct
{
short sine[TABLE_SIZE];
int left_phase;
int right_phase;
unsigned int sampsToGo;
}
paTestData;
PaError TestOnce( void );
static int patest1Callback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData );
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patest1Callback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
short *out = (short*)outputBuffer;
unsigned int i;
int finished = 0;
(void) inputBuffer; /* Prevent "unused variable" warnings. */
if( data->sampsToGo < framesPerBuffer )
{
/* final buffer... */
for( i=0; i<data->sampsToGo; i++ )
{
*out++ = data->sine[data->left_phase]; /* left */
*out++ = data->sine[data->right_phase]; /* right */
data->left_phase += 1;
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
}
/* zero remainder of final buffer */
for( ; i<framesPerBuffer; i++ )
{
*out++ = 0; /* left */
*out++ = 0; /* right */
}
finished = 1;
}
else
{
for( i=0; i<framesPerBuffer; i++ )
{
*out++ = data->sine[data->left_phase]; /* left */
*out++ = data->sine[data->right_phase]; /* right */
data->left_phase += 1;
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
}
data->sampsToGo -= framesPerBuffer;
}
return finished;
}
/*******************************************************************/
#ifdef MACINTOSH
int main(void);
int main(void)
{
int i;
PaError err;
int numLoops = 10;
printf("Loop %d times.\n", numLoops );
for( i=0; i<numLoops; i++ )
{
printf("Loop %d out of %d.\n", i+1, numLoops );
err = TestOnce();
if( err < 0 ) return 0;
}
}
#else
int main(int argc, char **argv);
int main(int argc, char **argv)
{
PaError err;
int i, numLoops = 10;
if( argc > 1 )
{
numLoops = atoi(argv[1]);
}
for( i=0; i<numLoops; i++ )
{
printf("Loop %d out of %d.\n", i+1, numLoops );
err = TestOnce();
if( err < 0 ) return 1;
}
printf("Test complete.\n");
return 0;
}
#endif
PaError TestOnce( void )
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
paTestData data;
int i;
int totalSamps;
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (short) (32767.0 * sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ));
}
data.left_phase = data.right_phase = 0;
data.sampsToGo = totalSamps = NUM_SECONDS * SAMPLE_RATE; /* Play for a few seconds. */
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paInt16;
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
1024, /* frames per buffer */
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patest1Callback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Waiting for sound to finish.\n");
Pa_Sleep(1000);
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
return paNoError;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,216 @@
/** @file patest_maxsines.c
@ingroup test_src
@brief How many sine waves can we calculate and play in less than 80% CPU Load.
@author Ross Bencina <rossb@audiomulch.com>
@author Phil Burk <philburk@softsynth.com>
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define MAX_SINES (2000)
#define MAX_USAGE (0.5)
#define SAMPLE_RATE (44100)
#define FREQ_TO_PHASE_INC(freq) (freq/(float)SAMPLE_RATE)
#define MIN_PHASE_INC FREQ_TO_PHASE_INC(200.0f)
#define MAX_PHASE_INC (MIN_PHASE_INC * (1 << 5))
#define FRAMES_PER_BUFFER (512)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TWOPI (M_PI * 2.0)
#define TABLE_SIZE (1024)
typedef struct paTestData
{
int numSines;
float sine[TABLE_SIZE + 1]; /* add one for guard point for interpolation */
float phases[MAX_SINES];
}
paTestData;
/* Convert phase between 0.0 and 1.0 to sine value
* using linear interpolation.
*/
float LookupSine( paTestData *data, float phase );
float LookupSine( paTestData *data, float phase )
{
float fIndex = phase*TABLE_SIZE;
int index = (int) fIndex;
float fract = fIndex - index;
float lo = data->sine[index];
float hi = data->sine[index+1];
float val = lo + fract*(hi-lo);
return val;
}
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback(const void* inputBuffer,
void* outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void* userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
float outSample;
float scaler;
int numForScale;
unsigned long i;
int j;
int finished = 0;
(void) inputBuffer; /* Prevent unused argument warning. */
/* Determine amplitude scaling factor */
numForScale = data->numSines;
if( numForScale < 8 ) numForScale = 8; /* prevent pops at beginning */
scaler = 1.0f / numForScale;
for( i=0; i<framesPerBuffer; i++ )
{
float output = 0.0;
float phaseInc = MIN_PHASE_INC;
float phase;
for( j=0; j<data->numSines; j++ )
{
/* Advance phase of next oscillator. */
phase = data->phases[j];
phase += phaseInc;
if( phase >= 1.0 ) phase -= 1.0;
output += LookupSine(data, phase);
data->phases[j] = phase;
phaseInc *= 1.02f;
if( phaseInc > MAX_PHASE_INC ) phaseInc = MIN_PHASE_INC;
}
outSample = (float) (output * scaler);
*out++ = outSample; /* Left */
*out++ = outSample; /* Right */
}
return finished;
}
/*******************************************************************/
int main(void);
int main(void)
{
int i;
PaStream* stream;
PaStreamParameters outputParameters;
PaError err;
paTestData data = {0};
double load;
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data.sine[TABLE_SIZE] = data.sine[0]; /* set guard point */
err = Pa_Initialize();
if( err != paNoError )
goto error;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* Default output device. */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2; /* Stereo output. */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output. */
outputParameters.hostApiSpecificStreamInfo = NULL;
outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)
->defaultHighOutputLatency;
err = Pa_OpenStream(&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* No out of range samples should occur. */
patestCallback,
&data);
if( err != paNoError )
goto error;
err = Pa_StartStream( stream );
if( err != paNoError )
goto error;
/* Play an increasing number of sine waves until we hit MAX_USAGE */
do {
data.numSines += 10;
Pa_Sleep(200);
load = Pa_GetStreamCpuLoad(stream);
printf("numSines = %d, CPU load = %f\n", data.numSines, load );
fflush(stdout);
} while((load < MAX_USAGE) && (data.numSines < MAX_SINES));
Pa_Sleep(2000); /* Stay for 2 seconds at max CPU. */
err = Pa_StopStream( stream );
if( err != paNoError )
goto error;
err = Pa_CloseStream( stream );
if( err != paNoError )
goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

155
third_party/portaudio/test/patest_mono.c vendored Normal file
View File

@@ -0,0 +1,155 @@
/** @file patest_mono.c
@ingroup test_src
@brief Play a monophonic sine wave using the Portable Audio api for several seconds.
@author Phil Burk http://www.softsynth.com
*/
/*
* $Id$
*
* Authors:
* Ross Bencina <rossb@audiomulch.com>
* Phil Burk <philburk@softsynth.com>
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define NUM_SECONDS (10)
#define SAMPLE_RATE (44100)
#define AMPLITUDE (0.8)
#define FRAMES_PER_BUFFER (64)
#define OUTPUT_DEVICE Pa_GetDefaultOutputDevice()
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
typedef struct
{
float sine[TABLE_SIZE];
int phase;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i;
int finished = 0;
/* avoid unused variable warnings */
(void) inputBuffer;
(void) timeInfo;
(void) statusFlags;
for( i=0; i<framesPerBuffer; i++ )
{
*out++ = data->sine[data->phase]; /* left */
data->phase += 1;
if( data->phase >= TABLE_SIZE ) data->phase -= TABLE_SIZE;
}
return finished;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
paTestData data;
int i;
printf("PortAudio Test: output MONO sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) (AMPLITUDE * sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ));
}
data.phase = 0;
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = OUTPUT_DEVICE;
outputParameters.channelCount = 1; /* MONO output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Play for %d seconds.\n", NUM_SECONDS ); fflush(stdout);
Pa_Sleep( NUM_SECONDS * 1000 );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,205 @@
/** @file patest_multi_sine.c
@ingroup test_src
@brief Play a different sine wave on each channel.
@author Phil Burk http://www.softsynth.com
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (128)
#define FREQ_INCR (300.0 / SAMPLE_RATE)
#define MAX_CHANNELS (64)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
typedef struct
{
short interleaved; /* Nonzero for interleaved / zero for non-interleaved. */
int numChannels; /* Actually used. */
double phases[MAX_CHANNELS]; /* Each channel gets its' own frequency. */
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback(const void* inputBuffer,
void* outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void* userData)
{
int frameIndex, channelIndex;
float** outputs = (float**)outputBuffer;
paTestData* data = (paTestData*)userData;
(void) inputBuffer; /* Prevent unused arg warning. */
if (data->interleaved)
{
float *out = (float*)outputBuffer; /* interleaved version */
for( frameIndex=0; frameIndex<(int)framesPerBuffer; frameIndex++ )
{
for( channelIndex=0; channelIndex<data->numChannels; channelIndex++ )
{
/* Output sine wave on every channel. */
*out++ = (float) sin(data->phases[channelIndex]);
/* Play each channel at a higher frequency. */
data->phases[channelIndex] += FREQ_INCR * (4 + channelIndex);
if( data->phases[channelIndex] >= (2.0 * M_PI) ) data->phases[channelIndex] -= (2.0 * M_PI);
}
}
}
else
{
for( frameIndex=0; frameIndex<(int)framesPerBuffer; frameIndex++ )
{
for( channelIndex=0; channelIndex<data->numChannels; channelIndex++ )
{
/* Output sine wave on every channel. */
outputs[channelIndex][frameIndex] = (float) sin(data->phases[channelIndex]);
/* Play each channel at a higher frequency. */
data->phases[channelIndex] += FREQ_INCR * (4 + channelIndex);
if( data->phases[channelIndex] >= (2.0 * M_PI) ) data->phases[channelIndex] -= (2.0 * M_PI);
}
}
}
return 0;
}
/*******************************************************************/
int test(short interleaved)
{
PaStream* stream;
PaStreamParameters outputParameters;
PaError err;
const PaDeviceInfo* pdi;
paTestData data;
short n;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* Default output device, max channels. */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
return paInvalidDevice;
}
pdi = Pa_GetDeviceInfo(outputParameters.device);
outputParameters.channelCount = pdi->maxOutputChannels;
if (outputParameters.channelCount > MAX_CHANNELS)
outputParameters.channelCount = MAX_CHANNELS;
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = pdi->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
data.interleaved = interleaved;
data.numChannels = outputParameters.channelCount;
for (n = 0; n < data.numChannels; n++)
data.phases[n] = 0.0; /* Phases wrap and maybe don't need initialisation. */
printf("%d ", data.numChannels);
if (interleaved)
printf("interleaved ");
else
{
printf(" non-interleaved ");
outputParameters.sampleFormat |= paNonInterleaved;
}
printf("channels.\n");
err = Pa_OpenStream(&stream,
NULL, /* No input. */
&outputParameters,
SAMPLE_RATE, /* Sample rate. */
FRAMES_PER_BUFFER, /* Frames per buffer. */
paClipOff, /* Samples never out of range, no clipping. */
patestCallback,
&data);
if (err == paNoError)
{
err = Pa_StartStream(stream);
if (err == paNoError)
{
printf("Hit ENTER to stop this test.\n");
getchar();
err = Pa_StopStream(stream);
}
Pa_CloseStream( stream );
}
return err;
}
/*******************************************************************/
int main(void)
{
PaError err;
printf("PortAudio Test: output sine wave on each channel.\n" );
err = Pa_Initialize();
if (err != paNoError)
goto done;
err = test(1); /* 1 means interleaved. */
if (err != paNoError)
goto done;
err = test(0); /* 0 means not interleaved. */
if (err != paNoError)
goto done;
printf("Test finished.\n");
done:
if (err)
{
fprintf(stderr, "An error occurred while using the portaudio stream\n");
fprintf(stderr, "Error number: %d\n", err );
fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(err));
}
Pa_Terminate();
return 0;
}

View File

@@ -0,0 +1,251 @@
/** @file patest_out_underflow.c
@ingroup test_src
@brief Count output underflows (using paOutputUnderflow flag)
under overloaded and normal conditions.
@author Ross Bencina <rossb@audiomulch.com>
@author Phil Burk <philburk@softsynth.com>
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2004 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define MAX_SINES (1000)
#define MAX_LOAD (1.2)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (512)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TWOPI (M_PI * 2.0)
typedef struct paTestData
{
int sineCount;
double phases[MAX_SINES];
int countUnderflows;
int outputUnderflowCount;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i;
int j;
int finished = paContinue;
(void) timeInfo; /* Prevent unused variable warning. */
(void) inputBuffer; /* Prevent unused variable warning. */
if( data->countUnderflows && (statusFlags & paOutputUnderflow) )
{
data->outputUnderflowCount++;
}
for( i=0; i<framesPerBuffer; i++ )
{
float output = 0.0;
double phaseInc = 0.02;
double phase;
for( j=0; j<data->sineCount; j++ )
{
/* Advance phase of next oscillator. */
phase = data->phases[j];
phase += phaseInc;
if( phase > TWOPI ) phase -= TWOPI;
phaseInc *= 1.02;
if( phaseInc > 0.5 ) phaseInc *= 0.5;
/* This is not a very efficient way to calc sines. */
output += (float) sin( phase );
data->phases[j] = phase;
}
*out++ = (float) (output / data->sineCount);
}
return finished;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
int safeSineCount, stressedSineCount;
int sineCount;
int safeUnderflowCount, stressedUnderflowCount;
paTestData data = {0};
double load;
double suggestedLatency;
printf("PortAudio Test: output sine waves, count underflows. SR = %d, BufSize = %d. MAX_LOAD = %f\n",
SAMPLE_RATE, FRAMES_PER_BUFFER, (float)MAX_LOAD );
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 1; /* mono output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.suggestedLatency = suggestedLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Establishing load conditions...\n" );
/* Determine number of sines required to get to 50% */
do
{
Pa_Sleep( 100 );
load = Pa_GetStreamCpuLoad( stream );
printf("sineCount = %d, CPU load = %f\n", data.sineCount, load );
if( load < 0.3 )
{
data.sineCount += 10;
}
else if( load < 0.4 )
{
data.sineCount += 2;
}
else
{
data.sineCount += 1;
}
}
while( load < 0.5 && data.sineCount < (MAX_SINES-1));
safeSineCount = data.sineCount;
/* Calculate target stress value then ramp up to that level*/
stressedSineCount = (int) (2.0 * data.sineCount * MAX_LOAD );
if( stressedSineCount > MAX_SINES )
stressedSineCount = MAX_SINES;
sineCount = data.sineCount;
for( ; sineCount < stressedSineCount; sineCount+=4 )
{
data.sineCount = sineCount;
Pa_Sleep( 100 );
load = Pa_GetStreamCpuLoad( stream );
printf("STRESSING: sineCount = %d, CPU load = %f\n", sineCount, load );
}
printf("Counting underflows for 2 seconds.\n");
data.countUnderflows = 1;
Pa_Sleep( 2000 );
stressedUnderflowCount = data.outputUnderflowCount;
data.countUnderflows = 0;
data.sineCount = safeSineCount;
printf("Resuming safe load...\n");
Pa_Sleep( 1500 );
data.outputUnderflowCount = 0;
Pa_Sleep( 1500 );
load = Pa_GetStreamCpuLoad( stream );
printf("sineCount = %d, CPU load = %f\n", data.sineCount, load );
printf("Counting underflows for 5 seconds.\n");
data.countUnderflows = 1;
Pa_Sleep( 5000 );
safeUnderflowCount = data.outputUnderflowCount;
printf("Stop stream.\n");
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("suggestedLatency = %f\n", suggestedLatency);
// Report pass or fail
if( stressedUnderflowCount == 0 )
printf("Test FAILED, no output underflows detected under stress.\n");
else
printf("Test %s, %d expected output underflows detected under stress, "
"%d unexpected underflows detected under safe load.\n",
(safeUnderflowCount == 0) ? "PASSED" : "FAILED",
stressedUnderflowCount, safeUnderflowCount );
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,234 @@
/** @file patest_prime.c
@ingroup test_src
@brief Test stream priming mode.
@author Ross Bencina http://www.audiomulch.com/~rossb
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#include "pa_util.h"
#define NUM_BEEPS (3)
#define SAMPLE_RATE (44100)
#define SAMPLE_PERIOD (1.0/44100.0)
#define FRAMES_PER_BUFFER (256)
#define BEEP_DURATION (400)
#define IDLE_DURATION (SAMPLE_RATE*2) /* 2 seconds */
#define SLEEP_MSEC (50)
#define STATE_BKG_IDLE (0)
#define STATE_BKG_BEEPING (1)
typedef struct
{
float leftPhase;
float rightPhase;
int state;
int beepCountdown;
int idleCountdown;
}
paTestData;
static void InitializeTestData( paTestData *testData )
{
testData->leftPhase = 0;
testData->rightPhase = 0;
testData->state = STATE_BKG_BEEPING;
testData->beepCountdown = BEEP_DURATION;
testData->idleCountdown = IDLE_DURATION;
}
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo *timeInfo,
PaStreamCallbackFlags statusFlags, void *userData )
{
/* Cast data passed through stream to our structure. */
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned int i;
int result = paContinue;
/* suppress unused parameter warnings */
(void) inputBuffer;
(void) timeInfo;
(void) statusFlags;
for( i=0; i<framesPerBuffer; i++ )
{
switch( data->state )
{
case STATE_BKG_IDLE:
*out++ = 0.0; /* left */
*out++ = 0.0; /* right */
--data->idleCountdown;
if( data->idleCountdown <= 0 ) result = paComplete;
break;
case STATE_BKG_BEEPING:
if( data->beepCountdown <= 0 )
{
data->state = STATE_BKG_IDLE;
*out++ = 0.0; /* left */
*out++ = 0.0; /* right */
}
else
{
/* Play sawtooth wave. */
*out++ = data->leftPhase; /* left */
*out++ = data->rightPhase; /* right */
/* Generate simple sawtooth phaser that ranges between -1.0 and 1.0. */
data->leftPhase += 0.01f;
/* When signal reaches top, drop back down. */
if( data->leftPhase >= 1.0f ) data->leftPhase -= 2.0f;
/* higher pitch so we can distinguish left and right. */
data->rightPhase += 0.03f;
if( data->rightPhase >= 1.0f ) data->rightPhase -= 2.0f;
}
--data->beepCountdown;
break;
}
}
return result;
}
/*******************************************************************/
static PaError DoTest( int flags )
{
PaStream *stream;
PaError err = paNoError;
paTestData data;
PaStreamParameters outputParameters;
InitializeTestData( &data );
outputParameters.device = Pa_GetDefaultOutputDevice();
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2;
outputParameters.hostApiSpecificStreamInfo = NULL;
outputParameters.sampleFormat = paFloat32;
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
/* Open an audio I/O stream. */
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER, /* frames per buffer */
paClipOff | flags, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("hear \"BEEP\"\n" );
fflush(stdout);
while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) Pa_Sleep(SLEEP_MSEC);
if( err < 0 ) goto error;
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
return err;
error:
return err;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaError err = paNoError;
int i;
/* Initialize library before making any other calls. */
err = Pa_Initialize();
if( err != paNoError ) goto error;
printf("PortAudio Test: Testing stream playback with no priming.\n");
printf("PortAudio Test: you should see BEEP before you hear it.\n");
printf("BEEP %d times.\n", NUM_BEEPS );
for( i=0; i< NUM_BEEPS; ++i )
{
err = DoTest( 0 );
if( err != paNoError )
goto error;
}
printf("PortAudio Test: Testing stream playback with priming.\n");
printf("PortAudio Test: you should see BEEP around the same time you hear it.\n");
for( i=0; i< NUM_BEEPS; ++i )
{
err = DoTest( paPrimeOutputBuffersUsingStreamCallback );
if( err != paNoError )
goto error;
}
printf("Test finished.\n");
Pa_Terminate();
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,243 @@
/** @file patest_read_record.c
@ingroup test_src
@brief Record input into an array; Save array to a file; Playback recorded
data. Implemented using the blocking API (Pa_ReadStream(), Pa_WriteStream() )
@author Phil Burk http://www.softsynth.com
@author Ross Bencina rossb@audiomulch.com
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <stdlib.h>
#include "portaudio.h"
/* #define SAMPLE_RATE (17932) // Test failure to open with this value. */
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (1024)
#define NUM_SECONDS (5)
#define NUM_CHANNELS (2)
/* #define DITHER_FLAG (paDitherOff) */
#define DITHER_FLAG (0) /**/
/* Select sample format. */
#if 1
#define PA_SAMPLE_TYPE paFloat32
typedef float SAMPLE;
#define SAMPLE_SILENCE (0.0f)
#define PRINTF_S_FORMAT "%.8f"
#elif 1
#define PA_SAMPLE_TYPE paInt16
typedef short SAMPLE;
#define SAMPLE_SILENCE (0)
#define PRINTF_S_FORMAT "%d"
#elif 0
#define PA_SAMPLE_TYPE paInt8
typedef char SAMPLE;
#define SAMPLE_SILENCE (0)
#define PRINTF_S_FORMAT "%d"
#else
#define PA_SAMPLE_TYPE paUInt8
typedef unsigned char SAMPLE;
#define SAMPLE_SILENCE (128)
#define PRINTF_S_FORMAT "%d"
#endif
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters inputParameters, outputParameters;
PaStream *stream;
PaError err;
SAMPLE *recordedSamples;
int i;
int totalFrames;
int numSamples;
int numBytes;
SAMPLE max, average, val;
printf("patest_read_record.c\n"); fflush(stdout);
totalFrames = NUM_SECONDS * SAMPLE_RATE; /* Record for a few seconds. */
numSamples = totalFrames * NUM_CHANNELS;
numBytes = numSamples * sizeof(SAMPLE);
recordedSamples = (SAMPLE *) malloc( numBytes );
if( recordedSamples == NULL )
{
printf("Could not allocate record array.\n");
exit(1);
}
for( i=0; i<numSamples; i++ ) recordedSamples[i] = 0;
err = Pa_Initialize();
if( err != paNoError ) goto error;
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device.\n");
goto error;
}
inputParameters.channelCount = NUM_CHANNELS;
inputParameters.sampleFormat = PA_SAMPLE_TYPE;
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
/* Record some audio. -------------------------------------------- */
err = Pa_OpenStream(
&stream,
&inputParameters,
NULL, /* &outputParameters, */
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
NULL, /* no callback, use blocking API */
NULL ); /* no callback, so no callback userData */
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Now recording!!\n"); fflush(stdout);
err = Pa_ReadStream( stream, recordedSamples, totalFrames );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
/* Measure maximum peak amplitude. */
max = 0;
average = 0;
for( i=0; i<numSamples; i++ )
{
val = recordedSamples[i];
if( val < 0 ) val = -val; /* ABS */
if( val > max )
{
max = val;
}
average += val;
}
average = average / numSamples;
printf("Sample max amplitude = "PRINTF_S_FORMAT"\n", max );
printf("Sample average = "PRINTF_S_FORMAT"\n", average );
/* Was as below. Better choose at compile time because this
keeps generating compiler-warnings:
if( PA_SAMPLE_TYPE == paFloat32 )
{
printf("sample max amplitude = %f\n", max );
printf("sample average = %f\n", average );
}
else
{
printf("sample max amplitude = %d\n", max );
printf("sample average = %d\n", average );
}
*/
/* Write recorded data to a file. */
#if 0
{
FILE *fid;
fid = fopen("recorded.raw", "wb");
if( fid == NULL )
{
printf("Could not open file.");
}
else
{
fwrite( recordedSamples, NUM_CHANNELS * sizeof(SAMPLE), totalFrames, fid );
fclose( fid );
printf("Wrote data to 'recorded.raw'\n");
}
}
#endif
/* Playback recorded data. -------------------------------------------- */
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = NUM_CHANNELS;
outputParameters.sampleFormat = PA_SAMPLE_TYPE;
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
printf("Begin playback.\n"); fflush(stdout);
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
NULL, /* no callback, use blocking API */
NULL ); /* no callback, so no callback userData */
if( err != paNoError ) goto error;
if( stream )
{
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Waiting for playback to finish.\n"); fflush(stdout);
err = Pa_WriteStream( stream, recordedSamples, totalFrames );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
printf("Done.\n"); fflush(stdout);
}
free( recordedSamples );
Pa_Terminate();
return 0;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return -1;
}

View File

@@ -0,0 +1,86 @@
/** @file patest_ringmix.c
@ingroup test_src
@brief Ring modulate inputs to left output, mix inputs to right output.
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include "stdio.h"
#include "portaudio.h"
/* This will be called asynchronously by the PortAudio engine. */
static int myCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
const float *in = (const float *) inputBuffer;
float *out = (float *) outputBuffer;
float leftInput, rightInput;
unsigned int i;
/* Read input buffer, process data, and fill output buffer. */
for( i=0; i<framesPerBuffer; i++ )
{
leftInput = *in++; /* Get interleaved samples from input buffer. */
rightInput = *in++;
*out++ = leftInput * rightInput; /* ring modulation */
*out++ = 0.5f * (leftInput + rightInput); /* mix */
}
return 0;
}
/* Open a PortAudioStream to input and output audio data. */
int main(void)
{
PaStream *stream;
Pa_Initialize();
Pa_OpenDefaultStream(
&stream,
2, 2, /* stereo input and output */
paFloat32, 44100.0,
64, /* 64 frames per buffer */
myCallback, NULL );
Pa_StartStream( stream );
Pa_Sleep( 10000 ); /* Sleep for 10 seconds while processing. */
Pa_StopStream( stream );
Pa_CloseStream( stream );
Pa_Terminate();
return 0;
}

View File

@@ -0,0 +1,216 @@
/** @file patest_sine8.c
@ingroup test_src
@brief Test 8 bit data: play a sine wave for several seconds.
@author Ross Bencina <rossb@audiomulch.com>
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define NUM_SECONDS (8)
#define SAMPLE_RATE (44100)
#define TABLE_SIZE (200)
#define TEST_UNSIGNED (0)
#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
#define M_PI (3.14159265)
#endif
typedef struct
{
sample_t sine[TABLE_SIZE];
int left_phase;
int right_phase;
unsigned int framesToGo;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
sample_t *out = (sample_t*)outputBuffer;
int i;
int framesToCalc;
int finished = 0;
(void) inputBuffer; /* Prevent unused variable warnings. */
if( data->framesToGo < framesPerBuffer )
{
framesToCalc = data->framesToGo;
data->framesToGo = 0;
finished = 1;
}
else
{
framesToCalc = framesPerBuffer;
data->framesToGo -= framesPerBuffer;
}
for( i=0; i<framesToCalc; i++ )
{
*out++ = data->sine[data->left_phase]; /* left */
*out++ = data->sine[data->right_phase]; /* right */
data->left_phase += 1;
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
}
/* zero remainder of final buffer */
for( ; i<(int)framesPerBuffer; i++ )
{
*out++ = SILENCE; /* left */
*out++ = SILENCE; /* right */
}
return finished;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters outputParameters;
PaStream* stream;
PaError err;
paTestData data;
PaTime streamOpened;
int i, totalSamps;
#if TEST_UNSIGNED
printf("PortAudio Test: output UNsigned 8 bit sine wave.\n");
#else
printf("PortAudio Test: output signed 8 bit sine wave.\n");
#endif
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = SILENCE + (char) (127.0 * sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ));
}
data.left_phase = data.right_phase = 0;
data.framesToGo = totalSamps = NUM_SECONDS * SAMPLE_RATE; /* Play for a few seconds. */
err = Pa_Initialize();
if( err != paNoError )
goto error;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* Default output device. */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2; /* Stereo output. */
outputParameters.sampleFormat = TEST_FORMAT;
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream( &stream,
NULL, /* No input. */
&outputParameters,
SAMPLE_RATE,
256, /* Frames per buffer. */
paClipOff, /* We won't output out of range samples so don't bother clipping them. */
patestCallback,
&data );
if( err != paNoError )
goto error;
streamOpened = Pa_GetStreamTime( stream ); /* Time in seconds when stream was opened (approx). */
err = Pa_StartStream( stream );
if( err != paNoError )
goto error;
/* Watch until sound is halfway finished. */
/* (Was ( Pa_StreamTime( stream ) < (totalSamps/2) ) in V18. */
while( (Pa_GetStreamTime( stream ) - streamOpened) < (PaTime)NUM_SECONDS / 2.0 )
Pa_Sleep(10);
/* Stop sound. */
printf("Stopping Stream.\n");
err = Pa_StopStream( stream );
if( err != paNoError )
goto error;
printf("Pause for 2 seconds.\n");
Pa_Sleep( 2000 );
printf("Starting again.\n");
err = Pa_StartStream( stream );
if( err != paNoError )
goto error;
printf("Waiting for sound to finish.\n");
while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
Pa_Sleep(100);
if( err < 0 )
goto error;
err = Pa_CloseStream( stream );
if( err != paNoError )
goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,190 @@
/*
* patest_sine_channelmaps.c
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file patest_sine_channelmaps.c
@ingroup test_src
@brief Plays sine waves using sme simple channel maps.
Designed for use with CoreAudio, but should made to work with other APIs
@author Bjorn Roche <bjorn@xowave.com>
@author Ross Bencina <rossb@audiomulch.com>
@author Phil Burk <philburk@softsynth.com>
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#ifdef __APPLE__
#include "pa_mac_core.h"
#endif
#define NUM_SECONDS (5)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (64)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
typedef struct
{
float sine[TABLE_SIZE];
int left_phase;
int right_phase;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i;
(void) timeInfo; /* Prevent unused variable warnings. */
(void) statusFlags;
(void) inputBuffer;
for( i=0; i<framesPerBuffer; i++ )
{
*out++ = data->sine[data->left_phase]; /* left */
*out++ = data->sine[data->right_phase]; /* right */
data->left_phase += 1;
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
}
return paContinue;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
paTestData data;
#ifdef __APPLE__
PaMacCoreStreamInfo macInfo;
const SInt32 channelMap[4] = { -1, -1, 0, 1 };
#endif
int i;
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
printf("Output will be mapped to channels 2 and 3 instead of 0 and 1.\n");
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data.left_phase = data.right_phase = 0;
err = Pa_Initialize();
if( err != paNoError ) goto error;
/** setup host specific info */
#ifdef __APPLE__
PaMacCore_SetupStreamInfo( &macInfo, paMacCorePlayNice );
PaMacCore_SetupChannelMap( &macInfo, channelMap, 4 );
for( i=0; i<4; ++i )
printf( "channel %d name: %s\n", i, PaMacCore_GetChannelName( Pa_GetDefaultOutputDevice(), i, false ) );
#else
printf( "Channel mapping not supported on this platform. Reverting to normal sine test.\n" );
#endif
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
#ifdef __APPLE__
outputParameters.hostApiSpecificStreamInfo = &macInfo;
#else
outputParameters.hostApiSpecificStreamInfo = NULL;
#endif
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Play for %d seconds.\n", NUM_SECONDS );
Pa_Sleep( NUM_SECONDS * 1000 );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,203 @@
/** @file patest_sine_formats.c
@ingroup test_src
@brief Play a sine wave for several seconds. Test various data formats.
@author Phil Burk
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define NUM_SECONDS (10)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (512)
#define LEFT_FREQ (SAMPLE_RATE/256.0) /* So we hit 1.0 */
#define RIGHT_FREQ (500.0)
#define AMPLITUDE (1.0)
/* Select ONE format for testing. */
#define TEST_UINT8 (0)
#define TEST_INT8 (0)
#define TEST_INT16 (1)
#define TEST_FLOAT32 (0)
#if TEST_UINT8
#define TEST_FORMAT paUInt8
typedef unsigned char SAMPLE_t;
#define SAMPLE_ZERO (0x80)
#define DOUBLE_TO_SAMPLE(x) (SAMPLE_ZERO + (SAMPLE_t)(127.0 * (x)))
#define FORMAT_NAME "Unsigned 8 Bit"
#elif TEST_INT8
#define TEST_FORMAT paInt8
typedef char SAMPLE_t;
#define SAMPLE_ZERO (0)
#define DOUBLE_TO_SAMPLE(x) (SAMPLE_ZERO + (SAMPLE_t)(127.0 * (x)))
#define FORMAT_NAME "Signed 8 Bit"
#elif TEST_INT16
#define TEST_FORMAT paInt16
typedef short SAMPLE_t;
#define SAMPLE_ZERO (0)
#define DOUBLE_TO_SAMPLE(x) (SAMPLE_ZERO + (SAMPLE_t)(32767 * (x)))
#define FORMAT_NAME "Signed 16 Bit"
#elif TEST_FLOAT32
#define TEST_FORMAT paFloat32
typedef float SAMPLE_t;
#define SAMPLE_ZERO (0.0)
#define DOUBLE_TO_SAMPLE(x) ((SAMPLE_t)(x))
#define FORMAT_NAME "Float 32 Bit"
#endif
#ifndef M_PI
#define M_PI (3.14159265)
#endif
typedef struct
{
double left_phase;
double right_phase;
unsigned int framesToGo;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer,
void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
SAMPLE_t *out = (SAMPLE_t *)outputBuffer;
int i;
int framesToCalc;
int finished = 0;
(void) inputBuffer; /* Prevent unused variable warnings. */
if( data->framesToGo < framesPerBuffer )
{
framesToCalc = data->framesToGo;
data->framesToGo = 0;
finished = 1;
}
else
{
framesToCalc = framesPerBuffer;
data->framesToGo -= framesPerBuffer;
}
for( i=0; i<framesToCalc; i++ )
{
data->left_phase += (LEFT_FREQ / SAMPLE_RATE);
if( data->left_phase > 1.0) data->left_phase -= 1.0;
*out++ = DOUBLE_TO_SAMPLE( AMPLITUDE * sin( (data->left_phase * M_PI * 2. )));
data->right_phase += (RIGHT_FREQ / SAMPLE_RATE);
if( data->right_phase > 1.0) data->right_phase -= 1.0;
*out++ = DOUBLE_TO_SAMPLE( AMPLITUDE * sin( (data->right_phase * M_PI * 2. )));
}
/* zero remainder of final buffer */
for( ; i<(int)framesPerBuffer; i++ )
{
*out++ = SAMPLE_ZERO; /* left */
*out++ = SAMPLE_ZERO; /* right */
}
return finished;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStream *stream;
PaStreamParameters outputParameters;
PaError err;
paTestData data;
int totalSamps;
printf("PortAudio Test: output " FORMAT_NAME "\n");
data.left_phase = data.right_phase = 0.0;
data.framesToGo = totalSamps = NUM_SECONDS * SAMPLE_RATE; /* Play for a few seconds. */
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* Default output device. */
outputParameters.channelCount = 2; /* Stereo output */
outputParameters.sampleFormat = TEST_FORMAT; /* Selected above. */
outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream( &stream,
NULL, /* No input. */
&outputParameters, /* As above. */
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Waiting %d seconds for sound to finish.\n", NUM_SECONDS );
while( ( err = Pa_IsStreamActive( stream ) ) == 1 ) Pa_Sleep(100);
if( err < 0 ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("PortAudio Test Finished: " FORMAT_NAME "\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,182 @@
/*
* $Id: patest_sine.c 1097 2006-08-26 08:27:53Z rossb $
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
/** @file patest_sine_srate_mac.c
@ingroup test_src
@brief Plays sine waves at 44100 and 48000,
and forces the hardware to change if this is a mac.
Designed for use with CoreAudio.
@author Bjorn Roche <bjorn@xowave.com>
@author Ross Bencina <rossb@audiomulch.com>
@author Phil Burk <philburk@softsynth.com>
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#ifdef __APPLE__
#include "pa_mac_core.h"
#endif
#define NUM_SECONDS (5)
#define SAMPLE_RATE1 (44100)
#define SAMPLE_RATE2 (48000)
#define FRAMES_PER_BUFFER (64)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
typedef struct
{
float sine[TABLE_SIZE];
int left_phase;
int right_phase;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i;
(void) timeInfo; /* Prevent unused variable warnings. */
(void) statusFlags;
(void) inputBuffer;
for( i=0; i<framesPerBuffer; i++ )
{
*out++ = data->sine[data->left_phase]; /* left */
*out++ = data->sine[data->right_phase]; /* right */
data->left_phase += 1;
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
}
return paContinue;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
paTestData data;
#ifdef __APPLE__
PaMacCoreStreamInfo macInfo;
#endif
int i;
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data.left_phase = data.right_phase = 0;
err = Pa_Initialize();
if( err != paNoError ) goto error;
for( i=0; i<2; ++i ) {
const float sr = i ? SAMPLE_RATE2 : SAMPLE_RATE1;
printf("PortAudio Test: output sine wave. SR = %g, BufSize = %d\n", sr, FRAMES_PER_BUFFER);
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
/** setup host specific info */
#ifdef __APPLE__
PaMacCore_SetupStreamInfo( &macInfo, paMacCorePro );
outputParameters.hostApiSpecificStreamInfo = &macInfo;
#else
printf( "Hardware SR changing not being tested on this platform.\n" );
outputParameters.hostApiSpecificStreamInfo = NULL;
#endif
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
sr,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Play for %d seconds.\n", NUM_SECONDS );
Pa_Sleep( NUM_SECONDS * 1000 );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
}
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,219 @@
/** @file patest_sine_time.c
@ingroup test_src
@brief Play a sine wave for several seconds, pausing in the middle.
Uses the Pa_GetStreamTime() call.
@author Ross Bencina <rossb@audiomulch.com>
@author Phil Burk <philburk@softsynth.com>
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#include "pa_util.h"
#define NUM_SECONDS (8)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (64)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TWOPI (M_PI * 2.0)
#define TABLE_SIZE (200)
typedef struct
{
double left_phase;
double right_phase;
volatile PaTime outTime;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned int i;
double left_phaseInc = 0.02;
double right_phaseInc = 0.06;
double left_phase = data->left_phase;
double right_phase = data->right_phase;
(void) statusFlags; /* Prevent unused variable warnings. */
(void) inputBuffer;
data->outTime = timeInfo->outputBufferDacTime;
for( i=0; i<framesPerBuffer; i++ )
{
left_phase += left_phaseInc;
if( left_phase > TWOPI ) left_phase -= TWOPI;
*out++ = (float) sin( left_phase );
right_phase += right_phaseInc;
if( right_phase > TWOPI ) right_phase -= TWOPI;
*out++ = (float) sin( right_phase );
}
data->left_phase = left_phase;
data->right_phase = right_phase;
return paContinue;
}
/*******************************************************************/
static void ReportStreamTime( PaStream *stream, paTestData *data );
static void ReportStreamTime( PaStream *stream, paTestData *data )
{
PaTime streamTime, latency, outTime;
streamTime = Pa_GetStreamTime( stream );
outTime = data->outTime;
if( outTime < 0.0 )
{
printf("Stream time = %8.1f\n", streamTime );
}
else
{
latency = outTime - streamTime;
printf("Stream time = %8.4f, outTime = %8.4f, latency = %8.4f\n",
streamTime, outTime, latency );
}
fflush(stdout);
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
paTestData data;
PaTime startTime;
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
data.left_phase = data.right_phase = 0;
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
/* Watch until sound is halfway finished. */
printf("Play for %d seconds.\n", NUM_SECONDS/2 ); fflush(stdout);
data.outTime = -1.0; /* mark time for callback as undefined */
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
startTime = Pa_GetStreamTime( stream );
do
{
ReportStreamTime( stream, &data );
Pa_Sleep(100);
} while( (Pa_GetStreamTime( stream ) - startTime) < (NUM_SECONDS/2) );
/* Stop sound for 2 seconds. */
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
printf("Pause for 2 seconds.\n"); fflush(stdout);
Pa_Sleep( 2000 );
data.outTime = -1.0; /* mark time for callback as undefined */
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
startTime = Pa_GetStreamTime( stream );
printf("Play until sound is finished.\n"); fflush(stdout);
do
{
ReportStreamTime( stream, &data );
Pa_Sleep(100);
} while( (Pa_GetStreamTime( stream ) - startTime) < (NUM_SECONDS/2) );
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,174 @@
/** @file patest_start_stop.c
@ingroup test_src
@brief Play a sine wave for several seconds. Start and stop the stream multiple times.
@author Ross Bencina <rossb@audiomulch.com>
@author Phil Burk <philburk@softsynth.com>
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define OUTPUT_DEVICE Pa_GetDefaultOutputDevice() /* default output device */
#define NUM_SECONDS (3)
#define NUM_LOOPS (4)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (400)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
typedef struct
{
float sine[TABLE_SIZE];
int left_phase;
int right_phase;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i;
(void) timeInfo; /* Prevent unused variable warnings. */
(void) statusFlags;
(void) inputBuffer;
for( i=0; i<framesPerBuffer; i++ )
{
*out++ = data->sine[data->left_phase]; /* left */
*out++ = data->sine[data->right_phase]; /* right */
data->left_phase += 1;
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
}
return paContinue;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
paTestData data;
int i;
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data.left_phase = data.right_phase = 0;
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = OUTPUT_DEVICE;
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
for( i=0; i<NUM_LOOPS; i++ )
{
data.left_phase = data.right_phase = 0;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Play for %d seconds.\n", NUM_SECONDS );
Pa_Sleep( NUM_SECONDS * 1000 );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
printf("Stopped.\n" );
Pa_Sleep( 1000 );
}
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

324
third_party/portaudio/test/patest_stop.c vendored Normal file
View File

@@ -0,0 +1,324 @@
/** @file patest_stop.c
@ingroup test_src
@brief Test different ways of stopping audio.
Test the three ways of stopping audio:
- calling Pa_StopStream(),
- calling Pa_AbortStream(),
- and returning a 1 from the callback function.
A long latency is set up so that you can hear the difference.
Then a simple 8 note sequence is repeated twice.
The program will print what you should hear.
@author Phil Burk <philburk@softsynth.com>
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define OUTPUT_DEVICE (Pa_GetDefaultOutputDevice())
#define SLEEP_DUR (200)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (256)
#define LATENCY_SECONDS (3.f)
#define FRAMES_PER_NOTE (SAMPLE_RATE/2)
#define MAX_REPEATS (2)
#define FUNDAMENTAL (400.0f / SAMPLE_RATE)
#define NOTE_0 (FUNDAMENTAL * 1.0f / 1.0f)
#define NOTE_1 (FUNDAMENTAL * 5.0f / 4.0f)
#define NOTE_2 (FUNDAMENTAL * 4.0f / 3.0f)
#define NOTE_3 (FUNDAMENTAL * 3.0f / 2.0f)
#define NOTE_4 (FUNDAMENTAL * 2.0f / 1.0f)
#define MODE_FINISH (0)
#define MODE_STOP (1)
#define MODE_ABORT (2)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (400)
typedef struct
{
float waveform[TABLE_SIZE + 1]; /* Add one for guard point for interpolation. */
float phase_increment;
float phase;
float *tune;
int notesPerTune;
int frameCounter;
int noteCounter;
int repeatCounter;
PaTime outTime;
int stopMode;
int done;
}
paTestData;
/************* Prototypes *****************************/
int TestStopMode( paTestData *data );
float LookupWaveform( paTestData *data, float phase );
/******************************************************
* Convert phase between 0.0 and 1.0 to waveform value
* using linear interpolation.
*/
float LookupWaveform( paTestData *data, float phase )
{
float fIndex = phase*TABLE_SIZE;
int index = (int) fIndex;
float fract = fIndex - index;
float lo = data->waveform[index];
float hi = data->waveform[index+1];
float val = lo + fract*(hi-lo);
return val;
}
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
float value;
unsigned int i = 0;
int finished = paContinue;
(void) inputBuffer; /* Prevent unused variable warnings. */
(void) timeInfo;
(void) statusFlags;
/* data->outTime = outTime; */
if( !data->done )
{
for( i=0; i<framesPerBuffer; i++ )
{
/* Are we done with this note? */
if( data->frameCounter >= FRAMES_PER_NOTE )
{
data->noteCounter += 1;
data->frameCounter = 0;
/* Are we done with this tune? */
if( data->noteCounter >= data->notesPerTune )
{
data->noteCounter = 0;
data->repeatCounter += 1;
/* Are we totally done? */
if( data->repeatCounter >= MAX_REPEATS )
{
data->done = 1;
if( data->stopMode == MODE_FINISH )
{
finished = paComplete;
break;
}
}
}
data->phase_increment = data->tune[data->noteCounter];
}
value = LookupWaveform(data, data->phase);
*out++ = value; /* left */
*out++ = value; /* right */
data->phase += data->phase_increment;
if( data->phase >= 1.0f ) data->phase -= 1.0f;
data->frameCounter += 1;
}
}
/* zero remainder of final buffer */
for( ; i<framesPerBuffer; i++ )
{
*out++ = 0; /* left */
*out++ = 0; /* right */
}
return finished;
}
/*******************************************************************/
int main(void);
int main(void)
{
paTestData data;
int i;
float simpleTune[] = { NOTE_0, NOTE_1, NOTE_2, NOTE_3, NOTE_4, NOTE_3, NOTE_2, NOTE_1 };
printf("PortAudio Test: play song and test stopping. ask for %f seconds latency\n", LATENCY_SECONDS );
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.waveform[i] = (float) (
(0.2 * sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. )) +
(0.2 * sin( ((double)(3*i)/(double)TABLE_SIZE) * M_PI * 2. )) +
(0.1 * sin( ((double)(5*i)/(double)TABLE_SIZE) * M_PI * 2. ))
);
}
data.waveform[TABLE_SIZE] = data.waveform[0]; /* Set guard point. */
data.tune = &simpleTune[0];
data.notesPerTune = sizeof(simpleTune) / sizeof(float);
printf("Test MODE_FINISH - callback returns 1.\n");
printf("Should hear entire %d note tune repeated twice.\n", data.notesPerTune);
data.stopMode = MODE_FINISH;
if( TestStopMode( &data ) != paNoError )
{
printf("Test of MODE_FINISH failed!\n");
goto error;
}
printf("Test MODE_STOP - stop when song is done.\n");
printf("Should hear entire %d note tune repeated twice.\n", data.notesPerTune);
data.stopMode = MODE_STOP;
if( TestStopMode( &data ) != paNoError )
{
printf("Test of MODE_STOP failed!\n");
goto error;
}
printf("Test MODE_ABORT - abort immediately.\n");
printf("Should hear last repetition cut short by %f seconds.\n", LATENCY_SECONDS);
data.stopMode = MODE_ABORT;
if( TestStopMode( &data ) != paNoError )
{
printf("Test of MODE_ABORT failed!\n");
goto error;
}
return 0;
error:
return 1;
}
int TestStopMode( paTestData *data )
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
data->done = 0;
data->phase = 0.0;
data->frameCounter = 0;
data->noteCounter = 0;
data->repeatCounter = 0;
data->phase_increment = data->tune[data->noteCounter];
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = OUTPUT_DEVICE;
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = LATENCY_SECONDS;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER, /* frames per buffer */
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
if( data->stopMode == MODE_FINISH )
{
while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
{
/*printf("outTime = %g, note# = %d, repeat# = %d\n", data->outTime,
data->noteCounter, data->repeatCounter );
fflush(stdout); */
Pa_Sleep( SLEEP_DUR );
}
if( err < 0 ) goto error;
}
else
{
while( data->repeatCounter < MAX_REPEATS )
{
/*printf("outTime = %g, note# = %d, repeat# = %d\n", data->outTime,
data->noteCounter, data->repeatCounter );
fflush(stdout); */
Pa_Sleep( SLEEP_DUR );
}
}
if( data->stopMode == MODE_ABORT )
{
printf("Call Pa_AbortStream()\n");
err = Pa_AbortStream( stream );
}
else
{
printf("Call Pa_StopStream()\n");
err = Pa_StopStream( stream );
}
if( err != paNoError ) goto error;
printf("Call Pa_CloseStream()\n"); fflush(stdout);
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,478 @@
/** @file patest_stop_playout.c
@ingroup test_src
@brief Test whether all queued samples are played when Pa_StopStream()
is used with a callback or read/write stream, or when the callback
returns paComplete.
@author Ross Bencina <rossb@audiomulch.com>
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com/
* Copyright (c) 1999-2004 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (1024)
#define TONE_SECONDS (1) /* long tone */
#define TONE_FADE_SECONDS (.04) /* fades at start and end of long tone */
#define GAP_SECONDS (.25) /* gap between long tone and blip */
#define BLIP_SECONDS (.035) /* short blip */
#define NUM_REPEATS (3)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (2048)
typedef struct
{
float sine[TABLE_SIZE+1];
int repeatCount;
double phase;
double lowIncrement, highIncrement;
int gap1Length, toneLength, toneFadesLength, gap2Length, blipLength;
int gap1Countdown, toneCountdown, gap2Countdown, blipCountdown;
}
TestData;
static void RetriggerTestSignalGenerator( TestData *data )
{
data->phase = 0.;
data->gap1Countdown = data->gap1Length;
data->toneCountdown = data->toneLength;
data->gap2Countdown = data->gap2Length;
data->blipCountdown = data->blipLength;
}
static void ResetTestSignalGenerator( TestData *data )
{
data->repeatCount = 0;
RetriggerTestSignalGenerator( data );
}
static void InitTestSignalGenerator( TestData *data )
{
int signalLengthModBufferLength, i;
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data->sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data->sine[TABLE_SIZE] = data->sine[0]; /* guard point for linear interpolation */
data->lowIncrement = (330. / SAMPLE_RATE) * TABLE_SIZE;
data->highIncrement = (1760. / SAMPLE_RATE) * TABLE_SIZE;
data->gap1Length = GAP_SECONDS * SAMPLE_RATE;
data->toneLength = TONE_SECONDS * SAMPLE_RATE;
data->toneFadesLength = TONE_FADE_SECONDS * SAMPLE_RATE;
data->gap2Length = GAP_SECONDS * SAMPLE_RATE;
data->blipLength = BLIP_SECONDS * SAMPLE_RATE;
/* adjust signal length to be a multiple of the buffer length */
signalLengthModBufferLength = (data->gap1Length + data->toneLength + data->gap2Length + data->blipLength) % FRAMES_PER_BUFFER;
if( signalLengthModBufferLength > 0 )
data->toneLength += signalLengthModBufferLength;
ResetTestSignalGenerator( data );
}
#define MIN( a, b ) (((a)<(b))?(a):(b))
static void GenerateTestSignal( TestData *data, float *stereo, int frameCount )
{
int framesGenerated = 0;
float output;
long index;
float fraction;
int count, i;
while( framesGenerated < frameCount && data->repeatCount < NUM_REPEATS )
{
if( framesGenerated < frameCount && data->gap1Countdown > 0 ){
count = MIN( frameCount - framesGenerated, data->gap1Countdown );
for( i=0; i < count; ++i )
{
*stereo++ = 0.f;
*stereo++ = 0.f;
}
data->gap1Countdown -= count;
framesGenerated += count;
}
if( framesGenerated < frameCount && data->toneCountdown > 0 ){
count = MIN( frameCount - framesGenerated, data->toneCountdown );
for( i=0; i < count; ++i )
{
/* tone with data->lowIncrement phase increment */
index = (long)data->phase;
fraction = data->phase - index;
output = data->sine[ index ] + (data->sine[ index + 1 ] - data->sine[ index ]) * fraction;
data->phase += data->lowIncrement;
while( data->phase >= TABLE_SIZE )
data->phase -= TABLE_SIZE;
/* apply fade to ends */
if( data->toneCountdown < data->toneFadesLength )
{
/* cosine-bell fade out at end */
output *= (-cos(((float)data->toneCountdown / (float)data->toneFadesLength) * M_PI) + 1.) * .5;
}
else if( data->toneCountdown > data->toneLength - data->toneFadesLength )
{
/* cosine-bell fade in at start */
output *= (cos(((float)(data->toneCountdown - (data->toneLength - data->toneFadesLength)) / (float)data->toneFadesLength) * M_PI) + 1.) * .5;
}
output *= .5; /* play tone half as loud as blip */
*stereo++ = output;
*stereo++ = output;
data->toneCountdown--;
}
framesGenerated += count;
}
if( framesGenerated < frameCount && data->gap2Countdown > 0 ){
count = MIN( frameCount - framesGenerated, data->gap2Countdown );
for( i=0; i < count; ++i )
{
*stereo++ = 0.f;
*stereo++ = 0.f;
}
data->gap2Countdown -= count;
framesGenerated += count;
}
if( framesGenerated < frameCount && data->blipCountdown > 0 ){
count = MIN( frameCount - framesGenerated, data->blipCountdown );
for( i=0; i < count; ++i )
{
/* tone with data->highIncrement phase increment */
index = (long)data->phase;
fraction = data->phase - index;
output = data->sine[ index ] + (data->sine[ index + 1 ] - data->sine[ index ]) * fraction;
data->phase += data->highIncrement;
while( data->phase >= TABLE_SIZE )
data->phase -= TABLE_SIZE;
/* cosine-bell envelope over whole blip */
output *= (-cos( ((float)data->blipCountdown / (float)data->blipLength) * 2. * M_PI) + 1.) * .5;
*stereo++ = output;
*stereo++ = output;
data->blipCountdown--;
}
framesGenerated += count;
}
if( data->blipCountdown == 0 )
{
RetriggerTestSignalGenerator( data );
data->repeatCount++;
}
}
if( framesGenerated < frameCount )
{
count = frameCount - framesGenerated;
for( i=0; i < count; ++i )
{
*stereo++ = 0.f;
*stereo++ = 0.f;
}
}
}
static int IsTestSignalFinished( TestData *data )
{
if( data->repeatCount >= NUM_REPEATS )
return 1;
else
return 0;
}
static int TestCallback1( const void *inputBuffer, void *outputBuffer,
unsigned long frameCount,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
(void) inputBuffer; /* Prevent unused variable warnings. */
(void) timeInfo;
(void) statusFlags;
GenerateTestSignal( (TestData*)userData, (float*)outputBuffer, frameCount );
if( IsTestSignalFinished( (TestData*)userData ) )
return paComplete;
else
return paContinue;
}
volatile int testCallback2Finished = 0;
static int TestCallback2( const void *inputBuffer, void *outputBuffer,
unsigned long frameCount,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
(void) inputBuffer; /* Prevent unused variable warnings. */
(void) timeInfo;
(void) statusFlags;
GenerateTestSignal( (TestData*)userData, (float*)outputBuffer, frameCount );
if( IsTestSignalFinished( (TestData*)userData ) )
testCallback2Finished = 1;
return paContinue;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
TestData data;
float writeBuffer[ FRAMES_PER_BUFFER * 2 ];
printf("PortAudio Test: check that stopping stream plays out all queued samples. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
InitTestSignalGenerator( &data );
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
/* test paComplete ---------------------------------------------------------- */
ResetTestSignalGenerator( &data );
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
TestCallback1,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("\nPlaying 'tone-blip' %d times using callback, stops by returning paComplete from callback.\n", NUM_REPEATS );
printf("If final blip is not intact, callback+paComplete implementation may be faulty.\n\n" );
while( (err = Pa_IsStreamActive( stream )) == 1 )
Pa_Sleep( 2 );
if( err != 0 ) goto error;
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Sleep( 500 );
/* test paComplete ---------------------------------------------------------- */
ResetTestSignalGenerator( &data );
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
TestCallback1,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("\nPlaying 'tone-blip' %d times using callback, stops by returning paComplete from callback.\n", NUM_REPEATS );
printf("If final blip is not intact or is followed by garbage, callback+paComplete implementation may be faulty.\n\n" );
while( (err = Pa_IsStreamActive( stream )) == 1 )
Pa_Sleep( 5 );
printf("Waiting 5 seconds after paComplete before stopping the stream. Tests that buffers are flushed correctly.\n");
Pa_Sleep( 5000 );
if( err != 0 ) goto error;
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Sleep( 500 );
/* test Pa_StopStream() with callback --------------------------------------- */
ResetTestSignalGenerator( &data );
testCallback2Finished = 0;
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
TestCallback2,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("\nPlaying 'tone-blip' %d times using callback, stops by calling Pa_StopStream.\n", NUM_REPEATS );
printf("If final blip is not intact, callback+Pa_StopStream implementation may be faulty.\n\n" );
/* note that polling a volatile flag is not a good way to synchronise with
the callback, but it's the best we can do portably. */
while( !testCallback2Finished )
Pa_Sleep( 2 );
Pa_Sleep( 500 );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Sleep( 500 );
/* test Pa_StopStream() with Pa_WriteStream --------------------------------- */
ResetTestSignalGenerator( &data );
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
NULL, /* no callback, use blocking API */
NULL ); /* no callback, so no callback userData */
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("\nPlaying 'tone-blip' %d times using Pa_WriteStream, stops by calling Pa_StopStream.\n", NUM_REPEATS );
printf("If final blip is not intact, Pa_WriteStream+Pa_StopStream implementation may be faulty.\n\n" );
do{
GenerateTestSignal( &data, writeBuffer, FRAMES_PER_BUFFER );
err = Pa_WriteStream( stream, writeBuffer, FRAMES_PER_BUFFER );
if( err != paNoError ) goto error;
}while( !IsTestSignalFinished( &data ) );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
/* -------------------------------------------------------------------------- */
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,269 @@
/** @file patest_suggested_vs_streaminfo_latency.c
@ingroup test_src
@brief Print suggested vs. PaStreamInfo reported actual latency
@author Ross Bencina <rossb@audiomulch.com>
Opens streams with a sequence of suggested latency values
from 0 to 2 seconds in .5ms intervals and gathers the resulting actual
latency values. Output a csv file and graph suggested vs. actual. Run
with framesPerBuffer unspecified, powers of 2 and multiples of 50 and
prime number buffer sizes.
*/
/*
* $Id: patest_sine.c 1368 2008-03-01 00:38:27Z rossb $
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "portaudio.h"
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER 2//(128)
#define NUM_CHANNELS (2)
#define SUGGESTED_LATENCY_START_SECONDS (0.0)
#define SUGGESTED_LATENCY_END_SECONDS (2.0)
#define SUGGESTED_LATENCY_INCREMENT_SECONDS (0.0005) /* half a millisecond increments */
/* dummy callback. does nothing. never gets called */
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
return paContinue;
}
/*******************************************************************/
static void usage()
{
int i;
const PaDeviceInfo *deviceInfo;
const char *channelString;
fprintf( stderr, "PortAudio suggested (requested) vs. resulting (reported) stream latency test\n" );
fprintf( stderr, "Usage: x.exe input-device-index output-device-index sample-rate frames-per-buffer\n" );
fprintf( stderr, "Use -1 for default device index, or use one of these:\n" );
for( i=0; i < Pa_GetDeviceCount(); ++i ){
deviceInfo = Pa_GetDeviceInfo(i);
if( deviceInfo->maxInputChannels > 0 && deviceInfo->maxOutputChannels > 0 )
channelString = "full-duplex";
else if( deviceInfo->maxInputChannels > 0 )
channelString = "input only";
else
channelString = "output only";
fprintf( stderr, "%d (%s, %s, %s)\n", i, deviceInfo->name, Pa_GetHostApiInfo(deviceInfo->hostApi)->name, channelString );
}
Pa_Terminate();
exit(-1);
}
int main( int argc, const char* argv[] );
int main( int argc, const char* argv[] )
{
PaStreamParameters inputParameters, outputParameters;
PaStream *stream;
PaError err;
PaTime suggestedLatency;
const PaStreamInfo *streamInfo;
const PaDeviceInfo *deviceInfo;
float sampleRate = SAMPLE_RATE;
int framesPerBuffer = FRAMES_PER_BUFFER;
err = Pa_Initialize();
if( err != paNoError ) goto error;
if( argc > 1 && strcmp(argv[1],"-h") == 0 )
usage();
if( argc > 3 ){
sampleRate = atoi(argv[3]);
}
if( argc > 4 ){
framesPerBuffer = atoi(argv[4]);
}
printf("# sample rate=%f, frames per buffer=%d\n", (float)sampleRate, framesPerBuffer );
inputParameters.device = -1;
if( argc > 1 )
inputParameters.device = atoi(argv[1]);
if( inputParameters.device == -1 ){
inputParameters.device = Pa_GetDefaultInputDevice();
if (inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device available.\n");
goto error;
}
}else{
deviceInfo = Pa_GetDeviceInfo(inputParameters.device);
if( !deviceInfo ){
fprintf(stderr,"Error: Invalid input device index.\n");
usage();
}
if( deviceInfo->maxInputChannels == 0 ){
fprintf(stderr,"Error: Specified input device has no input channels (an output only device?).\n");
usage();
}
}
inputParameters.channelCount = NUM_CHANNELS;
inputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
inputParameters.hostApiSpecificStreamInfo = NULL;
deviceInfo = Pa_GetDeviceInfo(inputParameters.device);
printf( "# using input device id %d (%s, %s)\n", inputParameters.device, deviceInfo->name, Pa_GetHostApiInfo(deviceInfo->hostApi)->name );
outputParameters.device = -1;
if( argc > 2 )
outputParameters.device = atoi(argv[2]);
if( outputParameters.device == -1 ){
outputParameters.device = Pa_GetDefaultOutputDevice();
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device available.\n");
goto error;
}
}else{
deviceInfo = Pa_GetDeviceInfo(outputParameters.device);
if( !deviceInfo ){
fprintf(stderr,"Error: Invalid output device index.\n");
usage();
}
if( deviceInfo->maxOutputChannels == 0 ){
fprintf(stderr,"Error: Specified output device has no output channels (an input only device?).\n");
usage();
}
}
outputParameters.channelCount = NUM_CHANNELS;
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.hostApiSpecificStreamInfo = NULL;
deviceInfo = Pa_GetDeviceInfo(outputParameters.device);
printf( "# using output device id %d (%s, %s)\n", outputParameters.device, deviceInfo->name, Pa_GetHostApiInfo(deviceInfo->hostApi)->name );
printf( "# suggested latency, half duplex PaStreamInfo::outputLatency, half duplex PaStreamInfo::inputLatency, full duplex PaStreamInfo::outputLatency, full duplex PaStreamInfo::inputLatency\n" );
suggestedLatency = SUGGESTED_LATENCY_START_SECONDS;
while( suggestedLatency <= SUGGESTED_LATENCY_END_SECONDS ){
outputParameters.suggestedLatency = suggestedLatency;
inputParameters.suggestedLatency = suggestedLatency;
printf( "%f, ", suggestedLatency );
/* ------------------------------ output ------------------------------ */
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
sampleRate,
framesPerBuffer,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
0 );
if( err != paNoError ) goto error;
streamInfo = Pa_GetStreamInfo( stream );
printf( "%f,", streamInfo->outputLatency );
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
/* ------------------------------ input ------------------------------ */
err = Pa_OpenStream(
&stream,
&inputParameters,
NULL, /* no output */
sampleRate,
framesPerBuffer,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
0 );
if( err != paNoError ) goto error;
streamInfo = Pa_GetStreamInfo( stream );
printf( "%f,", streamInfo->inputLatency );
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
/* ------------------------------ full duplex ------------------------------ */
err = Pa_OpenStream(
&stream,
&inputParameters,
&outputParameters,
sampleRate,
framesPerBuffer,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
0 );
if( err != paNoError ) goto error;
streamInfo = Pa_GetStreamInfo( stream );
printf( "%f,%f", streamInfo->outputLatency, streamInfo->inputLatency );
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
/* ------------------------------------------------------------ */
printf( "\n" );
suggestedLatency += SUGGESTED_LATENCY_INCREMENT_SECONDS;
}
Pa_Terminate();
printf("# Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,150 @@
#!/usr/bin/env python
"""
Run and graph the results of patest_suggested_vs_streaminfo_latency.c
Requires matplotlib for plotting: http://matplotlib.sourceforge.net/
"""
import os
from pylab import *
import numpy
from matplotlib.backends.backend_pdf import PdfPages
testExeName = "PATest.exe" # rename to whatever the compiled patest_suggested_vs_streaminfo_latency.c binary is
dataFileName = "patest_suggested_vs_streaminfo_latency.csv" # code below calls the exe to generate this file
inputDeviceIndex = -1 # -1 means default
outputDeviceIndex = -1 # -1 means default
sampleRate = 44100
pdfFilenameSuffix = "_wmme"
pdfFile = PdfPages("patest_suggested_vs_streaminfo_latency_" + str(sampleRate) + pdfFilenameSuffix +".pdf") #output this pdf file
def loadCsvData( dataFileName ):
params= ""
inputDevice = ""
outputDevice = ""
startLines = file(dataFileName).readlines(1024)
for line in startLines:
if "output device" in line:
outputDevice = line.strip(" \t\n\r#")
if "input device" in line:
inputDevice = line.strip(" \t\n\r#")
params = startLines[0].strip(" \t\n\r#")
data = numpy.loadtxt(dataFileName, delimiter=",", skiprows=4).transpose()
class R(object): pass
result = R()
result.params = params
for s in params.split(','):
if "sample rate" in s:
result.sampleRate = s
result.inputDevice = inputDevice
result.outputDevice = outputDevice
result.suggestedLatency = data[0]
result.halfDuplexOutputLatency = data[1]
result.halfDuplexInputLatency = data[2]
result.fullDuplexOutputLatency = data[3]
result.fullDuplexInputLatency = data[4]
return result;
def setFigureTitleAndAxisLabels( framesPerBufferString ):
title("PortAudio suggested (requested) vs. resulting (reported) stream latency\n" + framesPerBufferString)
ylabel("PaStreamInfo::{input,output}Latency (s)")
xlabel("Pa_OpenStream suggestedLatency (s)")
grid(True)
legend(loc="upper left")
def setDisplayRangeSeconds( maxSeconds ):
xlim(0, maxSeconds)
ylim(0, maxSeconds)
# run the test with different frames per buffer values:
compositeTestFramesPerBufferValues = [0]
# powers of two
for i in range (1,11):
compositeTestFramesPerBufferValues.append( pow(2,i) )
# multiples of 50
for i in range (1,20):
compositeTestFramesPerBufferValues.append( i * 50 )
# 10ms buffer sizes
compositeTestFramesPerBufferValues.append( 441 )
compositeTestFramesPerBufferValues.append( 882 )
# large primes
#compositeTestFramesPerBufferValues.append( 39209 )
#compositeTestFramesPerBufferValues.append( 37537 )
#compositeTestFramesPerBufferValues.append( 26437 )
individualPlotFramesPerBufferValues = [0,64,128,256,512] #output separate plots for these
isFirst = True
for framesPerBuffer in compositeTestFramesPerBufferValues:
commandString = testExeName + " " + str(inputDeviceIndex) + " " + str(outputDeviceIndex) + " " + str(sampleRate) + " " + str(framesPerBuffer) + ' > ' + dataFileName
print commandString
os.system(commandString)
d = loadCsvData(dataFileName)
if isFirst:
figure(1) # title sheet
gcf().text(0.1, 0.0,
"patest_suggested_vs_streaminfo_latency\n%s\n%s\n%s\n"%(d.inputDevice,d.outputDevice,d.sampleRate))
pdfFile.savefig()
figure(2) # composite plot, includes all compositeTestFramesPerBufferValues
if isFirst:
plot( d.suggestedLatency, d.suggestedLatency, label="Suggested latency" )
plot( d.suggestedLatency, d.halfDuplexOutputLatency )
plot( d.suggestedLatency, d.halfDuplexInputLatency )
plot( d.suggestedLatency, d.fullDuplexOutputLatency )
plot( d.suggestedLatency, d.fullDuplexInputLatency )
if framesPerBuffer in individualPlotFramesPerBufferValues: # individual plots
figure( 3 + individualPlotFramesPerBufferValues.index(framesPerBuffer) )
plot( d.suggestedLatency, d.suggestedLatency, label="Suggested latency" )
plot( d.suggestedLatency, d.halfDuplexOutputLatency, label="Half-duplex output latency" )
plot( d.suggestedLatency, d.halfDuplexInputLatency, label="Half-duplex input latency" )
plot( d.suggestedLatency, d.fullDuplexOutputLatency, label="Full-duplex output latency" )
plot( d.suggestedLatency, d.fullDuplexInputLatency, label="Full-duplex input latency" )
if framesPerBuffer == 0:
framesPerBufferText = "paFramesPerBufferUnspecified"
else:
framesPerBufferText = str(framesPerBuffer)
setFigureTitleAndAxisLabels( "user frames per buffer: "+str(framesPerBufferText) )
setDisplayRangeSeconds(2.2)
pdfFile.savefig()
setDisplayRangeSeconds(0.1)
setFigureTitleAndAxisLabels( "user frames per buffer: "+str(framesPerBufferText)+" (detail)" )
pdfFile.savefig()
isFirst = False
figure(2)
setFigureTitleAndAxisLabels( "composite of frames per buffer values:\n"+str(compositeTestFramesPerBufferValues) )
setDisplayRangeSeconds(2.2)
pdfFile.savefig()
setDisplayRangeSeconds(0.1)
setFigureTitleAndAxisLabels( "composite of frames per buffer values:\n"+str(compositeTestFramesPerBufferValues)+" (detail)" )
pdfFile.savefig()
pdfFile.close()
#uncomment this to display interactively, otherwise we just output a pdf
#show()

271
third_party/portaudio/test/patest_sync.c vendored Normal file
View File

@@ -0,0 +1,271 @@
/** @file patest_sync.c
@ingroup test_src
@brief Test time stamping and synchronization of audio and video.
A high latency is used so we can hear the difference in time.
Random durations are used so we know we are hearing the right beep
and not the one before or after.
Sequence of events:
-# Foreground requests a beep.
-# Background randomly schedules a beep.
-# Foreground waits for the beep to be heard based on PaUtil_GetTime().
-# Foreground outputs video (printf) in sync with audio.
-# Repeat.
@author Phil Burk http://www.softsynth.com
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#include "pa_util.h"
#define NUM_BEEPS (6)
#define SAMPLE_RATE (44100)
#define SAMPLE_PERIOD (1.0/44100.0)
#define FRAMES_PER_BUFFER (256)
#define BEEP_DURATION (400)
#define LATENCY_MSEC (2000)
#define SLEEP_MSEC (10)
#define TIMEOUT_MSEC (15000)
#define STATE_BKG_IDLE (0)
#define STATE_BKG_PENDING (1)
#define STATE_BKG_BEEPING (2)
typedef struct
{
float left_phase;
float right_phase;
int state;
volatile int requestBeep; /* Set by foreground, cleared by background. */
PaTime beepTime;
int beepCount;
double latency; /* For debugging. */
}
paTestData;
static unsigned long GenerateRandomNumber( void );
/************************************************************/
/* Calculate pseudo-random 32 bit number based on linear congruential method. */
static unsigned long GenerateRandomNumber( void )
{
static unsigned long randSeed = 99887766; /* Change this for different random sequences. */
randSeed = (randSeed * 196314165) + 907633515;
return randSeed;
}
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo *timeInfo,
PaStreamCallbackFlags statusFlags, void *userData )
{
/* Cast data passed through stream to our structure. */
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned int i;
(void) inputBuffer;
data->latency = timeInfo->outputBufferDacTime - timeInfo->currentTime;
for( i=0; i<framesPerBuffer; i++ )
{
switch( data->state )
{
case STATE_BKG_IDLE:
/* Schedule beep at some random time in the future. */
if( data->requestBeep )
{
int random = GenerateRandomNumber() >> 14;
data->beepTime = timeInfo->outputBufferDacTime + (( (double)(random + SAMPLE_RATE)) * SAMPLE_PERIOD );
data->state = STATE_BKG_PENDING;
}
*out++ = 0.0; /* left */
*out++ = 0.0; /* right */
break;
case STATE_BKG_PENDING:
if( (timeInfo->outputBufferDacTime + (i*SAMPLE_PERIOD)) >= data->beepTime )
{
data->state = STATE_BKG_BEEPING;
data->beepCount = BEEP_DURATION;
data->left_phase = data->right_phase = 0.0;
}
*out++ = 0.0; /* left */
*out++ = 0.0; /* right */
break;
case STATE_BKG_BEEPING:
if( data->beepCount <= 0 )
{
data->state = STATE_BKG_IDLE;
data->requestBeep = 0;
*out++ = 0.0; /* left */
*out++ = 0.0; /* right */
}
else
{
/* Play sawtooth wave. */
*out++ = data->left_phase; /* left */
*out++ = data->right_phase; /* right */
/* Generate simple sawtooth phaser that ranges between -1.0 and 1.0. */
data->left_phase += 0.01f;
/* When signal reaches top, drop back down. */
if( data->left_phase >= 1.0f ) data->left_phase -= 2.0f;
/* higher pitch so we can distinguish left and right. */
data->right_phase += 0.03f;
if( data->right_phase >= 1.0f ) data->right_phase -= 2.0f;
}
data->beepCount -= 1;
break;
default:
data->state = STATE_BKG_IDLE;
break;
}
}
return 0;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStream *stream;
PaError err;
paTestData DATA;
int i, timeout;
PaTime previousTime;
PaStreamParameters outputParameters;
printf("PortAudio Test: you should see BEEP at the same time you hear it.\n");
printf("Wait for a few seconds random delay between BEEPs.\n");
printf("BEEP %d times.\n", NUM_BEEPS );
/* Initialize our DATA for use by callback. */
DATA.left_phase = DATA.right_phase = 0.0;
DATA.state = STATE_BKG_IDLE;
DATA.requestBeep = 0;
/* Initialize library before making any other calls. */
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = Pa_GetDefaultOutputDevice();
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2;
outputParameters.hostApiSpecificStreamInfo = NULL;
outputParameters.sampleFormat = paFloat32;
outputParameters.suggestedLatency = (double)LATENCY_MSEC / 1000;
/* Open an audio I/O stream. */
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER, /* frames per buffer */
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&DATA );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("started\n");
fflush(stdout);
previousTime = Pa_GetStreamTime( stream );
for( i=0; i<NUM_BEEPS; i++ )
{
/* Request a beep from background. */
DATA.requestBeep = 1;
/* Wait for background to acknowledge request. */
timeout = TIMEOUT_MSEC;
while( (DATA.requestBeep == 1) && (timeout-- > 0 ) ) Pa_Sleep(SLEEP_MSEC);
if( timeout <= 0 )
{
fprintf( stderr, "Timed out waiting for background to acknowledge request.\n" );
goto error;
}
printf("calc beep for %9.3f, latency = %6.3f\n", DATA.beepTime, DATA.latency );
fflush(stdout);
/* Wait for scheduled beep time. */
timeout = TIMEOUT_MSEC + (10000/SLEEP_MSEC);
while( (Pa_GetStreamTime( stream ) < DATA.beepTime) && (timeout-- > 0 ) )
{
Pa_Sleep(SLEEP_MSEC);
}
if( timeout <= 0 )
{
fprintf( stderr, "Timed out waiting for time. Now = %9.3f, Beep for %9.3f.\n",
PaUtil_GetTime(), DATA.beepTime );
goto error;
}
/* Beep should be sounding now so print synchronized BEEP. */
printf("hear \"BEEP\" at %9.3f, delta = %9.3f\n",
Pa_GetStreamTime( stream ), (DATA.beepTime - previousTime) );
fflush(stdout);
previousTime = DATA.beepTime;
}
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,173 @@
/** @file patest_timing.c
@ingroup test_src
@brief Play a sine wave for several seconds, and spits out a ton of timing info while it's at it. Based on patest_sine.c
@author Bjorn Roche
@author Ross Bencina <rossb@audiomulch.com>
@author Phil Burk <philburk@softsynth.com>
*/
/*
* $Id: patest_timing.c 578 2003-09-02 04:17:38Z rossbencina $
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define NUM_SECONDS (5)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (64)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
typedef struct
{
PaStream *stream;
PaTime start;
float sine[TABLE_SIZE];
int left_phase;
int right_phase;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i;
(void) timeInfo; /* Prevent unused variable warnings. */
(void) statusFlags;
(void) inputBuffer;
printf( "Timing info given to callback: Adc: %g, Current: %g, Dac: %g\n",
timeInfo->inputBufferAdcTime,
timeInfo->currentTime,
timeInfo->outputBufferDacTime );
printf( "getStreamTime() returns: %g\n", Pa_GetStreamTime(data->stream) - data->start );
for( i=0; i<framesPerBuffer; i++ )
{
*out++ = data->sine[data->left_phase]; /* left */
*out++ = data->sine[data->right_phase]; /* right */
data->left_phase += 1;
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
}
return paContinue;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
paTestData data;
int i;
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data.left_phase = data.right_phase = 0;
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
data.stream = stream;
data.start = Pa_GetStreamTime(stream);
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
data.start = Pa_GetStreamTime(stream);
if( err != paNoError ) goto error;
printf("Play for %d seconds.\n", NUM_SECONDS );
Pa_Sleep( NUM_SECONDS * 1000 );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
printf("The tone should have been heard for about 5 seconds and all the timing info above should report that about 5 seconds elapsed (except Adc, which is undefined since there was no input device opened).\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,200 @@
/** @file patest_toomanysines.c
@ingroup test_src
@brief Play more sine waves than we can handle in real time as a stress test.
@todo This may not be needed now that we have "patest_out_overflow.c".
@author Ross Bencina <rossb@audiomulch.com>
@author Phil Burk <philburk@softsynth.com>
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define MAX_SINES (1000)
#define MAX_LOAD (1.2)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (512)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TWOPI (M_PI * 2.0)
typedef struct paTestData
{
int numSines;
double phases[MAX_SINES];
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i;
int j;
int finished = 0;
(void) inputBuffer; /* Prevent unused variable warning. */
for( i=0; i<framesPerBuffer; i++ )
{
float output = 0.0;
double phaseInc = 0.02;
double phase;
for( j=0; j<data->numSines; j++ )
{
/* Advance phase of next oscillator. */
phase = data->phases[j];
phase += phaseInc;
if( phase > TWOPI ) phase -= TWOPI;
phaseInc *= 1.02;
if( phaseInc > 0.5 ) phaseInc *= 0.5;
/* This is not a very efficient way to calc sines. */
output += (float) sin( phase );
data->phases[j] = phase;
}
*out++ = (float) (output / data->numSines);
}
return finished;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
int numStress;
paTestData data = {0};
double load;
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d. MAX_LOAD = %f\n",
SAMPLE_RATE, FRAMES_PER_BUFFER, MAX_LOAD );
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 1; /* mono output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
/* Determine number of sines required to get to 50% */
do
{ Pa_Sleep( 100 );
load = Pa_GetStreamCpuLoad( stream );
printf("numSines = %d, CPU load = %f\n", data.numSines, load );
if( load < 0.3 )
{
data.numSines += 10;
}
else if( load < 0.4 )
{
data.numSines += 2;
}
else
{
data.numSines += 1;
}
}
while( load < 0.5 );
/* Calculate target stress value then ramp up to that level*/
numStress = (int) (2.0 * data.numSines * MAX_LOAD );
if( numStress > MAX_SINES )
numStress = MAX_SINES;
for( ; data.numSines < numStress; data.numSines+=2 )
{
Pa_Sleep( 200 );
load = Pa_GetStreamCpuLoad( stream );
printf("STRESSING: numSines = %d, CPU load = %f\n", data.numSines, load );
}
printf("Suffer for 5 seconds.\n");
Pa_Sleep( 5000 );
printf("Stop stream.\n");
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,178 @@
/** @file patest_two_rates.c
@ingroup test_src
@brief Play two streams at different rates to make sure they don't interfere.
@author Phil Burk <philburk@softsynth.com>
*/
/*
* $Id$
*
* Author: Phil Burk http://www.softsynth.com
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define OUTPUT_DEVICE (Pa_GetDefaultOutputDeviceID())
#define SAMPLE_RATE_1 (44100)
#define SAMPLE_RATE_2 (48000)
#define FRAMES_PER_BUFFER (256)
#define FREQ_INCR (0.1)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
typedef struct
{
double phase;
int numFrames;
} paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
int frameIndex;
(void) timeInfo; /* Prevent unused variable warnings. */
(void) inputBuffer;
for( frameIndex=0; frameIndex<(int)framesPerBuffer; frameIndex++ )
{
/* Generate sine wave. */
float value = (float) 0.3 * sin(data->phase);
/* Stereo - two channels. */
*out++ = value;
*out++ = value;
data->phase += FREQ_INCR;
if( data->phase >= (2.0 * M_PI) ) data->phase -= (2.0 * M_PI);
}
data->numFrames += 1;
return 0;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaError err;
PaStreamParameters outputParameters;
PaStream *stream1;
PaStream *stream2;
paTestData data1 = {0};
paTestData data2 = {0};
printf("PortAudio Test: two rates.\n" );
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
/* Start first stream. **********************/
err = Pa_OpenStream(
&stream1,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE_1,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data1 );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream1 );
if( err != paNoError ) goto error;
Pa_Sleep( 3 * 1000 );
/* Start second stream. **********************/
err = Pa_OpenStream(
&stream2,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE_2,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data2 );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream2 );
if( err != paNoError ) goto error;
Pa_Sleep( 3 * 1000 );
err = Pa_StopStream( stream2 );
if( err != paNoError ) goto error;
Pa_Sleep( 3 * 1000 );
err = Pa_StopStream( stream1 );
if( err != paNoError ) goto error;
Pa_CloseStream( stream2 );
Pa_CloseStream( stream1 );
Pa_Terminate();
printf("NumFrames = %d on stream1, %d on stream2.\n", data1.numFrames, data2.numFrames );
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,162 @@
/** @file patest_underflow.c
@ingroup test_src
@brief Simulate an output buffer underflow condition.
Tests whether the stream can be stopped when underflowing buffers.
@author Ross Bencina <rossb@audiomulch.com>
@author Phil Burk <philburk@softsynth.com>
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define NUM_SECONDS (20)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (2048)
#define MSEC_PER_BUFFER ( (FRAMES_PER_BUFFER * 1000) / SAMPLE_RATE )
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
typedef struct
{
float sine[TABLE_SIZE];
int left_phase;
int right_phase;
int sleepTime;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i;
int finished = 0;
(void) inputBuffer; /* Prevent unused variable warnings. */
for( i=0; i<framesPerBuffer; i++ )
{
*out++ = data->sine[data->left_phase]; /* left */
*out++ = data->sine[data->right_phase]; /* right */
data->left_phase += 1;
if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
}
/* Cause underflow to occur. */
if( data->sleepTime > 0 ) Pa_Sleep( data->sleepTime );
data->sleepTime += 1;
return finished;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
paTestData data;
int i;
printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data.left_phase = data.right_phase = data.sleepTime = 0;
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
while( data.sleepTime < (2 * MSEC_PER_BUFFER) )
{
printf("SleepTime = %d\n", data.sleepTime );
Pa_Sleep( data.sleepTime );
}
printf("Try to stop stream.\n");
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,243 @@
/** @file patest_unplug.c
@ingroup test_src
@brief Debug a crash involving unplugging a USB device.
@author Phil Burk http://www.softsynth.com
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <math.h>
#include "portaudio.h"
#define NUM_SECONDS (8)
#define SAMPLE_RATE (44100)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
#define FRAMES_PER_BUFFER (64)
#define MAX_CHANNELS (8)
typedef struct
{
short sine[TABLE_SIZE];
int32_t phases[MAX_CHANNELS];
int32_t numChannels;
int32_t sampsToGo;
}
paTestData;
static int inputCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
int finished = 0;
(void) inputBuffer; /* Prevent "unused variable" warnings. */
(void) outputBuffer; /* Prevent "unused variable" warnings. */
data->sampsToGo -= framesPerBuffer;
if (data->sampsToGo <= 0)
{
data->sampsToGo = 0;
finished = 1;
}
return finished;
}
static int outputCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
short *out = (short*)outputBuffer;
unsigned int i;
int finished = 0;
(void) inputBuffer; /* Prevent "unused variable" warnings. */
for( i=0; i<framesPerBuffer; i++ )
{
for (int channelIndex = 0; channelIndex < data->numChannels; channelIndex++)
{
int phase = data->phases[channelIndex];
*out++ = data->sine[phase];
phase += channelIndex + 2;
if( phase >= TABLE_SIZE ) phase -= TABLE_SIZE;
data->phases[channelIndex] = phase;
}
}
return finished;
}
/*******************************************************************/
int main(int argc, char **args);
int main(int argc, char **args)
{
PaStreamParameters inputParameters;
PaStreamParameters outputParameters;
PaStream *inputStream;
PaStream *outputStream;
const PaDeviceInfo *deviceInfo;
PaError err;
paTestData data;
int i;
int totalSamps;
int inputDevice = -1;
int outputDevice = -1;
printf("Test unplugging a USB device.\n");
if( argc > 1 ) {
inputDevice = outputDevice = atoi( args[1] );
printf("Using device number %d.\n\n", inputDevice );
} else {
printf("Using default device.\n\n" );
}
memset(&data, 0, sizeof(data));
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (short) (32767.0 * sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ));
}
data.numChannels = 2;
data.sampsToGo = totalSamps = NUM_SECONDS * SAMPLE_RATE; /* Play for a few seconds. */
err = Pa_Initialize();
if( err != paNoError ) goto error;
if( inputDevice == -1 )
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
else
inputParameters.device = inputDevice ;
if (inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device.\n");
goto error;
}
if( outputDevice == -1 )
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
else
outputParameters.device = outputDevice ;
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
inputParameters.channelCount = 2;
inputParameters.sampleFormat = paInt16;
deviceInfo = Pa_GetDeviceInfo( inputParameters.device );
if( deviceInfo == NULL )
{
fprintf( stderr, "No matching input device.\n" );
goto error;
}
inputParameters.suggestedLatency = deviceInfo->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&inputStream,
&inputParameters,
NULL,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
0,
inputCallback,
&data );
if( err != paNoError ) goto error;
outputParameters.channelCount = 2;
outputParameters.sampleFormat = paInt16;
deviceInfo = Pa_GetDeviceInfo( outputParameters.device );
if( deviceInfo == NULL )
{
fprintf( stderr, "No matching output device.\n" );
goto error;
}
outputParameters.suggestedLatency = deviceInfo->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
err = Pa_OpenStream(
&outputStream,
NULL,
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
(paClipOff | paDitherOff),
outputCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( inputStream );
if( err != paNoError ) goto error;
err = Pa_StartStream( outputStream );
if( err != paNoError ) goto error;
printf("When you hear sound, unplug the USB device.\n");
do
{
Pa_Sleep(500);
printf("Frames remaining = %d\n", data.sampsToGo);
printf("Pa_IsStreamActive(inputStream) = %d\n", Pa_IsStreamActive(inputStream));
printf("Pa_IsStreamActive(outputStream) = %d\n", Pa_IsStreamActive(outputStream));
} while( Pa_IsStreamActive(inputStream) && Pa_IsStreamActive(outputStream) );
err = Pa_CloseStream( inputStream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( outputStream );
if( err != paNoError ) goto error;
Pa_Terminate();
return paNoError;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
fprintf( stderr, "Host Error message: %s\n", Pa_GetLastHostErrorInfo()->errorText );
return err;
}

331
third_party/portaudio/test/patest_wire.c vendored Normal file
View File

@@ -0,0 +1,331 @@
/** @file patest_wire.c
@ingroup test_src
@brief Pass input directly to output.
Note that some HW devices, for example many ISA audio cards
on PCs, do NOT support full duplex! For a PC, you normally need
a PCI based audio card such as the SBLive.
@author Phil Burk http://www.softsynth.com
While adapting to V19-API, I excluded configs with framesPerCallback=0
because of an assert in file pa_common/pa_process.c. Pieter, Oct 9, 2003.
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define SAMPLE_RATE (44100)
typedef struct WireConfig_s
{
int isInputInterleaved;
int isOutputInterleaved;
int numInputChannels;
int numOutputChannels;
int framesPerCallback;
/* count status flags */
int numInputUnderflows;
int numInputOverflows;
int numOutputUnderflows;
int numOutputOverflows;
int numPrimingOutputs;
int numCallbacks;
} WireConfig_t;
#define USE_FLOAT_INPUT (1)
#define USE_FLOAT_OUTPUT (1)
/* Latencies set to defaults. */
#if USE_FLOAT_INPUT
#define INPUT_FORMAT paFloat32
typedef float INPUT_SAMPLE;
#else
#define INPUT_FORMAT paInt16
typedef short INPUT_SAMPLE;
#endif
#if USE_FLOAT_OUTPUT
#define OUTPUT_FORMAT paFloat32
typedef float OUTPUT_SAMPLE;
#else
#define OUTPUT_FORMAT paInt16
typedef short OUTPUT_SAMPLE;
#endif
double gInOutScaler = 1.0;
#define CONVERT_IN_TO_OUT(in) ((OUTPUT_SAMPLE) ((in) * gInOutScaler))
#define INPUT_DEVICE (Pa_GetDefaultInputDevice())
#define OUTPUT_DEVICE (Pa_GetDefaultOutputDevice())
static PaError TestConfiguration( WireConfig_t *config );
static int wireCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData );
/* This routine will be called by the PortAudio engine when audio is needed.
** It may be called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int wireCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
INPUT_SAMPLE *in;
OUTPUT_SAMPLE *out;
int inStride;
int outStride;
int inDone = 0;
int outDone = 0;
WireConfig_t *config = (WireConfig_t *) userData;
unsigned int i;
int inChannel, outChannel;
/* This may get called with NULL inputBuffer during initial setup. */
if( inputBuffer == NULL) return 0;
/* Count flags */
if( (statusFlags & paInputUnderflow) != 0 ) config->numInputUnderflows += 1;
if( (statusFlags & paInputOverflow) != 0 ) config->numInputOverflows += 1;
if( (statusFlags & paOutputUnderflow) != 0 ) config->numOutputUnderflows += 1;
if( (statusFlags & paOutputOverflow) != 0 ) config->numOutputOverflows += 1;
if( (statusFlags & paPrimingOutput) != 0 ) config->numPrimingOutputs += 1;
config->numCallbacks += 1;
inChannel=0, outChannel=0;
while( !(inDone && outDone) )
{
if( config->isInputInterleaved )
{
in = ((INPUT_SAMPLE*)inputBuffer) + inChannel;
inStride = config->numInputChannels;
}
else
{
in = ((INPUT_SAMPLE**)inputBuffer)[inChannel];
inStride = 1;
}
if( config->isOutputInterleaved )
{
out = ((OUTPUT_SAMPLE*)outputBuffer) + outChannel;
outStride = config->numOutputChannels;
}
else
{
out = ((OUTPUT_SAMPLE**)outputBuffer)[outChannel];
outStride = 1;
}
for( i=0; i<framesPerBuffer; i++ )
{
*out = CONVERT_IN_TO_OUT( *in );
out += outStride;
in += inStride;
}
if(inChannel < (config->numInputChannels - 1)) inChannel++;
else inDone = 1;
if(outChannel < (config->numOutputChannels - 1)) outChannel++;
else outDone = 1;
}
return 0;
}
/*******************************************************************/
int main(void);
int main(void)
{
PaError err = paNoError;
WireConfig_t CONFIG;
WireConfig_t *config = &CONFIG;
int configIndex = 0;;
err = Pa_Initialize();
if( err != paNoError ) goto error;
printf("Please connect audio signal to input and listen for it on output!\n");
printf("input format = %lu\n", INPUT_FORMAT );
printf("output format = %lu\n", OUTPUT_FORMAT );
printf("input device ID = %d\n", INPUT_DEVICE );
printf("output device ID = %d\n", OUTPUT_DEVICE );
if( INPUT_FORMAT == OUTPUT_FORMAT )
{
gInOutScaler = 1.0;
}
else if( (INPUT_FORMAT == paInt16) && (OUTPUT_FORMAT == paFloat32) )
{
gInOutScaler = 1.0/32768.0;
}
else if( (INPUT_FORMAT == paFloat32) && (OUTPUT_FORMAT == paInt16) )
{
gInOutScaler = 32768.0;
}
for( config->isInputInterleaved = 0; config->isInputInterleaved < 2; config->isInputInterleaved++ )
{
for( config->isOutputInterleaved = 0; config->isOutputInterleaved < 2; config->isOutputInterleaved++ )
{
for( config->numInputChannels = 1; config->numInputChannels < 3; config->numInputChannels++ )
{
for( config->numOutputChannels = 1; config->numOutputChannels < 3; config->numOutputChannels++ )
{
/* If framesPerCallback = 0, assertion fails in file pa_common/pa_process.c, line 1413: EX. */
for( config->framesPerCallback = 64; config->framesPerCallback < 129; config->framesPerCallback += 64 )
{
printf("-----------------------------------------------\n" );
printf("Configuration #%d\n", configIndex++ );
err = TestConfiguration( config );
/* Give user a chance to bail out. */
if( err == 1 )
{
err = paNoError;
goto done;
}
else if( err != paNoError ) goto error;
}
}
}
}
}
done:
Pa_Terminate();
printf("Full duplex sound test complete.\n"); fflush(stdout);
printf("Hit ENTER to quit.\n"); fflush(stdout);
getchar();
return 0;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
printf("Hit ENTER to quit.\n"); fflush(stdout);
getchar();
return -1;
}
static PaError TestConfiguration( WireConfig_t *config )
{
int c;
PaError err = paNoError;
PaStream *stream;
PaStreamParameters inputParameters, outputParameters;
printf("input %sinterleaved!\n", (config->isInputInterleaved ? " " : "NOT ") );
printf("output %sinterleaved!\n", (config->isOutputInterleaved ? " " : "NOT ") );
printf("input channels = %d\n", config->numInputChannels );
printf("output channels = %d\n", config->numOutputChannels );
printf("framesPerCallback = %d\n", config->framesPerCallback );
inputParameters.device = INPUT_DEVICE; /* default input device */
if (inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device.\n");
goto error;
}
inputParameters.channelCount = config->numInputChannels;
inputParameters.sampleFormat = INPUT_FORMAT | (config->isInputInterleaved ? 0 : paNonInterleaved);
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
outputParameters.device = OUTPUT_DEVICE; /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default output device.\n");
goto error;
}
outputParameters.channelCount = config->numOutputChannels;
outputParameters.sampleFormat = OUTPUT_FORMAT | (config->isOutputInterleaved ? 0 : paNonInterleaved);
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = NULL;
config->numInputUnderflows = 0;
config->numInputOverflows = 0;
config->numOutputUnderflows = 0;
config->numOutputOverflows = 0;
config->numPrimingOutputs = 0;
config->numCallbacks = 0;
err = Pa_OpenStream(
&stream,
&inputParameters,
&outputParameters,
SAMPLE_RATE,
config->framesPerCallback, /* frames per buffer */
paClipOff, /* we won't output out of range samples so don't bother clipping them */
wireCallback,
config );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Now recording and playing. - Hit ENTER for next configuration, or 'q' to quit.\n"); fflush(stdout);
c = getchar();
printf("Closing stream.\n");
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
#define CHECK_FLAG_COUNT(member) \
if( config->member > 0 ) printf("FLAGS SET: " #member " = %d\n", config->member );
CHECK_FLAG_COUNT( numInputUnderflows );
CHECK_FLAG_COUNT( numInputOverflows );
CHECK_FLAG_COUNT( numOutputUnderflows );
CHECK_FLAG_COUNT( numOutputOverflows );
CHECK_FLAG_COUNT( numPrimingOutputs );
printf("number of callbacks = %d\n", config->numCallbacks );
if( c == 'q' ) return 1;
error:
return err;
}

View File

@@ -0,0 +1,517 @@
/*
* $Id: $
* Portable Audio I/O Library
* Windows MME low level buffer user guided parameters search
*
* Copyright (c) 2010 Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <time.h>
#include <math.h>
#define _WIN32_WINNT 0x0501 /* for GetNativeSystemInfo */
#include <windows.h> /* required when using pa_win_wmme.h */
#include <mmsystem.h> /* required when using pa_win_wmme.h */
#include <conio.h> /* for _getch */
#include "portaudio.h"
#include "pa_win_wmme.h"
#define DEFAULT_SAMPLE_RATE (44100.)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (2048)
#define CHANNEL_COUNT (2)
/* search parameters. we test all buffer counts in this range */
#define MIN_WMME_BUFFER_COUNT (2)
#define MAX_WMME_BUFFER_COUNT (12)
/*******************************************************************/
/* functions to query and print Windows version information */
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
LPFN_ISWOW64PROCESS fnIsWow64Process;
static BOOL IsWow64()
{
BOOL bIsWow64 = FALSE;
//IsWow64Process is not available on all supported versions of Windows.
//Use GetModuleHandle to get a handle to the DLL that contains the function
//and GetProcAddress to get a pointer to the function if available.
fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
GetModuleHandle(TEXT("kernel32")),"IsWow64Process" );
if(NULL != fnIsWow64Process)
{
if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
{
//handle error
}
}
return bIsWow64;
}
static void printWindowsVersionInfo( FILE *fp )
{
OSVERSIONINFOEX osVersionInfoEx;
SYSTEM_INFO systemInfo;
const char *osName = "Unknown";
const char *osProductType = "";
const char *processorArchitecture = "Unknown";
memset( &osVersionInfoEx, 0, sizeof(OSVERSIONINFOEX) );
osVersionInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx( &osVersionInfoEx );
if( osVersionInfoEx.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ){
switch( osVersionInfoEx.dwMinorVersion ){
case 0: osName = "Windows 95"; break;
case 10: osName = "Windows 98"; break; // could also be 98SE (I've seen code discriminate based
// on osInfo.Version.Revision.ToString() == "2222A")
case 90: osName = "Windows Me"; break;
}
}else if( osVersionInfoEx.dwPlatformId == VER_PLATFORM_WIN32_NT ){
switch( osVersionInfoEx.dwMajorVersion ){
case 3: osName = "Windows NT 3.51"; break;
case 4: osName = "Windows NT 4.0"; break;
case 5: switch( osVersionInfoEx.dwMinorVersion ){
case 0: osName = "Windows 2000"; break;
case 1: osName = "Windows XP"; break;
case 2:
if( osVersionInfoEx.wSuiteMask & 0x00008000 /*VER_SUITE_WH_SERVER*/ ){
osName = "Windows Home Server";
}else{
if( osVersionInfoEx.wProductType == VER_NT_WORKSTATION ){
osName = "Windows XP Professional x64 Edition (?)";
}else{
if( GetSystemMetrics(/*SM_SERVERR2*/89) == 0 )
osName = "Windows Server 2003";
else
osName = "Windows Server 2003 R2";
}
}break;
}break;
case 6:switch( osVersionInfoEx.dwMinorVersion ){
case 0:
if( osVersionInfoEx.wProductType == VER_NT_WORKSTATION )
osName = "Windows Vista";
else
osName = "Windows Server 2008";
break;
case 1:
if( osVersionInfoEx.wProductType == VER_NT_WORKSTATION )
osName = "Windows 7";
else
osName = "Windows Server 2008 R2";
break;
}break;
}
}
if(osVersionInfoEx.dwMajorVersion == 4)
{
if(osVersionInfoEx.wProductType == VER_NT_WORKSTATION)
osProductType = "Workstation";
else if(osVersionInfoEx.wProductType == VER_NT_SERVER)
osProductType = "Server";
}
else if(osVersionInfoEx.dwMajorVersion == 5)
{
if(osVersionInfoEx.wProductType == VER_NT_WORKSTATION)
{
if((osVersionInfoEx.wSuiteMask & VER_SUITE_PERSONAL) == VER_SUITE_PERSONAL)
osProductType = "Home Edition"; // Windows XP Home Edition
else
osProductType = "Professional"; // Windows XP / Windows 2000 Professional
}
else if(osVersionInfoEx.wProductType == VER_NT_SERVER)
{
if(osVersionInfoEx.dwMinorVersion == 0)
{
if((osVersionInfoEx.wSuiteMask & VER_SUITE_DATACENTER) == VER_SUITE_DATACENTER)
osProductType = "Datacenter Server"; // Windows 2000 Datacenter Server
else if((osVersionInfoEx.wSuiteMask & VER_SUITE_ENTERPRISE) == VER_SUITE_ENTERPRISE)
osProductType = "Advanced Server"; // Windows 2000 Advanced Server
else
osProductType = "Server"; // Windows 2000 Server
}
}
else
{
if((osVersionInfoEx.wSuiteMask & VER_SUITE_DATACENTER) == VER_SUITE_DATACENTER)
osProductType = "Datacenter Edition"; // Windows Server 2003 Datacenter Edition
else if((osVersionInfoEx.wSuiteMask & VER_SUITE_ENTERPRISE) == VER_SUITE_ENTERPRISE)
osProductType = "Enterprise Edition"; // Windows Server 2003 Enterprise Edition
else if((osVersionInfoEx.wSuiteMask & VER_SUITE_BLADE) == VER_SUITE_BLADE)
osProductType = "Web Edition"; // Windows Server 2003 Web Edition
else
osProductType = "Standard Edition"; // Windows Server 2003 Standard Edition
}
}
memset( &systemInfo, 0, sizeof(SYSTEM_INFO) );
GetNativeSystemInfo( &systemInfo );
if( systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL )
processorArchitecture = "x86";
else if( systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 )
processorArchitecture = "x64";
else if( systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 )
processorArchitecture = "Itanium";
fprintf( fp, "OS name and edition: %s %s\n", osName, osProductType );
fprintf( fp, "OS version: %d.%d.%d %S\n",
osVersionInfoEx.dwMajorVersion, osVersionInfoEx.dwMinorVersion,
osVersionInfoEx.dwBuildNumber, osVersionInfoEx.szCSDVersion );
fprintf( fp, "Processor architecture: %s\n", processorArchitecture );
fprintf( fp, "WoW64 process: %s\n", IsWow64() ? "Yes" : "No" );
}
static void printTimeAndDate( FILE *fp )
{
struct tm *local;
time_t t;
t = time(NULL);
local = localtime(&t);
fprintf(fp, "Local time and date: %s", asctime(local));
local = gmtime(&t);
fprintf(fp, "UTC time and date: %s", asctime(local));
}
/*******************************************************************/
typedef struct
{
float sine[TABLE_SIZE];
double phase;
double phaseIncrement;
volatile int fadeIn;
volatile int fadeOut;
double amp;
}
paTestData;
static paTestData data;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i,j;
(void) timeInfo; /* Prevent unused variable warnings. */
(void) statusFlags;
(void) inputBuffer;
for( i=0; i<framesPerBuffer; i++ )
{
float x = data->sine[(int)data->phase];
data->phase += data->phaseIncrement;
if( data->phase >= TABLE_SIZE ){
data->phase -= TABLE_SIZE;
}
x *= data->amp;
if( data->fadeIn ){
data->amp += .001;
if( data->amp >= 1. )
data->fadeIn = 0;
}else if( data->fadeOut ){
if( data->amp > 0 )
data->amp -= .001;
}
for( j = 0; j < CHANNEL_COUNT; ++j ){
*out++ = x;
}
}
if( data->amp > 0 )
return paContinue;
else
return paComplete;
}
#define YES 1
#define NO 0
static int playUntilKeyPress( int deviceIndex, float sampleRate,
int framesPerUserBuffer, int framesPerWmmeBuffer, int wmmeBufferCount )
{
PaStreamParameters outputParameters;
PaWinMmeStreamInfo wmmeStreamInfo;
PaStream *stream;
PaError err;
int c;
outputParameters.device = deviceIndex;
outputParameters.channelCount = CHANNEL_COUNT;
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point processing */
outputParameters.suggestedLatency = 0; /*Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;*/
outputParameters.hostApiSpecificStreamInfo = NULL;
wmmeStreamInfo.size = sizeof(PaWinMmeStreamInfo);
wmmeStreamInfo.hostApiType = paMME;
wmmeStreamInfo.version = 1;
wmmeStreamInfo.flags = paWinMmeUseLowLevelLatencyParameters | paWinMmeDontThrottleOverloadedProcessingThread;
wmmeStreamInfo.framesPerBuffer = framesPerWmmeBuffer;
wmmeStreamInfo.bufferCount = wmmeBufferCount;
outputParameters.hostApiSpecificStreamInfo = &wmmeStreamInfo;
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
sampleRate,
framesPerUserBuffer,
paClipOff | paPrimeOutputBuffersUsingStreamCallback, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
data.amp = 0;
data.fadeIn = 1;
data.fadeOut = 0;
data.phase = 0;
data.phaseIncrement = 15 + ((rand()%100) / 10); // randomise pitch
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
do{
printf( "Trying buffer size %d.\nIf it sounds smooth (without clicks or glitches) press 'y', if it sounds bad press 'n' ('q' to quit)\n", framesPerWmmeBuffer );
c = tolower(_getch());
if( c == 'q' ){
Pa_Terminate();
exit(0);
}
}while( c != 'y' && c != 'n' );
data.fadeOut = 1;
while( Pa_IsStreamActive(stream) == 1 )
Pa_Sleep( 100 );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
return (c == 'y') ? YES : NO;
error:
return err;
}
/*******************************************************************/
static void usage( int wmmeHostApiIndex )
{
int i;
fprintf( stderr, "PortAudio WMME output latency user guided test\n" );
fprintf( stderr, "Usage: x.exe mme-device-index [sampleRate [min-buffer-count max-buffer-count]]\n" );
fprintf( stderr, "Invalid device index. Use one of these:\n" );
for( i=0; i < Pa_GetDeviceCount(); ++i ){
if( Pa_GetDeviceInfo(i)->hostApi == wmmeHostApiIndex && Pa_GetDeviceInfo(i)->maxOutputChannels > 0 )
fprintf( stderr, "%d (%s)\n", i, Pa_GetDeviceInfo(i)->name );
}
Pa_Terminate();
exit(-1);
}
/*
ideas:
o- could be testing with 80% CPU load
o- could test with different channel counts
*/
int main(int argc, char* argv[])
{
PaError err;
int i;
int deviceIndex;
int wmmeBufferCount, wmmeBufferSize, smallestWorkingBufferSize;
int smallestWorkingBufferingLatencyFrames;
int min, max, mid;
int testResult;
FILE *resultsFp;
int wmmeHostApiIndex;
const PaHostApiInfo *wmmeHostApiInfo;
double sampleRate = DEFAULT_SAMPLE_RATE;
int wmmeMinBufferCount = MIN_WMME_BUFFER_COUNT;
int wmmeMaxBufferCount = MAX_WMME_BUFFER_COUNT;
err = Pa_Initialize();
if( err != paNoError ) goto error;
wmmeHostApiIndex = Pa_HostApiTypeIdToHostApiIndex( paMME );
wmmeHostApiInfo = Pa_GetHostApiInfo( wmmeHostApiIndex );
if( argc > 5 )
usage(wmmeHostApiIndex);
deviceIndex = wmmeHostApiInfo->defaultOutputDevice;
if( argc >= 2 ){
deviceIndex = -1;
if( sscanf( argv[1], "%d", &deviceIndex ) != 1 )
usage(wmmeHostApiIndex);
if( deviceIndex < 0 || deviceIndex >= Pa_GetDeviceCount() || Pa_GetDeviceInfo(deviceIndex)->hostApi != wmmeHostApiIndex ){
usage(wmmeHostApiIndex);
}
}
printf( "Using device id %d (%s)\n", deviceIndex, Pa_GetDeviceInfo(deviceIndex)->name );
if( argc >= 3 ){
if( sscanf( argv[2], "%lf", &sampleRate ) != 1 )
usage(wmmeHostApiIndex);
}
printf( "Testing with sample rate %f.\n", (float)sampleRate );
if( argc == 4 ){
if( sscanf( argv[3], "%d", &wmmeMinBufferCount ) != 1 )
usage(wmmeHostApiIndex);
wmmeMaxBufferCount = wmmeMinBufferCount;
}
if( argc == 5 ){
if( sscanf( argv[3], "%d", &wmmeMinBufferCount ) != 1 )
usage(wmmeHostApiIndex);
if( sscanf( argv[4], "%d", &wmmeMaxBufferCount ) != 1 )
usage(wmmeHostApiIndex);
}
printf( "Testing buffer counts from %d to %d\n", wmmeMinBufferCount, wmmeMaxBufferCount );
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data.phase = 0;
resultsFp = fopen( "results.txt", "at" );
fprintf( resultsFp, "*** WMME smallest working output buffer sizes\n" );
printTimeAndDate( resultsFp );
printWindowsVersionInfo( resultsFp );
fprintf( resultsFp, "audio device: %s\n", Pa_GetDeviceInfo( deviceIndex )->name );
fflush( resultsFp );
fprintf( resultsFp, "Sample rate: %f\n", (float)sampleRate );
fprintf( resultsFp, "Buffer count, Smallest working buffer size (frames), Smallest working buffering latency (frames), Smallest working buffering latency (Seconds)\n" );
for( wmmeBufferCount = wmmeMinBufferCount; wmmeBufferCount <= wmmeMaxBufferCount; ++wmmeBufferCount ){
printf( "Test %d of %d\n", (wmmeBufferCount - wmmeMinBufferCount) + 1, (wmmeMaxBufferCount-wmmeMinBufferCount) + 1 );
printf( "Testing with %d buffers...\n", wmmeBufferCount );
/*
Binary search after Niklaus Wirth
from http://en.wikipedia.org/wiki/Binary_search_algorithm#The_algorithm
*/
min = 1;
max = (int)((sampleRate * .3) / (wmmeBufferCount-1)); //8192; /* we assume that this size works 300ms */
smallestWorkingBufferSize = 0;
do{
mid = min + ((max - min) / 2);
wmmeBufferSize = mid;
testResult = playUntilKeyPress( deviceIndex, sampleRate, wmmeBufferSize, wmmeBufferSize, wmmeBufferCount );
if( testResult == YES ){
max = mid - 1;
smallestWorkingBufferSize = wmmeBufferSize;
}else{
min = mid + 1;
}
}while( (min <= max) && (testResult == YES || testResult == NO) );
smallestWorkingBufferingLatencyFrames = smallestWorkingBufferSize * (wmmeBufferCount - 1);
printf( "Smallest working buffer size for %d buffers is: %d\n", wmmeBufferCount, smallestWorkingBufferSize );
printf( "Corresponding to buffering latency of %d frames, or %f seconds.\n", smallestWorkingBufferingLatencyFrames, smallestWorkingBufferingLatencyFrames / sampleRate );
fprintf( resultsFp, "%d, %d, %d, %f\n", wmmeBufferCount, smallestWorkingBufferSize, smallestWorkingBufferingLatencyFrames, smallestWorkingBufferingLatencyFrames / sampleRate );
fflush( resultsFp );
}
fprintf( resultsFp, "###\n" );
fclose( resultsFp );
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,191 @@
/*
* $Id: $
* Portable Audio I/O Library
* Windows MME low level buffer parameters test
*
* Copyright (c) 2007 Ross Bencina
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include <windows.h> /* required when using pa_win_wmme.h */
#include <mmsystem.h> /* required when using pa_win_wmme.h */
#include "portaudio.h"
#include "pa_win_wmme.h"
#define NUM_SECONDS (6)
#define SAMPLE_RATE (44100)
#define WMME_FRAMES_PER_BUFFER (440)
#define WMME_BUFFER_COUNT (6)
#define FRAMES_PER_BUFFER WMME_FRAMES_PER_BUFFER /* hardwire portaudio callback buffer size to WMME buffer size for this test */
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (2048)
#define CHANNEL_COUNT (2)
typedef struct
{
float sine[TABLE_SIZE];
double phase;
}
paTestData;
/* This routine will be called by the PortAudio engine when audio is needed.
** It may called at interrupt level on some machines so don't do anything
** that could mess up the system like calling malloc() or free().
*/
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned long i,j;
(void) timeInfo; /* Prevent unused variable warnings. */
(void) statusFlags;
(void) inputBuffer;
for( i=0; i<framesPerBuffer; i++ )
{
float x = data->sine[(int)data->phase];
data->phase += 20;
if( data->phase >= TABLE_SIZE ){
data->phase -= TABLE_SIZE;
}
for( j = 0; j < CHANNEL_COUNT; ++j ){
*out++ = x;
}
}
return paContinue;
}
/*******************************************************************/
int main(int argc, char* argv[])
{
PaStreamParameters outputParameters;
PaWinMmeStreamInfo wmmeStreamInfo;
PaStream *stream;
PaError err;
paTestData data;
int i;
int deviceIndex;
printf("PortAudio Test: output a sine blip on each channel. SR = %d, BufSize = %d, Chans = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER, CHANNEL_COUNT);
err = Pa_Initialize();
if( err != paNoError ) goto error;
deviceIndex = Pa_GetHostApiInfo( Pa_HostApiTypeIdToHostApiIndex( paMME ) )->defaultOutputDevice;
if( argc == 2 ){
sscanf( argv[1], "%d", &deviceIndex );
}
printf( "using device id %d (%s)\n", deviceIndex, Pa_GetDeviceInfo(deviceIndex)->name );
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
data.phase = 0;
outputParameters.device = deviceIndex;
outputParameters.channelCount = CHANNEL_COUNT;
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point processing */
outputParameters.suggestedLatency = 0; /*Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;*/
outputParameters.hostApiSpecificStreamInfo = NULL;
wmmeStreamInfo.size = sizeof(PaWinMmeStreamInfo);
wmmeStreamInfo.hostApiType = paMME;
wmmeStreamInfo.version = 1;
wmmeStreamInfo.flags = paWinMmeUseLowLevelLatencyParameters | paWinMmeDontThrottleOverloadedProcessingThread;
wmmeStreamInfo.framesPerBuffer = WMME_FRAMES_PER_BUFFER;
wmmeStreamInfo.bufferCount = WMME_BUFFER_COUNT;
outputParameters.hostApiSpecificStreamInfo = &wmmeStreamInfo;
if( Pa_IsFormatSupported( 0, &outputParameters, SAMPLE_RATE ) == paFormatIsSupported ){
printf( "Pa_IsFormatSupported reports device will support %d channels.\n", CHANNEL_COUNT );
}else{
printf( "Pa_IsFormatSupported reports device will not support %d channels.\n", CHANNEL_COUNT );
}
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
patestCallback,
&data );
if( err != paNoError ) goto error;
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Play for %d seconds.\n", NUM_SECONDS );
Pa_Sleep( NUM_SECONDS * 1000 );
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,165 @@
/** @file patest_write_stop.c
@brief Play a few seconds of silence followed by a few cycles of a sine wave. Tests to make sure that pa_StopStream() completes playback in blocking I/O
@author Bjorn Roche of XO Audio (www.xoaudio.com)
@author Ross Bencina
@author Phil Burk
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <math.h>
#include "portaudio.h"
#define NUM_SECONDS (5)
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (1024)
#ifndef M_PI
#define M_PI (3.14159265)
#endif
#define TABLE_SIZE (200)
int main(void);
int main(void)
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
float buffer[FRAMES_PER_BUFFER][2]; /* stereo output buffer */
float sine[TABLE_SIZE]; /* sine wavetable */
int left_phase = 0;
int right_phase = 0;
int left_inc = 1;
int right_inc = 3; /* higher pitch so we can distinguish left and right. */
int i, j;
int bufferCount;
const int framesBy2 = FRAMES_PER_BUFFER >> 1;
const float framesBy2f = (float) framesBy2 ;
printf( "PortAudio Test: output silence, followed by one buffer of a ramped sine wave. SR = %d, BufSize = %d\n",
SAMPLE_RATE, FRAMES_PER_BUFFER);
/* initialise sinusoidal wavetable */
for( i=0; i<TABLE_SIZE; i++ )
{
sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
}
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency * 5;
outputParameters.hostApiSpecificStreamInfo = NULL;
/* open the stream */
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
NULL, /* no callback, use blocking API */
NULL ); /* no callback, so no callback userData */
if( err != paNoError ) goto error;
/* start the stream */
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
printf("Playing %d seconds of silence followed by one buffer of a ramped sinusoid.\n", NUM_SECONDS );
bufferCount = ((NUM_SECONDS * SAMPLE_RATE) / FRAMES_PER_BUFFER);
/* clear buffer */
for( j=0; j < FRAMES_PER_BUFFER; j++ )
{
buffer[j][0] = 0; /* left */
buffer[j][1] = 0; /* right */
}
/* play the silent buffer a bunch o' times */
for( i=0; i < bufferCount; i++ )
{
err = Pa_WriteStream( stream, buffer, FRAMES_PER_BUFFER );
if( err != paNoError ) goto error;
}
/* play a non-silent buffer once */
for( j=0; j < FRAMES_PER_BUFFER; j++ )
{
float ramp = 1;
if( j < framesBy2 )
ramp = j / framesBy2f;
else
ramp = (FRAMES_PER_BUFFER - j) / framesBy2f ;
buffer[j][0] = sine[left_phase] * ramp; /* left */
buffer[j][1] = sine[right_phase] * ramp; /* right */
left_phase += left_inc;
if( left_phase >= TABLE_SIZE ) left_phase -= TABLE_SIZE;
right_phase += right_inc;
if( right_phase >= TABLE_SIZE ) right_phase -= TABLE_SIZE;
}
err = Pa_WriteStream( stream, buffer, FRAMES_PER_BUFFER );
if( err != paNoError ) goto error;
/* stop stream, close, and terminate */
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}

View File

@@ -0,0 +1,168 @@
/** @file patest_write_stop_threads.c
@brief Call Pa_StopStream() from another thread to see if PortAudio hangs.
@author Bjorn Roche of XO Audio (www.xoaudio.com)
@author Ross Bencina
@author Phil Burk
*/
/*
* $Id$
*
* This program uses the PortAudio Portable Audio Library.
* For more information see: http://www.portaudio.com/
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
* they can be incorporated into the canonical version. It is also
* requested that these non-binding requests be included along with the
* license above.
*/
#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include <memory.h>
/* pthread may only be available on Mac and Linux. */
#include <pthread.h>
#include "portaudio.h"
#define SAMPLE_RATE (44100)
#define FRAMES_PER_BUFFER (2048)
static float s_buffer[FRAMES_PER_BUFFER][2]; /* stereo output buffer */
/**
* WARNING: PortAudio is NOT thread safe. DO NOT call PortAudio
* from multiple threads without synchronization. This test uses
* PA in an ILLEGAL WAY in order to try to flush out potential hang bugs.
* The test calls Pa_WriteStream() and Pa_StopStream() simultaneously
* from separate threads in order to try to cause Pa_StopStream() to hang.
* In the main thread we write to the stream in a loop.
* Then try stopping PA from another thread to see if it hangs.
*
* @note: Do not expect this test to pass. The test is only here
* as a debugging aid for hang bugs. Since this test uses PA in an
* illegal way, it may fail for reasons that are not PA bugs.
*/
/* Wait awhile then abort the stream. */
void *stop_thread_proc(void *arg)
{
PaStream *stream = (PaStream *)arg;
PaTime time;
for (int i = 0; i < 20; i++)
{
/* ILLEGAL unsynchronised call to PA, see comment above */
time = Pa_GetStreamTime( stream );
printf("Stream time = %f\n", time);
fflush(stdout);
usleep(100 * 1000);
}
printf("Call Pa_StopStream()\n");
fflush(stdout);
/* ILLEGAL unsynchronised call to PA, see comment above */
PaError err = Pa_StopStream( stream );
printf("Pa_StopStream() returned %d\n", err);
fflush(stdout);
return stream;
}
int main(void);
int main(void)
{
PaStreamParameters outputParameters;
PaStream *stream;
PaError err;
int result;
pthread_t thread;
printf( "PortAudio Test: output silence and stop from another thread. SR = %d, BufSize = %d\n",
SAMPLE_RATE, FRAMES_PER_BUFFER);
err = Pa_Initialize();
if( err != paNoError ) goto error;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
outputParameters.channelCount = 2; /* stereo output */
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency * 5;
outputParameters.hostApiSpecificStreamInfo = NULL;
/* open the stream */
err = Pa_OpenStream(
&stream,
NULL, /* no input */
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won't output out of range samples so don't bother clipping them */
NULL, /* no callback, use blocking API */
NULL ); /* no callback, so no callback userData */
if( err != paNoError ) goto error;
result = pthread_create(&thread, NULL /* attributes */, stop_thread_proc, stream);
/* start the stream */
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
/* clear buffer */
memset( s_buffer, 0, sizeof(s_buffer) );
/* play the silent buffer many times */
while( Pa_IsStreamActive(stream) > 0 )
{
err = Pa_WriteStream( stream, s_buffer, FRAMES_PER_BUFFER );
printf("Pa_WriteStream returns %d = %s\n", err, Pa_GetErrorText( err ));
if( err != paNoError )
{
err = paNoError;
break;
};
}
printf("Try to join the thread that called Pa_StopStream().\n");
result = pthread_join( thread, NULL );
printf("pthread_join returned %d\n", result);
/* close, and terminate */
printf("Call Pa_CloseStream\n");
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
Pa_Terminate();
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
fprintf( stderr, "An error occurred while using the portaudio stream\n" );
fprintf( stderr, "Error number: %d\n", err );
fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
return err;
}