/******************************************/ /* playsaw.cpp by Gary P. Scavone, 2006 This program will output sawtooth waveforms of different frequencies on each channel. */ /******************************************/ #include "RtAudio.h" #include #include #include #include #include #include #include using namespace std; typedef double SAMPLE; #define FORMAT RTAUDIO_FLOAT64 #define SCALE 1.0 #define BASE_RATE 0.005 #define TIME 1.0 #define CHANNELS 1 #define PI 3.14159265358979 #define SAMPLE_RATE 44100 #define NOT_IMPLEMENTED cout << "Not implemented!\n"; exit(-1) RtAudio::StreamOptions g_options; SAMPLE g_freq = 440; SAMPLE g_t = 0; double g_pulse_width = .5; bool g_use_input = false; ofstream myfile; void usage_and_exit() { cout << "usage:\n\n"; cout << "sig-gen [type] [input] [frequency] [width]\n"; cout << " [type]: --sine | --saw | --pulse | --noise | --impulse\n"; cout << " [input]: --input (optional flag to multiply the signal times standard input)\n"; cout << " [frequency]: (a number > 0, only applicable to some signal types)\n"; cout << " [width]: pulse width (only applicable to some signal types)\n"; exit(0); } int sine_callback(void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames, double streamTime, RtAudioStreamStatus status, void* user_data) { SAMPLE * obuffy = (SAMPLE *)outputBuffer; SAMPLE * ibuffy = (SAMPLE *)inputBuffer; for( unsigned i = 0; i < nBufferFrames; i++ ) { obuffy[i] = sin( 2 * PI * g_freq * g_t / SAMPLE_RATE ); g_t += 1.0; //if (g_use_input) obuffy[i] *= ibuffy[i]; } return 0; } int saw_callback(void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames, double streamTime, RtAudioStreamStatus status, void* user_data) { SAMPLE * obuffy = (SAMPLE *)outputBuffer; SAMPLE * ibuffy = (SAMPLE *)inputBuffer; for( unsigned i = 0; i < nBufferFrames; i++ ) { if (g_t <= SAMPLE_RATE / g_freq * g_pulse_width) { SAMPLE interp = g_t / (SAMPLE_RATE / g_freq * g_pulse_width) * 2 - 1; obuffy[i] = interp; } else { SAMPLE interp = - ( g_t - (SAMPLE_RATE / g_freq * g_pulse_width) ) / (SAMPLE_RATE / g_freq * (1 - g_pulse_width)) * 2 + 1; obuffy[i] = interp; } if (g_t > SAMPLE_RATE / g_freq) { g_t -= SAMPLE_RATE / g_freq; } g_t += 1.0; if (g_use_input) obuffy[i] *= ibuffy[i]; } myfile.write ( (char*)outputBuffer, nBufferFrames * sizeof(SAMPLE) ); return 0; } int pulse_callback(void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames, double streamTime, RtAudioStreamStatus status, void* user_data) { SAMPLE * obuffy = (SAMPLE *)outputBuffer; SAMPLE * ibuffy = (SAMPLE *)inputBuffer; for( unsigned i = 0; i < nBufferFrames; i++ ) { obuffy[i] = -1.0; if (g_t > SAMPLE_RATE / g_freq * g_pulse_width) { obuffy[i] = 1.0; } if (g_t > SAMPLE_RATE / g_freq) { g_t -= SAMPLE_RATE / g_freq; } g_t += 1.0; if (g_use_input) obuffy[i] *= ibuffy[i]; } return 0; } int impulse_callback(void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames, double streamTime, RtAudioStreamStatus status, void* user_data) { SAMPLE * obuffy = (SAMPLE *)outputBuffer; SAMPLE * ibuffy = (SAMPLE *)inputBuffer; for( unsigned i = 0; i < nBufferFrames; i++ ) { obuffy[i] = 0; if (g_t > SAMPLE_RATE / g_freq) { obuffy[i] = 1.0; g_t -= SAMPLE_RATE / g_freq; } g_t += 1.0; if (g_use_input) obuffy[i] *= ibuffy[i]; } return 0; } int noise_callback(void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames, double streamTime, RtAudioStreamStatus status, void* user_data) { SAMPLE * obuffy = (SAMPLE *)outputBuffer; SAMPLE * ibuffy = (SAMPLE *)inputBuffer; for( unsigned i = 0; i < nBufferFrames; i++ ) { obuffy[i] = (double)rand() / RAND_MAX * 2 - 1; if (g_use_input) obuffy[i] *= ibuffy[i]; } return 0; } int main( int argc, char* argv[] ) { unsigned int buffer_frames, device = 0, offset = 0; RtAudio dac; int (*audio_callback)(void*, void*, unsigned int, double, RtAudioStreamStatus, void*); audio_callback = &sine_callback; myfile.open ("rawout", ios::binary); cout << "\n=== REALTIME SIGNAL GENERATOR ===\n\n"; if ( dac.getDeviceCount() < 1 ) { std::cout << "No audio devices found!\n"; exit( 1 ); } // get arguments if (argc < 2 || argc > 5) usage_and_exit(); int param_num = 0; for (int i = 1; i < argc; i++) { string arg = argv[i]; if (arg[0] == '-' && arg[1] == '-') { if (arg == "--sine") { audio_callback = &sine_callback; cout << "sine (freq = " << g_freq << ")\n"; } else if (arg == "--saw") { audio_callback = &saw_callback; cout << "saw (freq = " << g_freq << ", pulse width = " << g_pulse_width << ")\n"; } else if (arg == "--pulse") { audio_callback = &pulse_callback; cout << "pulse (freq = " << g_freq << ", pulse width = " << g_pulse_width << ")\n"; } else if (arg == "--noise") { srand (time(NULL)); audio_callback = &noise_callback; cout << "noise (uniform distribution)\n"; } else if (arg == "--impulse") { audio_callback = &impulse_callback; cout << "impulse (freq = " << g_freq << ")\n"; } else if (arg == "--input") { g_use_input = true; } else { cout << "unrecognized option \"" << arg << "\"\n"; usage_and_exit(); } } else { switch (param_num) { case 0: g_freq = atof( arg.c_str() ); if (g_freq <= 0) { cout << "bad frequency \"" << arg << "\"\n"; usage_and_exit(); } break; case 1: g_pulse_width = atof( arg.c_str() ); if (g_pulse_width < 0 || g_pulse_width > 1) { cout << "bad pulse width \"" << arg << "\"\n"; usage_and_exit(); } break; } param_num++; } } double *data = (double *) calloc( CHANNELS, sizeof( double ) ); // Let RtAudio print messages to stderr. dac.showWarnings( true ); buffer_frames = 512; RtAudio::StreamParameters iParams; iParams.deviceId = 0;//dac.getDefaultInputDevice(); iParams.nChannels = CHANNELS; iParams.firstChannel = offset; RtAudio::StreamParameters oParams; oParams.deviceId = 0;//dac.getDefaultOutputDevice(); oParams.nChannels = CHANNELS; oParams.firstChannel = offset; cout << "iparam channels: " << iParams.nChannels << endl; cout << "oparam channels: " << oParams.nChannels << endl; //g_options.flags |= RTAUDIO_HOG_DEVICE; //g_options.flags |= RTAUDIO_SCHEDULE_REALTIME; try { //if (g_use_input) dac.openStream( &oParams, &iParams, FORMAT, SAMPLE_RATE, &buffer_frames, audio_callback, NULL, &g_options ); //else // dac.openStream( &oParams, NULL, FORMAT, SAMPLE_RATE, &buffer_frames, audio_callback, NULL, &g_options ); dac.startStream(); } catch ( RtError& e ) { e.printMessage(); goto cleanup; } char input; //std::cout << "Stream latency = " << dac.getStreamLatency() << "\n" << std::endl; cout << "Playing ... press to quit. (buffer size = " << buffer_frames << ")\n"; std::cin.get( input ); myfile.close(); try { // Stop the stream dac.stopStream(); } catch ( RtError& e ) { e.printMessage(); } cleanup: if ( dac.isStreamOpen() ) dac.closeStream(); free( data ); return 0; }