You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

219 lines
6.0KB

  1. /******************************************/
  2. /*
  3. playsaw.cpp
  4. by Gary P. Scavone, 2006
  5. This program will output sawtooth waveforms
  6. of different frequencies on each channel.
  7. */
  8. /******************************************/
  9. #include "RtAudio.h"
  10. #include <iostream>
  11. #include <cstdlib>
  12. /*
  13. typedef char MY_TYPE;
  14. #define FORMAT RTAUDIO_SINT8
  15. #define SCALE 127.0
  16. */
  17. typedef signed short MY_TYPE;
  18. #define FORMAT RTAUDIO_SINT16
  19. #define SCALE 32767.0
  20. /*
  21. typedef S24 MY_TYPE;
  22. #define FORMAT RTAUDIO_SINT24
  23. #define SCALE 8388607.0
  24. typedef signed long MY_TYPE;
  25. #define FORMAT RTAUDIO_SINT32
  26. #define SCALE 2147483647.0
  27. typedef float MY_TYPE;
  28. #define FORMAT RTAUDIO_FLOAT32
  29. #define SCALE 1.0
  30. typedef double MY_TYPE;
  31. #define FORMAT RTAUDIO_FLOAT64
  32. #define SCALE 1.0
  33. */
  34. // Platform-dependent sleep routines.
  35. #if defined( WIN32 )
  36. #include <windows.h>
  37. #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds )
  38. #else // Unix variants
  39. #include <unistd.h>
  40. #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )
  41. #endif
  42. #define BASE_RATE 0.005
  43. #define TIME 1.0
  44. void usage( void ) {
  45. // Error function in case of incorrect command-line
  46. // argument specifications
  47. std::cout << "\nuseage: playsaw N fs <device> <channelOffset> <time>\n";
  48. std::cout << " where N = number of channels,\n";
  49. std::cout << " fs = the sample rate,\n";
  50. std::cout << " device = optional device to use (default = 0),\n";
  51. std::cout << " channelOffset = an optional channel offset on the device (default = 0),\n";
  52. std::cout << " and time = an optional time duration in seconds (default = no limit).\n\n";
  53. exit( 0 );
  54. }
  55. void errorCallback( RtAudioError::Type /*type*/, const std::string &errorText )
  56. {
  57. // This example error handling function does exactly the same thing
  58. // as the embedded RtAudio::error() function.
  59. std::cerr << "\nerrorCallback: " << errorText << "\n\n";
  60. }
  61. unsigned int channels;
  62. RtAudio::StreamOptions options;
  63. unsigned int frameCounter = 0;
  64. bool checkCount = false;
  65. unsigned int nFrames = 0;
  66. const unsigned int callbackReturnValue = 1; // 1 = stop and drain, 2 = abort
  67. double streamTimePrintIncrement = 1.0; // seconds
  68. double streamTimePrintTime = 1.0; // seconds
  69. #define USE_INTERLEAVED
  70. #if defined( USE_INTERLEAVED )
  71. // Interleaved buffers
  72. int saw( void *outputBuffer, void * /*inputBuffer*/, unsigned int nBufferFrames,
  73. double streamTime, RtAudioStreamStatus status, void *data )
  74. {
  75. unsigned int i, j;
  76. extern unsigned int channels;
  77. MY_TYPE *buffer = (MY_TYPE *) outputBuffer;
  78. double *lastValues = (double *) data;
  79. if ( status )
  80. std::cout << "Stream underflow detected!" << std::endl;
  81. if ( streamTime >= streamTimePrintTime ) {
  82. std::cout << "streamTime = " << streamTime << std::endl;
  83. streamTimePrintTime += streamTimePrintIncrement;
  84. }
  85. for ( i=0; i<nBufferFrames; i++ ) {
  86. for ( j=0; j<channels; j++ ) {
  87. *buffer++ = (MY_TYPE) (lastValues[j] * SCALE * 0.5);
  88. lastValues[j] += BASE_RATE * (j+1+(j*0.1));
  89. if ( lastValues[j] >= 1.0 ) lastValues[j] -= 2.0;
  90. }
  91. }
  92. frameCounter += nBufferFrames;
  93. if ( checkCount && ( frameCounter >= nFrames ) ) return callbackReturnValue;
  94. return 0;
  95. }
  96. #else // Use non-interleaved buffers
  97. int saw( void *outputBuffer, void * /*inputBuffer*/, unsigned int nBufferFrames,
  98. double streamTime, RtAudioStreamStatus status, void *data )
  99. {
  100. unsigned int i, j;
  101. extern unsigned int channels;
  102. MY_TYPE *buffer = (MY_TYPE *) outputBuffer;
  103. double *lastValues = (double *) data;
  104. if ( status )
  105. std::cout << "Stream underflow detected!" << std::endl;
  106. if ( streamTime >= streamTimePrintTime ) {
  107. std::cout << "streamTime = " << streamTime << std::endl;
  108. streamTimePrintTime += streamTimePrintIncrement;
  109. }
  110. double increment;
  111. for ( j=0; j<channels; j++ ) {
  112. increment = BASE_RATE * (j+1+(j*0.1));
  113. for ( i=0; i<nBufferFrames; i++ ) {
  114. *buffer++ = (MY_TYPE) (lastValues[j] * SCALE * 0.5);
  115. lastValues[j] += increment;
  116. if ( lastValues[j] >= 1.0 ) lastValues[j] -= 2.0;
  117. }
  118. }
  119. frameCounter += nBufferFrames;
  120. if ( checkCount && ( frameCounter >= nFrames ) ) return callbackReturnValue;
  121. return 0;
  122. }
  123. #endif
  124. int main( int argc, char *argv[] )
  125. {
  126. unsigned int bufferFrames, fs, device = 0, offset = 0;
  127. // minimal command-line checking
  128. if (argc < 3 || argc > 6 ) usage();
  129. RtAudio dac;
  130. if ( dac.getDeviceCount() < 1 ) {
  131. std::cout << "\nNo audio devices found!\n";
  132. exit( 1 );
  133. }
  134. channels = (unsigned int) atoi( argv[1] );
  135. fs = (unsigned int) atoi( argv[2] );
  136. if ( argc > 3 )
  137. device = (unsigned int) atoi( argv[3] );
  138. if ( argc > 4 )
  139. offset = (unsigned int) atoi( argv[4] );
  140. if ( argc > 5 )
  141. nFrames = (unsigned int) (fs * atof( argv[5] ));
  142. if ( nFrames > 0 ) checkCount = true;
  143. double *data = (double *) calloc( channels, sizeof( double ) );
  144. // Let RtAudio print messages to stderr.
  145. dac.showWarnings( true );
  146. // Set our stream parameters for output only.
  147. bufferFrames = 512;
  148. RtAudio::StreamParameters oParams;
  149. oParams.deviceId = device;
  150. oParams.nChannels = channels;
  151. oParams.firstChannel = offset;
  152. if ( device == 0 )
  153. oParams.deviceId = dac.getDefaultOutputDevice();
  154. options.flags = RTAUDIO_HOG_DEVICE;
  155. options.flags |= RTAUDIO_SCHEDULE_REALTIME;
  156. #if !defined( USE_INTERLEAVED )
  157. options.flags |= RTAUDIO_NONINTERLEAVED;
  158. #endif
  159. dac.openStream( &oParams, NULL, FORMAT, fs, &bufferFrames, &saw, (void *)data, &options, &errorCallback );
  160. if ( dac.isStreamOpen() == false ) goto cleanup;
  161. // Stream is open ... now start it.
  162. dac.startStream();
  163. if ( checkCount ) {
  164. while ( dac.isStreamRunning() == true ) SLEEP( 100 );
  165. }
  166. else {
  167. char input;
  168. //std::cout << "Stream latency = " << dac.getStreamLatency() << "\n" << std::endl;
  169. std::cout << "\nPlaying ... press <enter> to quit (buffer size = " << bufferFrames << ").\n";
  170. std::cin.get( input );
  171. // Block released ... stop the stream
  172. dac.stopStream(); // or could call dac.abortStream();
  173. }
  174. cleanup:
  175. if ( dac.isStreamOpen() ) dac.closeStream();
  176. free( data );
  177. return 0;
  178. }