summaryrefslogtreecommitdiff
path: root/portaudio/test
diff options
context:
space:
mode:
authorsanine <sanine.not@pm.me>2022-08-25 14:54:53 -0500
committersanine <sanine.not@pm.me>2022-08-25 14:54:53 -0500
commit37c97e345d12f95dde44e1d1a4c2f2aadd4615bc (patch)
treee1bb25bc855883062bdd7847ff2c04290f71c840 /portaudio/test
parent5634c7b04da619669f2f29f6798c03982be05180 (diff)
add initial structure
Diffstat (limited to 'portaudio/test')
-rw-r--r--portaudio/test/CMakeLists.txt13
-rw-r--r--portaudio/test/README.txt52
-rw-r--r--portaudio/test/pa_minlat.c205
-rw-r--r--portaudio/test/patest1.c208
-rw-r--r--portaudio/test/patest_buffer.c206
-rw-r--r--portaudio/test/patest_callbackstop.c252
-rw-r--r--portaudio/test/patest_clip.c190
-rw-r--r--portaudio/test/patest_converters.c395
-rw-r--r--portaudio/test/patest_dither.c190
-rw-r--r--portaudio/test/patest_dsound_find_best_latency_params.c513
-rw-r--r--portaudio/test/patest_dsound_low_level_latency_params.c186
-rw-r--r--portaudio/test/patest_dsound_surround.c204
-rw-r--r--portaudio/test/patest_hang.c164
-rw-r--r--portaudio/test/patest_in_overflow.c236
-rw-r--r--portaudio/test/patest_jack_wasapi.c343
-rw-r--r--portaudio/test/patest_latency.c193
-rw-r--r--portaudio/test/patest_leftright.c185
-rw-r--r--portaudio/test/patest_longsine.c151
-rw-r--r--portaudio/test/patest_many.c210
-rw-r--r--portaudio/test/patest_maxsines.c216
-rw-r--r--portaudio/test/patest_mono.c155
-rw-r--r--portaudio/test/patest_multi_sine.c205
-rw-r--r--portaudio/test/patest_out_underflow.c251
-rw-r--r--portaudio/test/patest_prime.c234
-rw-r--r--portaudio/test/patest_read_record.c243
-rw-r--r--portaudio/test/patest_ringmix.c86
-rw-r--r--portaudio/test/patest_sine8.c216
-rw-r--r--portaudio/test/patest_sine_channelmaps.c190
-rw-r--r--portaudio/test/patest_sine_formats.c203
-rw-r--r--portaudio/test/patest_sine_srate.c182
-rw-r--r--portaudio/test/patest_sine_time.c219
-rw-r--r--portaudio/test/patest_start_stop.c174
-rw-r--r--portaudio/test/patest_stop.c324
-rw-r--r--portaudio/test/patest_stop_playout.c478
-rw-r--r--portaudio/test/patest_suggested_vs_streaminfo_latency.c269
-rw-r--r--portaudio/test/patest_suggested_vs_streaminfo_latency.py150
-rw-r--r--portaudio/test/patest_sync.c271
-rw-r--r--portaudio/test/patest_timing.c173
-rw-r--r--portaudio/test/patest_toomanysines.c200
-rw-r--r--portaudio/test/patest_two_rates.c178
-rw-r--r--portaudio/test/patest_underflow.c162
-rw-r--r--portaudio/test/patest_unplug.c243
-rw-r--r--portaudio/test/patest_wire.c331
-rw-r--r--portaudio/test/patest_wmme_find_best_latency_params.c517
-rw-r--r--portaudio/test/patest_wmme_low_level_latency_params.c191
-rw-r--r--portaudio/test/patest_write_stop.c165
-rw-r--r--portaudio/test/patest_write_stop_hang_illegal.c168
47 files changed, 10490 insertions, 0 deletions
diff --git a/portaudio/test/CMakeLists.txt b/portaudio/test/CMakeLists.txt
new file mode 100644
index 0000000..973568f
--- /dev/null
+++ b/portaudio/test/CMakeLists.txt
@@ -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)
diff --git a/portaudio/test/README.txt b/portaudio/test/README.txt
new file mode 100644
index 0000000..7cce15e
--- /dev/null
+++ b/portaudio/test/README.txt
@@ -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.
diff --git a/portaudio/test/pa_minlat.c b/portaudio/test/pa_minlat.c
new file mode 100644
index 0000000..683b2bb
--- /dev/null
+++ b/portaudio/test/pa_minlat.c
@@ -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;
+}
diff --git a/portaudio/test/patest1.c b/portaudio/test/patest1.c
new file mode 100644
index 0000000..25d6e3f
--- /dev/null
+++ b/portaudio/test/patest1.c
@@ -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;
+}
diff --git a/portaudio/test/patest_buffer.c b/portaudio/test/patest_buffer.c
new file mode 100644
index 0000000..d19e121
--- /dev/null
+++ b/portaudio/test/patest_buffer.c
@@ -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;
+}
diff --git a/portaudio/test/patest_callbackstop.c b/portaudio/test/patest_callbackstop.c
new file mode 100644
index 0000000..fba9dca
--- /dev/null
+++ b/portaudio/test/patest_callbackstop.c
@@ -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;
+}
diff --git a/portaudio/test/patest_clip.c b/portaudio/test/patest_clip.c
new file mode 100644
index 0000000..77989f4
--- /dev/null
+++ b/portaudio/test/patest_clip.c
@@ -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;
+}
diff --git a/portaudio/test/patest_converters.c b/portaudio/test/patest_converters.c
new file mode 100644
index 0000000..f76738c
--- /dev/null
+++ b/portaudio/test/patest_converters.c
@@ -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;
+}
diff --git a/portaudio/test/patest_dither.c b/portaudio/test/patest_dither.c
new file mode 100644
index 0000000..fc402dc
--- /dev/null
+++ b/portaudio/test/patest_dither.c
@@ -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. */
+}
diff --git a/portaudio/test/patest_dsound_find_best_latency_params.c b/portaudio/test/patest_dsound_find_best_latency_params.c
new file mode 100644
index 0000000..1c074ab
--- /dev/null
+++ b/portaudio/test/patest_dsound_find_best_latency_params.c
@@ -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;
+}
diff --git a/portaudio/test/patest_dsound_low_level_latency_params.c b/portaudio/test/patest_dsound_low_level_latency_params.c
new file mode 100644
index 0000000..d583e69
--- /dev/null
+++ b/portaudio/test/patest_dsound_low_level_latency_params.c
@@ -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;
+}
diff --git a/portaudio/test/patest_dsound_surround.c b/portaudio/test/patest_dsound_surround.c
new file mode 100644
index 0000000..b7c887d
--- /dev/null
+++ b/portaudio/test/patest_dsound_surround.c
@@ -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;
+}
diff --git a/portaudio/test/patest_hang.c b/portaudio/test/patest_hang.c
new file mode 100644
index 0000000..501b47d
--- /dev/null
+++ b/portaudio/test/patest_hang.c
@@ -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;
+}
diff --git a/portaudio/test/patest_in_overflow.c b/portaudio/test/patest_in_overflow.c
new file mode 100644
index 0000000..31868bd
--- /dev/null
+++ b/portaudio/test/patest_in_overflow.c
@@ -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;
+}
diff --git a/portaudio/test/patest_jack_wasapi.c b/portaudio/test/patest_jack_wasapi.c
new file mode 100644
index 0000000..bd79881
--- /dev/null
+++ b/portaudio/test/patest_jack_wasapi.c
@@ -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;
+}
diff --git a/portaudio/test/patest_latency.c b/portaudio/test/patest_latency.c
new file mode 100644
index 0000000..7f622c1
--- /dev/null
+++ b/portaudio/test/patest_latency.c
@@ -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;
+}
diff --git a/portaudio/test/patest_leftright.c b/portaudio/test/patest_leftright.c
new file mode 100644
index 0000000..e61a351
--- /dev/null
+++ b/portaudio/test/patest_leftright.c
@@ -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;
+}
diff --git a/portaudio/test/patest_longsine.c b/portaudio/test/patest_longsine.c
new file mode 100644
index 0000000..f439030
--- /dev/null
+++ b/portaudio/test/patest_longsine.c
@@ -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;
+}
diff --git a/portaudio/test/patest_many.c b/portaudio/test/patest_many.c
new file mode 100644
index 0000000..76cc043
--- /dev/null
+++ b/portaudio/test/patest_many.c
@@ -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;
+}
diff --git a/portaudio/test/patest_maxsines.c b/portaudio/test/patest_maxsines.c
new file mode 100644
index 0000000..638a01a
--- /dev/null
+++ b/portaudio/test/patest_maxsines.c
@@ -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;
+}
diff --git a/portaudio/test/patest_mono.c b/portaudio/test/patest_mono.c
new file mode 100644
index 0000000..e7d7d1b
--- /dev/null
+++ b/portaudio/test/patest_mono.c
@@ -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;
+}
diff --git a/portaudio/test/patest_multi_sine.c b/portaudio/test/patest_multi_sine.c
new file mode 100644
index 0000000..ec9ed8c
--- /dev/null
+++ b/portaudio/test/patest_multi_sine.c
@@ -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;
+}
diff --git a/portaudio/test/patest_out_underflow.c b/portaudio/test/patest_out_underflow.c
new file mode 100644
index 0000000..a8c45ea
--- /dev/null
+++ b/portaudio/test/patest_out_underflow.c
@@ -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;
+}
diff --git a/portaudio/test/patest_prime.c b/portaudio/test/patest_prime.c
new file mode 100644
index 0000000..e943310
--- /dev/null
+++ b/portaudio/test/patest_prime.c
@@ -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;
+}
diff --git a/portaudio/test/patest_read_record.c b/portaudio/test/patest_read_record.c
new file mode 100644
index 0000000..bd9c7fe
--- /dev/null
+++ b/portaudio/test/patest_read_record.c
@@ -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;
+}
diff --git a/portaudio/test/patest_ringmix.c b/portaudio/test/patest_ringmix.c
new file mode 100644
index 0000000..2db6706
--- /dev/null
+++ b/portaudio/test/patest_ringmix.c
@@ -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;
+}
diff --git a/portaudio/test/patest_sine8.c b/portaudio/test/patest_sine8.c
new file mode 100644
index 0000000..82de69d
--- /dev/null
+++ b/portaudio/test/patest_sine8.c
@@ -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;
+}
diff --git a/portaudio/test/patest_sine_channelmaps.c b/portaudio/test/patest_sine_channelmaps.c
new file mode 100644
index 0000000..3476701
--- /dev/null
+++ b/portaudio/test/patest_sine_channelmaps.c
@@ -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;
+}
diff --git a/portaudio/test/patest_sine_formats.c b/portaudio/test/patest_sine_formats.c
new file mode 100644
index 0000000..3224d6e
--- /dev/null
+++ b/portaudio/test/patest_sine_formats.c
@@ -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;
+}
diff --git a/portaudio/test/patest_sine_srate.c b/portaudio/test/patest_sine_srate.c
new file mode 100644
index 0000000..d4ce81b
--- /dev/null
+++ b/portaudio/test/patest_sine_srate.c
@@ -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;
+}
diff --git a/portaudio/test/patest_sine_time.c b/portaudio/test/patest_sine_time.c
new file mode 100644
index 0000000..c1d6097
--- /dev/null
+++ b/portaudio/test/patest_sine_time.c
@@ -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;
+}
diff --git a/portaudio/test/patest_start_stop.c b/portaudio/test/patest_start_stop.c
new file mode 100644
index 0000000..2470b26
--- /dev/null
+++ b/portaudio/test/patest_start_stop.c
@@ -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;
+}
diff --git a/portaudio/test/patest_stop.c b/portaudio/test/patest_stop.c
new file mode 100644
index 0000000..164ad4e
--- /dev/null
+++ b/portaudio/test/patest_stop.c
@@ -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;
+}
diff --git a/portaudio/test/patest_stop_playout.c b/portaudio/test/patest_stop_playout.c
new file mode 100644
index 0000000..7e6932e
--- /dev/null
+++ b/portaudio/test/patest_stop_playout.c
@@ -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;
+}
diff --git a/portaudio/test/patest_suggested_vs_streaminfo_latency.c b/portaudio/test/patest_suggested_vs_streaminfo_latency.c
new file mode 100644
index 0000000..c26d871
--- /dev/null
+++ b/portaudio/test/patest_suggested_vs_streaminfo_latency.c
@@ -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;
+}
diff --git a/portaudio/test/patest_suggested_vs_streaminfo_latency.py b/portaudio/test/patest_suggested_vs_streaminfo_latency.py
new file mode 100644
index 0000000..8026787
--- /dev/null
+++ b/portaudio/test/patest_suggested_vs_streaminfo_latency.py
@@ -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()
diff --git a/portaudio/test/patest_sync.c b/portaudio/test/patest_sync.c
new file mode 100644
index 0000000..52df0fe
--- /dev/null
+++ b/portaudio/test/patest_sync.c
@@ -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;
+}
diff --git a/portaudio/test/patest_timing.c b/portaudio/test/patest_timing.c
new file mode 100644
index 0000000..2a240b4
--- /dev/null
+++ b/portaudio/test/patest_timing.c
@@ -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;
+}
diff --git a/portaudio/test/patest_toomanysines.c b/portaudio/test/patest_toomanysines.c
new file mode 100644
index 0000000..2d32071
--- /dev/null
+++ b/portaudio/test/patest_toomanysines.c
@@ -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;
+}
diff --git a/portaudio/test/patest_two_rates.c b/portaudio/test/patest_two_rates.c
new file mode 100644
index 0000000..2116b1e
--- /dev/null
+++ b/portaudio/test/patest_two_rates.c
@@ -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;
+}
diff --git a/portaudio/test/patest_underflow.c b/portaudio/test/patest_underflow.c
new file mode 100644
index 0000000..96216a6
--- /dev/null
+++ b/portaudio/test/patest_underflow.c
@@ -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;
+}
diff --git a/portaudio/test/patest_unplug.c b/portaudio/test/patest_unplug.c
new file mode 100644
index 0000000..0e4486e
--- /dev/null
+++ b/portaudio/test/patest_unplug.c
@@ -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;
+}
diff --git a/portaudio/test/patest_wire.c b/portaudio/test/patest_wire.c
new file mode 100644
index 0000000..f04e6be
--- /dev/null
+++ b/portaudio/test/patest_wire.c
@@ -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;
+}
diff --git a/portaudio/test/patest_wmme_find_best_latency_params.c b/portaudio/test/patest_wmme_find_best_latency_params.c
new file mode 100644
index 0000000..5c715f9
--- /dev/null
+++ b/portaudio/test/patest_wmme_find_best_latency_params.c
@@ -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;
+}
diff --git a/portaudio/test/patest_wmme_low_level_latency_params.c b/portaudio/test/patest_wmme_low_level_latency_params.c
new file mode 100644
index 0000000..31c8892
--- /dev/null
+++ b/portaudio/test/patest_wmme_low_level_latency_params.c
@@ -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;
+}
diff --git a/portaudio/test/patest_write_stop.c b/portaudio/test/patest_write_stop.c
new file mode 100644
index 0000000..855923f
--- /dev/null
+++ b/portaudio/test/patest_write_stop.c
@@ -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;
+}
diff --git a/portaudio/test/patest_write_stop_hang_illegal.c b/portaudio/test/patest_write_stop_hang_illegal.c
new file mode 100644
index 0000000..3d53d4f
--- /dev/null
+++ b/portaudio/test/patest_write_stop_hang_illegal.c
@@ -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;
+}