1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
/******************************************/
/*
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 <iostream>
#include <cstdlib>
#include <cstring>
#include <stdio.h>
/*
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__ ) || defined( __WINDOWS_WASAPI__ )
#include <windows.h>
#define SLEEP( milliseconds ) Sleep( (DWORD) milliseconds )
#else // Unix variants
#include <unistd.h>
#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 <duration> <device> <channelOffset>\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;
if ( device == 0 )
iParams.deviceId = adc.getDefaultInputDevice();
else
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 ( RtAudioError& 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 ( RtAudioError& 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;
}
|