annotate src/portaudio_20161030_catalina_patch/examples/paex_sine_c++.cpp @ 162:d43aab368df9

Duplicate for patch testing
author Chris Cannam <cannam@all-day-breakfast.com>
date Wed, 30 Oct 2019 11:25:10 +0000
parents
children
rev   line source
cannam@162 1 /** @file paex_sine.c
cannam@162 2 @ingroup examples_src
cannam@162 3 @brief Play a sine wave for several seconds.
cannam@162 4 @author Ross Bencina <rossb@audiomulch.com>
cannam@162 5 @author Phil Burk <philburk@softsynth.com>
cannam@162 6 */
cannam@162 7 /*
cannam@162 8 * $Id: paex_sine.c 1752 2011-09-08 03:21:55Z philburk $
cannam@162 9 *
cannam@162 10 * This program uses the PortAudio Portable Audio Library.
cannam@162 11 * For more information see: http://www.portaudio.com/
cannam@162 12 * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
cannam@162 13 *
cannam@162 14 * Permission is hereby granted, free of charge, to any person obtaining
cannam@162 15 * a copy of this software and associated documentation files
cannam@162 16 * (the "Software"), to deal in the Software without restriction,
cannam@162 17 * including without limitation the rights to use, copy, modify, merge,
cannam@162 18 * publish, distribute, sublicense, and/or sell copies of the Software,
cannam@162 19 * and to permit persons to whom the Software is furnished to do so,
cannam@162 20 * subject to the following conditions:
cannam@162 21 *
cannam@162 22 * The above copyright notice and this permission notice shall be
cannam@162 23 * included in all copies or substantial portions of the Software.
cannam@162 24 *
cannam@162 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
cannam@162 26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
cannam@162 27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
cannam@162 28 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
cannam@162 29 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
cannam@162 30 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
cannam@162 31 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cannam@162 32 */
cannam@162 33
cannam@162 34 /*
cannam@162 35 * The text above constitutes the entire PortAudio license; however,
cannam@162 36 * the PortAudio community also makes the following non-binding requests:
cannam@162 37 *
cannam@162 38 * Any person wishing to distribute modifications to the Software is
cannam@162 39 * requested to send the modifications to the original developer so that
cannam@162 40 * they can be incorporated into the canonical version. It is also
cannam@162 41 * requested that these non-binding requests be included along with the
cannam@162 42 * license above.
cannam@162 43 */
cannam@162 44 #include <stdio.h>
cannam@162 45 #include <math.h>
cannam@162 46 #include "portaudio.h"
cannam@162 47
cannam@162 48 #define NUM_SECONDS (5)
cannam@162 49 #define SAMPLE_RATE (44100)
cannam@162 50 #define FRAMES_PER_BUFFER (64)
cannam@162 51
cannam@162 52 #ifndef M_PI
cannam@162 53 #define M_PI (3.14159265)
cannam@162 54 #endif
cannam@162 55
cannam@162 56 #define TABLE_SIZE (200)
cannam@162 57
cannam@162 58 class Sine
cannam@162 59 {
cannam@162 60 public:
cannam@162 61 Sine() : stream(0), left_phase(0), right_phase(0)
cannam@162 62 {
cannam@162 63 /* initialise sinusoidal wavetable */
cannam@162 64 for( int i=0; i<TABLE_SIZE; i++ )
cannam@162 65 {
cannam@162 66 sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
cannam@162 67 }
cannam@162 68
cannam@162 69 sprintf( message, "No Message" );
cannam@162 70 }
cannam@162 71
cannam@162 72 bool open(PaDeviceIndex index)
cannam@162 73 {
cannam@162 74 PaStreamParameters outputParameters;
cannam@162 75
cannam@162 76 outputParameters.device = index;
cannam@162 77 if (outputParameters.device == paNoDevice) {
cannam@162 78 return false;
cannam@162 79 }
cannam@162 80
cannam@162 81 const PaDeviceInfo* pInfo = Pa_GetDeviceInfo(index);
cannam@162 82 if (pInfo != 0)
cannam@162 83 {
cannam@162 84 printf("Output device name: '%s'\r", pInfo->name);
cannam@162 85 }
cannam@162 86
cannam@162 87 outputParameters.channelCount = 2; /* stereo output */
cannam@162 88 outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
cannam@162 89 outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
cannam@162 90 outputParameters.hostApiSpecificStreamInfo = NULL;
cannam@162 91
cannam@162 92 PaError err = Pa_OpenStream(
cannam@162 93 &stream,
cannam@162 94 NULL, /* no input */
cannam@162 95 &outputParameters,
cannam@162 96 SAMPLE_RATE,
cannam@162 97 paFramesPerBufferUnspecified,
cannam@162 98 paClipOff, /* we won't output out of range samples so don't bother clipping them */
cannam@162 99 &Sine::paCallback,
cannam@162 100 this /* Using 'this' for userData so we can cast to Sine* in paCallback method */
cannam@162 101 );
cannam@162 102
cannam@162 103 if (err != paNoError)
cannam@162 104 {
cannam@162 105 /* Failed to open stream to device !!! */
cannam@162 106 return false;
cannam@162 107 }
cannam@162 108
cannam@162 109 err = Pa_SetStreamFinishedCallback( stream, &Sine::paStreamFinished );
cannam@162 110
cannam@162 111 if (err != paNoError)
cannam@162 112 {
cannam@162 113 Pa_CloseStream( stream );
cannam@162 114 stream = 0;
cannam@162 115
cannam@162 116 return false;
cannam@162 117 }
cannam@162 118
cannam@162 119 return true;
cannam@162 120 }
cannam@162 121
cannam@162 122 bool close()
cannam@162 123 {
cannam@162 124 if (stream == 0)
cannam@162 125 return false;
cannam@162 126
cannam@162 127 PaError err = Pa_CloseStream( stream );
cannam@162 128 stream = 0;
cannam@162 129
cannam@162 130 return (err == paNoError);
cannam@162 131 }
cannam@162 132
cannam@162 133
cannam@162 134 bool start()
cannam@162 135 {
cannam@162 136 if (stream == 0)
cannam@162 137 return false;
cannam@162 138
cannam@162 139 PaError err = Pa_StartStream( stream );
cannam@162 140
cannam@162 141 return (err == paNoError);
cannam@162 142 }
cannam@162 143
cannam@162 144 bool stop()
cannam@162 145 {
cannam@162 146 if (stream == 0)
cannam@162 147 return false;
cannam@162 148
cannam@162 149 PaError err = Pa_StopStream( stream );
cannam@162 150
cannam@162 151 return (err == paNoError);
cannam@162 152 }
cannam@162 153
cannam@162 154 private:
cannam@162 155 /* The instance callback, where we have access to every method/variable in object of class Sine */
cannam@162 156 int paCallbackMethod(const void *inputBuffer, void *outputBuffer,
cannam@162 157 unsigned long framesPerBuffer,
cannam@162 158 const PaStreamCallbackTimeInfo* timeInfo,
cannam@162 159 PaStreamCallbackFlags statusFlags)
cannam@162 160 {
cannam@162 161 float *out = (float*)outputBuffer;
cannam@162 162 unsigned long i;
cannam@162 163
cannam@162 164 (void) timeInfo; /* Prevent unused variable warnings. */
cannam@162 165 (void) statusFlags;
cannam@162 166 (void) inputBuffer;
cannam@162 167
cannam@162 168 for( i=0; i<framesPerBuffer; i++ )
cannam@162 169 {
cannam@162 170 *out++ = sine[left_phase]; /* left */
cannam@162 171 *out++ = sine[right_phase]; /* right */
cannam@162 172 left_phase += 1;
cannam@162 173 if( left_phase >= TABLE_SIZE ) left_phase -= TABLE_SIZE;
cannam@162 174 right_phase += 3; /* higher pitch so we can distinguish left and right. */
cannam@162 175 if( right_phase >= TABLE_SIZE ) right_phase -= TABLE_SIZE;
cannam@162 176 }
cannam@162 177
cannam@162 178 return paContinue;
cannam@162 179
cannam@162 180 }
cannam@162 181
cannam@162 182 /* This routine will be called by the PortAudio engine when audio is needed.
cannam@162 183 ** It may called at interrupt level on some machines so don't do anything
cannam@162 184 ** that could mess up the system like calling malloc() or free().
cannam@162 185 */
cannam@162 186 static int paCallback( const void *inputBuffer, void *outputBuffer,
cannam@162 187 unsigned long framesPerBuffer,
cannam@162 188 const PaStreamCallbackTimeInfo* timeInfo,
cannam@162 189 PaStreamCallbackFlags statusFlags,
cannam@162 190 void *userData )
cannam@162 191 {
cannam@162 192 /* Here we cast userData to Sine* type so we can call the instance method paCallbackMethod, we can do that since
cannam@162 193 we called Pa_OpenStream with 'this' for userData */
cannam@162 194 return ((Sine*)userData)->paCallbackMethod(inputBuffer, outputBuffer,
cannam@162 195 framesPerBuffer,
cannam@162 196 timeInfo,
cannam@162 197 statusFlags);
cannam@162 198 }
cannam@162 199
cannam@162 200
cannam@162 201 void paStreamFinishedMethod()
cannam@162 202 {
cannam@162 203 printf( "Stream Completed: %s\n", message );
cannam@162 204 }
cannam@162 205
cannam@162 206 /*
cannam@162 207 * This routine is called by portaudio when playback is done.
cannam@162 208 */
cannam@162 209 static void paStreamFinished(void* userData)
cannam@162 210 {
cannam@162 211 return ((Sine*)userData)->paStreamFinishedMethod();
cannam@162 212 }
cannam@162 213
cannam@162 214 PaStream *stream;
cannam@162 215 float sine[TABLE_SIZE];
cannam@162 216 int left_phase;
cannam@162 217 int right_phase;
cannam@162 218 char message[20];
cannam@162 219 };
cannam@162 220
cannam@162 221 class ScopedPaHandler
cannam@162 222 {
cannam@162 223 public:
cannam@162 224 ScopedPaHandler()
cannam@162 225 : _result(Pa_Initialize())
cannam@162 226 {
cannam@162 227 }
cannam@162 228 ~ScopedPaHandler()
cannam@162 229 {
cannam@162 230 if (_result == paNoError)
cannam@162 231 {
cannam@162 232 Pa_Terminate();
cannam@162 233 }
cannam@162 234 }
cannam@162 235
cannam@162 236 PaError result() const { return _result; }
cannam@162 237
cannam@162 238 private:
cannam@162 239 PaError _result;
cannam@162 240 };
cannam@162 241
cannam@162 242
cannam@162 243 /*******************************************************************/
cannam@162 244 int main(void);
cannam@162 245 int main(void)
cannam@162 246 {
cannam@162 247 Sine sine;
cannam@162 248
cannam@162 249 printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
cannam@162 250
cannam@162 251 ScopedPaHandler paInit;
cannam@162 252 if( paInit.result() != paNoError ) goto error;
cannam@162 253
cannam@162 254 if (sine.open(Pa_GetDefaultOutputDevice()))
cannam@162 255 {
cannam@162 256 if (sine.start())
cannam@162 257 {
cannam@162 258 printf("Play for %d seconds.\n", NUM_SECONDS );
cannam@162 259 Pa_Sleep( NUM_SECONDS * 1000 );
cannam@162 260
cannam@162 261 sine.stop();
cannam@162 262 }
cannam@162 263
cannam@162 264 sine.close();
cannam@162 265 }
cannam@162 266
cannam@162 267 printf("Test finished.\n");
cannam@162 268 return paNoError;
cannam@162 269
cannam@162 270 error:
cannam@162 271 fprintf( stderr, "An error occured while using the portaudio stream\n" );
cannam@162 272 fprintf( stderr, "Error number: %d\n", paInit.result() );
cannam@162 273 fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( paInit.result() ) );
cannam@162 274 return 1;
cannam@162 275 }