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