annotate src/portaudio_20161030_catalina_patch/test/patest_stop.c @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents 4edcd14160a5
children
rev   line source
Chris@4 1 /** @file patest_stop.c
Chris@4 2 @ingroup test_src
Chris@4 3 @brief Test different ways of stopping audio.
Chris@4 4
Chris@4 5 Test the three ways of stopping audio:
Chris@4 6 - calling Pa_StopStream(),
Chris@4 7 - calling Pa_AbortStream(),
Chris@4 8 - and returning a 1 from the callback function.
Chris@4 9
Chris@4 10 A long latency is set up so that you can hear the difference.
Chris@4 11 Then a simple 8 note sequence is repeated twice.
Chris@4 12 The program will print what you should hear.
Chris@4 13
Chris@4 14 @author Phil Burk <philburk@softsynth.com>
Chris@4 15 */
Chris@4 16 /*
Chris@55 17 * $Id$
Chris@4 18 *
Chris@4 19 * This program uses the PortAudio Portable Audio Library.
Chris@4 20 * For more information see: http://www.portaudio.com
Chris@4 21 * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
Chris@4 22 *
Chris@4 23 * Permission is hereby granted, free of charge, to any person obtaining
Chris@4 24 * a copy of this software and associated documentation files
Chris@4 25 * (the "Software"), to deal in the Software without restriction,
Chris@4 26 * including without limitation the rights to use, copy, modify, merge,
Chris@4 27 * publish, distribute, sublicense, and/or sell copies of the Software,
Chris@4 28 * and to permit persons to whom the Software is furnished to do so,
Chris@4 29 * subject to the following conditions:
Chris@4 30 *
Chris@4 31 * The above copyright notice and this permission notice shall be
Chris@4 32 * included in all copies or substantial portions of the Software.
Chris@4 33 *
Chris@4 34 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Chris@4 35 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Chris@4 36 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
Chris@4 37 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
Chris@4 38 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
Chris@4 39 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
Chris@4 40 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Chris@4 41 */
Chris@4 42
Chris@4 43 /*
Chris@4 44 * The text above constitutes the entire PortAudio license; however,
Chris@4 45 * the PortAudio community also makes the following non-binding requests:
Chris@4 46 *
Chris@4 47 * Any person wishing to distribute modifications to the Software is
Chris@4 48 * requested to send the modifications to the original developer so that
Chris@4 49 * they can be incorporated into the canonical version. It is also
Chris@4 50 * requested that these non-binding requests be included along with the
Chris@4 51 * license above.
Chris@4 52 */
Chris@4 53 #include <stdio.h>
Chris@4 54 #include <math.h>
Chris@4 55 #include "portaudio.h"
Chris@4 56
Chris@4 57 #define OUTPUT_DEVICE (Pa_GetDefaultOutputDevice())
Chris@4 58 #define SLEEP_DUR (200)
Chris@4 59 #define SAMPLE_RATE (44100)
Chris@4 60 #define FRAMES_PER_BUFFER (256)
Chris@4 61 #define LATENCY_SECONDS (3.f)
Chris@4 62 #define FRAMES_PER_NOTE (SAMPLE_RATE/2)
Chris@4 63 #define MAX_REPEATS (2)
Chris@4 64 #define FUNDAMENTAL (400.0f / SAMPLE_RATE)
Chris@4 65 #define NOTE_0 (FUNDAMENTAL * 1.0f / 1.0f)
Chris@4 66 #define NOTE_1 (FUNDAMENTAL * 5.0f / 4.0f)
Chris@4 67 #define NOTE_2 (FUNDAMENTAL * 4.0f / 3.0f)
Chris@4 68 #define NOTE_3 (FUNDAMENTAL * 3.0f / 2.0f)
Chris@4 69 #define NOTE_4 (FUNDAMENTAL * 2.0f / 1.0f)
Chris@4 70 #define MODE_FINISH (0)
Chris@4 71 #define MODE_STOP (1)
Chris@4 72 #define MODE_ABORT (2)
Chris@4 73 #ifndef M_PI
Chris@4 74 #define M_PI (3.14159265)
Chris@4 75 #endif
Chris@4 76 #define TABLE_SIZE (400)
Chris@4 77
Chris@4 78 typedef struct
Chris@4 79 {
Chris@4 80 float waveform[TABLE_SIZE + 1]; /* Add one for guard point for interpolation. */
Chris@4 81 float phase_increment;
Chris@4 82 float phase;
Chris@4 83 float *tune;
Chris@4 84 int notesPerTune;
Chris@4 85 int frameCounter;
Chris@4 86 int noteCounter;
Chris@4 87 int repeatCounter;
Chris@4 88 PaTime outTime;
Chris@4 89 int stopMode;
Chris@4 90 int done;
Chris@4 91 }
Chris@4 92 paTestData;
Chris@4 93
Chris@4 94 /************* Prototypes *****************************/
Chris@4 95 int TestStopMode( paTestData *data );
Chris@4 96 float LookupWaveform( paTestData *data, float phase );
Chris@4 97
Chris@4 98 /******************************************************
Chris@4 99 * Convert phase between 0.0 and 1.0 to waveform value
Chris@4 100 * using linear interpolation.
Chris@4 101 */
Chris@4 102 float LookupWaveform( paTestData *data, float phase )
Chris@4 103 {
Chris@4 104 float fIndex = phase*TABLE_SIZE;
Chris@4 105 int index = (int) fIndex;
Chris@4 106 float fract = fIndex - index;
Chris@4 107 float lo = data->waveform[index];
Chris@4 108 float hi = data->waveform[index+1];
Chris@4 109 float val = lo + fract*(hi-lo);
Chris@4 110 return val;
Chris@4 111 }
Chris@4 112
Chris@4 113 /* This routine will be called by the PortAudio engine when audio is needed.
Chris@4 114 ** It may called at interrupt level on some machines so don't do anything
Chris@4 115 ** that could mess up the system like calling malloc() or free().
Chris@4 116 */
Chris@4 117 static int patestCallback( const void *inputBuffer, void *outputBuffer,
Chris@4 118 unsigned long framesPerBuffer,
Chris@4 119 const PaStreamCallbackTimeInfo* timeInfo,
Chris@4 120 PaStreamCallbackFlags statusFlags,
Chris@4 121 void *userData )
Chris@4 122 {
Chris@4 123 paTestData *data = (paTestData*)userData;
Chris@4 124 float *out = (float*)outputBuffer;
Chris@4 125 float value;
Chris@4 126 unsigned int i = 0;
Chris@4 127 int finished = paContinue;
Chris@4 128
Chris@4 129 (void) inputBuffer; /* Prevent unused variable warnings. */
Chris@4 130 (void) timeInfo;
Chris@4 131 (void) statusFlags;
Chris@4 132
Chris@4 133
Chris@4 134 /* data->outTime = outTime; */
Chris@4 135
Chris@4 136 if( !data->done )
Chris@4 137 {
Chris@4 138 for( i=0; i<framesPerBuffer; i++ )
Chris@4 139 {
Chris@4 140 /* Are we done with this note? */
Chris@4 141 if( data->frameCounter >= FRAMES_PER_NOTE )
Chris@4 142 {
Chris@4 143 data->noteCounter += 1;
Chris@4 144 data->frameCounter = 0;
Chris@4 145 /* Are we done with this tune? */
Chris@4 146 if( data->noteCounter >= data->notesPerTune )
Chris@4 147 {
Chris@4 148 data->noteCounter = 0;
Chris@4 149 data->repeatCounter += 1;
Chris@4 150 /* Are we totally done? */
Chris@4 151 if( data->repeatCounter >= MAX_REPEATS )
Chris@4 152 {
Chris@4 153 data->done = 1;
Chris@4 154 if( data->stopMode == MODE_FINISH )
Chris@4 155 {
Chris@4 156 finished = paComplete;
Chris@4 157 break;
Chris@4 158 }
Chris@4 159 }
Chris@4 160 }
Chris@4 161 data->phase_increment = data->tune[data->noteCounter];
Chris@4 162 }
Chris@4 163 value = LookupWaveform(data, data->phase);
Chris@4 164 *out++ = value; /* left */
Chris@4 165 *out++ = value; /* right */
Chris@4 166 data->phase += data->phase_increment;
Chris@4 167 if( data->phase >= 1.0f ) data->phase -= 1.0f;
Chris@4 168
Chris@4 169 data->frameCounter += 1;
Chris@4 170 }
Chris@4 171 }
Chris@4 172 /* zero remainder of final buffer */
Chris@4 173 for( ; i<framesPerBuffer; i++ )
Chris@4 174 {
Chris@4 175 *out++ = 0; /* left */
Chris@4 176 *out++ = 0; /* right */
Chris@4 177 }
Chris@4 178 return finished;
Chris@4 179 }
Chris@4 180 /*******************************************************************/
Chris@4 181 int main(void);
Chris@4 182 int main(void)
Chris@4 183 {
Chris@4 184 paTestData data;
Chris@4 185 int i;
Chris@4 186 float simpleTune[] = { NOTE_0, NOTE_1, NOTE_2, NOTE_3, NOTE_4, NOTE_3, NOTE_2, NOTE_1 };
Chris@4 187
Chris@4 188 printf("PortAudio Test: play song and test stopping. ask for %f seconds latency\n", LATENCY_SECONDS );
Chris@4 189 /* initialise sinusoidal wavetable */
Chris@4 190 for( i=0; i<TABLE_SIZE; i++ )
Chris@4 191 {
Chris@4 192 data.waveform[i] = (float) (
Chris@4 193 (0.2 * sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. )) +
Chris@4 194 (0.2 * sin( ((double)(3*i)/(double)TABLE_SIZE) * M_PI * 2. )) +
Chris@4 195 (0.1 * sin( ((double)(5*i)/(double)TABLE_SIZE) * M_PI * 2. ))
Chris@4 196 );
Chris@4 197 }
Chris@4 198 data.waveform[TABLE_SIZE] = data.waveform[0]; /* Set guard point. */
Chris@4 199 data.tune = &simpleTune[0];
Chris@4 200 data.notesPerTune = sizeof(simpleTune) / sizeof(float);
Chris@4 201
Chris@4 202 printf("Test MODE_FINISH - callback returns 1.\n");
Chris@4 203 printf("Should hear entire %d note tune repeated twice.\n", data.notesPerTune);
Chris@4 204 data.stopMode = MODE_FINISH;
Chris@4 205 if( TestStopMode( &data ) != paNoError )
Chris@4 206 {
Chris@4 207 printf("Test of MODE_FINISH failed!\n");
Chris@4 208 goto error;
Chris@4 209 }
Chris@4 210
Chris@4 211 printf("Test MODE_STOP - stop when song is done.\n");
Chris@4 212 printf("Should hear entire %d note tune repeated twice.\n", data.notesPerTune);
Chris@4 213 data.stopMode = MODE_STOP;
Chris@4 214 if( TestStopMode( &data ) != paNoError )
Chris@4 215 {
Chris@4 216 printf("Test of MODE_STOP failed!\n");
Chris@4 217 goto error;
Chris@4 218 }
Chris@4 219
Chris@4 220 printf("Test MODE_ABORT - abort immediately.\n");
Chris@4 221 printf("Should hear last repetition cut short by %f seconds.\n", LATENCY_SECONDS);
Chris@4 222 data.stopMode = MODE_ABORT;
Chris@4 223 if( TestStopMode( &data ) != paNoError )
Chris@4 224 {
Chris@4 225 printf("Test of MODE_ABORT failed!\n");
Chris@4 226 goto error;
Chris@4 227 }
Chris@4 228
Chris@4 229 return 0;
Chris@4 230
Chris@4 231 error:
Chris@4 232 return 1;
Chris@4 233 }
Chris@4 234
Chris@4 235 int TestStopMode( paTestData *data )
Chris@4 236 {
Chris@4 237 PaStreamParameters outputParameters;
Chris@4 238 PaStream *stream;
Chris@4 239 PaError err;
Chris@4 240
Chris@4 241 data->done = 0;
Chris@4 242 data->phase = 0.0;
Chris@4 243 data->frameCounter = 0;
Chris@4 244 data->noteCounter = 0;
Chris@4 245 data->repeatCounter = 0;
Chris@4 246 data->phase_increment = data->tune[data->noteCounter];
Chris@4 247
Chris@4 248 err = Pa_Initialize();
Chris@4 249 if( err != paNoError ) goto error;
Chris@4 250
Chris@4 251 outputParameters.device = OUTPUT_DEVICE;
Chris@4 252 if (outputParameters.device == paNoDevice) {
Chris@4 253 fprintf(stderr,"Error: No default output device.\n");
Chris@4 254 goto error;
Chris@4 255 }
Chris@4 256 outputParameters.channelCount = 2; /* stereo output */
Chris@4 257 outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
Chris@4 258 outputParameters.suggestedLatency = LATENCY_SECONDS;
Chris@4 259 outputParameters.hostApiSpecificStreamInfo = NULL;
Chris@4 260
Chris@4 261 err = Pa_OpenStream(
Chris@4 262 &stream,
Chris@4 263 NULL, /* no input */
Chris@4 264 &outputParameters,
Chris@4 265 SAMPLE_RATE,
Chris@4 266 FRAMES_PER_BUFFER, /* frames per buffer */
Chris@4 267 paClipOff, /* we won't output out of range samples so don't bother clipping them */
Chris@4 268 patestCallback,
Chris@4 269 data );
Chris@4 270 if( err != paNoError ) goto error;
Chris@4 271
Chris@4 272 err = Pa_StartStream( stream );
Chris@4 273 if( err != paNoError ) goto error;
Chris@4 274
Chris@4 275 if( data->stopMode == MODE_FINISH )
Chris@4 276 {
Chris@4 277 while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
Chris@4 278 {
Chris@4 279 /*printf("outTime = %g, note# = %d, repeat# = %d\n", data->outTime,
Chris@4 280 data->noteCounter, data->repeatCounter );
Chris@4 281 fflush(stdout); */
Chris@4 282 Pa_Sleep( SLEEP_DUR );
Chris@4 283 }
Chris@4 284 if( err < 0 ) goto error;
Chris@4 285 }
Chris@4 286 else
Chris@4 287 {
Chris@4 288 while( data->repeatCounter < MAX_REPEATS )
Chris@4 289 {
Chris@4 290 /*printf("outTime = %g, note# = %d, repeat# = %d\n", data->outTime,
Chris@4 291 data->noteCounter, data->repeatCounter );
Chris@4 292 fflush(stdout); */
Chris@4 293 Pa_Sleep( SLEEP_DUR );
Chris@4 294 }
Chris@4 295 }
Chris@4 296
Chris@4 297 if( data->stopMode == MODE_ABORT )
Chris@4 298 {
Chris@4 299 printf("Call Pa_AbortStream()\n");
Chris@4 300 err = Pa_AbortStream( stream );
Chris@4 301 }
Chris@4 302 else
Chris@4 303 {
Chris@4 304 printf("Call Pa_StopStream()\n");
Chris@4 305 err = Pa_StopStream( stream );
Chris@4 306 }
Chris@4 307 if( err != paNoError ) goto error;
Chris@4 308
Chris@4 309 printf("Call Pa_CloseStream()\n"); fflush(stdout);
Chris@4 310 err = Pa_CloseStream( stream );
Chris@4 311 if( err != paNoError ) goto error;
Chris@4 312
Chris@4 313 Pa_Terminate();
Chris@4 314 printf("Test finished.\n");
Chris@4 315
Chris@4 316 return err;
Chris@4 317
Chris@4 318 error:
Chris@4 319 Pa_Terminate();
Chris@4 320 fprintf( stderr, "An error occured while using the portaudio stream\n" );
Chris@4 321 fprintf( stderr, "Error number: %d\n", err );
Chris@4 322 fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
Chris@4 323 return err;
Chris@4 324 }