Audio plugin host https://kx.studio/carla
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.

204 lines
5.3KB

  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( __WINDOWS_ASIO__ ) || defined( __WINDOWS_DS__ )
  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. unsigned int channels;
  56. RtAudio::StreamOptions options;
  57. unsigned int frameCounter = 0;
  58. bool checkCount = false;
  59. unsigned int nFrames = 0;
  60. const unsigned int callbackReturnValue = 1;
  61. //#define USE_INTERLEAVED
  62. #if defined( USE_INTERLEAVED )
  63. // Interleaved buffers
  64. int saw( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
  65. double streamTime, RtAudioStreamStatus status, void *data )
  66. {
  67. unsigned int i, j;
  68. extern unsigned int channels;
  69. MY_TYPE *buffer = (MY_TYPE *) outputBuffer;
  70. double *lastValues = (double *) data;
  71. if ( status )
  72. std::cout << "Stream underflow detected!" << std::endl;
  73. for ( i=0; i<nBufferFrames; i++ ) {
  74. for ( j=0; j<channels; j++ ) {
  75. *buffer++ = (MY_TYPE) (lastValues[j] * SCALE * 0.5);
  76. lastValues[j] += BASE_RATE * (j+1+(j*0.1));
  77. if ( lastValues[j] >= 1.0 ) lastValues[j] -= 2.0;
  78. }
  79. }
  80. frameCounter += nBufferFrames;
  81. if ( checkCount && ( frameCounter >= nFrames ) ) return callbackReturnValue;
  82. return 0;
  83. }
  84. #else // Use non-interleaved buffers
  85. int saw( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
  86. double streamTime, RtAudioStreamStatus status, void *data )
  87. {
  88. unsigned int i, j;
  89. extern unsigned int channels;
  90. MY_TYPE *buffer = (MY_TYPE *) outputBuffer;
  91. double *lastValues = (double *) data;
  92. if ( status )
  93. std::cout << "Stream underflow detected!" << std::endl;
  94. double increment;
  95. for ( j=0; j<channels; j++ ) {
  96. increment = BASE_RATE * (j+1+(j*0.1));
  97. for ( i=0; i<nBufferFrames; i++ ) {
  98. *buffer++ = (MY_TYPE) (lastValues[j] * SCALE * 0.5);
  99. lastValues[j] += increment;
  100. if ( lastValues[j] >= 1.0 ) lastValues[j] -= 2.0;
  101. }
  102. }
  103. frameCounter += nBufferFrames;
  104. if ( checkCount && ( frameCounter >= nFrames ) ) return callbackReturnValue;
  105. return 0;
  106. }
  107. #endif
  108. int main( int argc, char *argv[] )
  109. {
  110. unsigned int bufferFrames, fs, device = 0, offset = 0;
  111. // minimal command-line checking
  112. if (argc < 3 || argc > 6 ) usage();
  113. RtAudio dac;
  114. if ( dac.getDeviceCount() < 1 ) {
  115. std::cout << "\nNo audio devices found!\n";
  116. exit( 1 );
  117. }
  118. channels = (unsigned int) atoi( argv[1] );
  119. fs = (unsigned int) atoi( argv[2] );
  120. if ( argc > 3 )
  121. device = (unsigned int) atoi( argv[3] );
  122. if ( argc > 4 )
  123. offset = (unsigned int) atoi( argv[4] );
  124. if ( argc > 5 )
  125. nFrames = (unsigned int) (fs * atof( argv[5] ));
  126. if ( nFrames > 0 ) checkCount = true;
  127. double *data = (double *) calloc( channels, sizeof( double ) );
  128. // Let RtAudio print messages to stderr.
  129. dac.showWarnings( true );
  130. // Set our stream parameters for output only.
  131. bufferFrames = 512;
  132. RtAudio::StreamParameters oParams;
  133. oParams.deviceId = device;
  134. oParams.nChannels = channels;
  135. oParams.firstChannel = offset;
  136. options.flags = RTAUDIO_HOG_DEVICE;
  137. options.flags |= RTAUDIO_SCHEDULE_REALTIME;
  138. #if !defined( USE_INTERLEAVED )
  139. options.flags |= RTAUDIO_NONINTERLEAVED;
  140. #endif
  141. try {
  142. dac.openStream( &oParams, NULL, FORMAT, fs, &bufferFrames, &saw, (void *)data, &options );
  143. dac.startStream();
  144. }
  145. catch ( RtError& e ) {
  146. e.printMessage();
  147. goto cleanup;
  148. }
  149. if ( checkCount ) {
  150. while ( dac.isStreamRunning() == true ) SLEEP( 100 );
  151. }
  152. else {
  153. char input;
  154. //std::cout << "Stream latency = " << dac.getStreamLatency() << "\n" << std::endl;
  155. std::cout << "\nPlaying ... press <enter> to quit (buffer size = " << bufferFrames << ").\n";
  156. std::cin.get( input );
  157. try {
  158. // Stop the stream
  159. dac.stopStream();
  160. }
  161. catch ( RtError& e ) {
  162. e.printMessage();
  163. }
  164. }
  165. cleanup:
  166. if ( dac.isStreamOpen() ) dac.closeStream();
  167. free( data );
  168. return 0;
  169. }