/******************************************/ /* record.cpp by Gary P. Scavone, 2007 This program records audio from a device and writes it to a header-less binary file. Use the 'playraw', with the same parameters and format settings, to playback the audio. */ /******************************************/ #include "RtAudio.h" #include #include #include #include /* typedef char MY_TYPE; #define FORMAT RTAUDIO_SINT8 */ typedef signed short MY_TYPE; #define FORMAT RTAUDIO_SINT16 /* typedef S24 MY_TYPE; #define FORMAT RTAUDIO_SINT24 typedef signed long MY_TYPE; #define FORMAT RTAUDIO_SINT32 typedef float MY_TYPE; #define FORMAT RTAUDIO_FLOAT32 typedef double MY_TYPE; #define FORMAT RTAUDIO_FLOAT64 */ // Platform-dependent sleep routines. #if defined( __WINDOWS_ASIO__ ) || defined( __WINDOWS_DS__ ) #include #define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds ) #else // Unix variants #include #define SLEEP( milliseconds ) usleep( (unsigned long) (milliseconds * 1000.0) ) #endif void usage( void ) { // Error function in case of incorrect command-line // argument specifications std::cout << "\nuseage: record N fs \n"; std::cout << " where N = number of channels,\n"; std::cout << " fs = the sample rate,\n"; std::cout << " duration = optional time in seconds to record (default = 2.0),\n"; std::cout << " device = optional device to use (default = 0),\n"; std::cout << " and channelOffset = an optional channel offset on the device (default = 0).\n\n"; exit( 0 ); } struct InputData { MY_TYPE* buffer; unsigned long bufferBytes; unsigned long totalFrames; unsigned long frameCounter; unsigned int channels; }; // Interleaved buffers int input( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames, double streamTime, RtAudioStreamStatus status, void *data ) { InputData *iData = (InputData *) data; // Simply copy the data to our allocated buffer. unsigned int frames = nBufferFrames; if ( iData->frameCounter + nBufferFrames > iData->totalFrames ) { frames = iData->totalFrames - iData->frameCounter; iData->bufferBytes = frames * iData->channels * sizeof( MY_TYPE ); } unsigned long offset = iData->frameCounter * iData->channels; memcpy( iData->buffer+offset, inputBuffer, iData->bufferBytes ); iData->frameCounter += frames; if ( iData->frameCounter >= iData->totalFrames ) return 2; return 0; } int main( int argc, char *argv[] ) { unsigned int channels, fs, bufferFrames, device = 0, offset = 0; double time = 2.0; FILE *fd; // minimal command-line checking if ( argc < 3 || argc > 6 ) usage(); RtAudio adc; if ( adc.getDeviceCount() < 1 ) { std::cout << "\nNo audio devices found!\n"; exit( 1 ); } channels = (unsigned int) atoi( argv[1] ); fs = (unsigned int) atoi( argv[2] ); if ( argc > 3 ) time = (double) atof( argv[3] ); if ( argc > 4 ) device = (unsigned int) atoi( argv[4] ); if ( argc > 5 ) offset = (unsigned int) atoi( argv[5] ); // Let RtAudio print messages to stderr. adc.showWarnings( true ); // Set our stream parameters for input only. bufferFrames = 512; RtAudio::StreamParameters iParams; iParams.deviceId = device; iParams.nChannels = channels; iParams.firstChannel = offset; InputData data; data.buffer = 0; try { adc.openStream( NULL, &iParams, FORMAT, fs, &bufferFrames, &input, (void *)&data ); } catch ( RtError& e ) { std::cout << '\n' << e.getMessage() << '\n' << std::endl; goto cleanup; } data.bufferBytes = bufferFrames * channels * sizeof( MY_TYPE ); data.totalFrames = (unsigned long) (fs * time); data.frameCounter = 0; data.channels = channels; unsigned long totalBytes; totalBytes = data.totalFrames * channels * sizeof( MY_TYPE ); // Allocate the entire data buffer before starting stream. data.buffer = (MY_TYPE*) malloc( totalBytes ); if ( data.buffer == 0 ) { std::cout << "Memory allocation error ... quitting!\n"; goto cleanup; } try { adc.startStream(); } catch ( RtError& e ) { std::cout << '\n' << e.getMessage() << '\n' << std::endl; goto cleanup; } std::cout << "\nRecording for " << time << " seconds ... writing file 'record.raw' (buffer frames = " << bufferFrames << ")." << std::endl; while ( adc.isStreamRunning() ) { SLEEP( 100 ); // wake every 100 ms to check if we're done } // Now write the entire data to the file. fd = fopen( "record.raw", "wb" ); fwrite( data.buffer, sizeof( MY_TYPE ), data.totalFrames * channels, fd ); fclose( fd ); cleanup: if ( adc.isStreamOpen() ) adc.closeStream(); if ( data.buffer ) free( data.buffer ); return 0; }