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.

172 lines
4.7KB

  1. /******************************************/
  2. /*
  3. record.cpp
  4. by Gary P. Scavone, 2007
  5. This program records audio from a device and writes it to a
  6. header-less binary file. Use the 'playraw', with the same
  7. parameters and format settings, to playback the audio.
  8. */
  9. /******************************************/
  10. #include "RtAudio.h"
  11. #include <iostream>
  12. #include <cstdlib>
  13. #include <cstring>
  14. #include <stdio.h>
  15. /*
  16. typedef char MY_TYPE;
  17. #define FORMAT RTAUDIO_SINT8
  18. */
  19. typedef signed short MY_TYPE;
  20. #define FORMAT RTAUDIO_SINT16
  21. /*
  22. typedef S24 MY_TYPE;
  23. #define FORMAT RTAUDIO_SINT24
  24. typedef signed long MY_TYPE;
  25. #define FORMAT RTAUDIO_SINT32
  26. typedef float MY_TYPE;
  27. #define FORMAT RTAUDIO_FLOAT32
  28. typedef double MY_TYPE;
  29. #define FORMAT RTAUDIO_FLOAT64
  30. */
  31. // Platform-dependent sleep routines.
  32. #if defined( __WINDOWS_ASIO__ ) || defined( __WINDOWS_DS__ )
  33. #include <windows.h>
  34. #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds )
  35. #else // Unix variants
  36. #include <unistd.h>
  37. #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) )
  38. #endif
  39. void usage( void ) {
  40. // Error function in case of incorrect command-line
  41. // argument specifications
  42. std::cout << "\nuseage: record N fs <duration> <device> <channelOffset>\n";
  43. std::cout << " where N = number of channels,\n";
  44. std::cout << " fs = the sample rate,\n";
  45. std::cout << " duration = optional time in seconds to record (default = 2.0),\n";
  46. std::cout << " device = optional device to use (default = 0),\n";
  47. std::cout << " and channelOffset = an optional channel offset on the device (default = 0).\n\n";
  48. exit( 0 );
  49. }
  50. struct InputData {
  51. MY_TYPE* buffer;
  52. unsigned long bufferBytes;
  53. unsigned long totalFrames;
  54. unsigned long frameCounter;
  55. unsigned int channels;
  56. };
  57. // Interleaved buffers
  58. int input( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
  59. double streamTime, RtAudioStreamStatus status, void *data )
  60. {
  61. InputData *iData = (InputData *) data;
  62. // Simply copy the data to our allocated buffer.
  63. unsigned int frames = nBufferFrames;
  64. if ( iData->frameCounter + nBufferFrames > iData->totalFrames ) {
  65. frames = iData->totalFrames - iData->frameCounter;
  66. iData->bufferBytes = frames * iData->channels * sizeof( MY_TYPE );
  67. }
  68. unsigned long offset = iData->frameCounter * iData->channels;
  69. memcpy( iData->buffer+offset, inputBuffer, iData->bufferBytes );
  70. iData->frameCounter += frames;
  71. if ( iData->frameCounter >= iData->totalFrames ) return 2;
  72. return 0;
  73. }
  74. int main( int argc, char *argv[] )
  75. {
  76. unsigned int channels, fs, bufferFrames, device = 0, offset = 0;
  77. double time = 2.0;
  78. FILE *fd;
  79. // minimal command-line checking
  80. if ( argc < 3 || argc > 6 ) usage();
  81. RtAudio adc;
  82. if ( adc.getDeviceCount() < 1 ) {
  83. std::cout << "\nNo audio devices found!\n";
  84. exit( 1 );
  85. }
  86. channels = (unsigned int) atoi( argv[1] );
  87. fs = (unsigned int) atoi( argv[2] );
  88. if ( argc > 3 )
  89. time = (double) atof( argv[3] );
  90. if ( argc > 4 )
  91. device = (unsigned int) atoi( argv[4] );
  92. if ( argc > 5 )
  93. offset = (unsigned int) atoi( argv[5] );
  94. // Let RtAudio print messages to stderr.
  95. adc.showWarnings( true );
  96. // Set our stream parameters for input only.
  97. bufferFrames = 512;
  98. RtAudio::StreamParameters iParams;
  99. iParams.deviceId = device;
  100. iParams.nChannels = channels;
  101. iParams.firstChannel = offset;
  102. InputData data;
  103. data.buffer = 0;
  104. try {
  105. adc.openStream( NULL, &iParams, FORMAT, fs, &bufferFrames, &input, (void *)&data );
  106. }
  107. catch ( RtError& e ) {
  108. std::cout << '\n' << e.getMessage() << '\n' << std::endl;
  109. goto cleanup;
  110. }
  111. data.bufferBytes = bufferFrames * channels * sizeof( MY_TYPE );
  112. data.totalFrames = (unsigned long) (fs * time);
  113. data.frameCounter = 0;
  114. data.channels = channels;
  115. unsigned long totalBytes;
  116. totalBytes = data.totalFrames * channels * sizeof( MY_TYPE );
  117. // Allocate the entire data buffer before starting stream.
  118. data.buffer = (MY_TYPE*) malloc( totalBytes );
  119. if ( data.buffer == 0 ) {
  120. std::cout << "Memory allocation error ... quitting!\n";
  121. goto cleanup;
  122. }
  123. try {
  124. adc.startStream();
  125. }
  126. catch ( RtError& e ) {
  127. std::cout << '\n' << e.getMessage() << '\n' << std::endl;
  128. goto cleanup;
  129. }
  130. std::cout << "\nRecording for " << time << " seconds ... writing file 'record.raw' (buffer frames = " << bufferFrames << ")." << std::endl;
  131. while ( adc.isStreamRunning() ) {
  132. SLEEP( 100 ); // wake every 100 ms to check if we're done
  133. }
  134. // Now write the entire data to the file.
  135. fd = fopen( "record.raw", "wb" );
  136. fwrite( data.buffer, sizeof( MY_TYPE ), data.totalFrames * channels, fd );
  137. fclose( fd );
  138. cleanup:
  139. if ( adc.isStreamOpen() ) adc.closeStream();
  140. if ( data.buffer ) free( data.buffer );
  141. return 0;
  142. }