//----------------------------------------------------------------------------- // name: Delayed.cpp // desc: delayed expample real-time // // author: Ge Wang (ge@ccrma.stanford.edu) // date: fall 2011 // uses: RtAudio by Gary Scavone //----------------------------------------------------------------------------- #include "RtAudio.h" #include #include using namespace std; // our datetype #define SAMPLE double // corresponding format for RtAudio #define MY_FORMAT RTAUDIO_FLOAT64 // sample rate #define MY_SRATE 44100 // number of channels #define MY_CHANNELS 1 // number of strings #define MY_NUMSTRINGS 6 // for convenience #define MY_PIE 3.14159265358979 // delay buffer SAMPLE * g_delayBuffer = NULL; // attenuation SAMPLE g_attenuation = .99; // max delay possible int g_maxAmountOfDelay = 2 * MY_SRATE; // amount of delay int g_amountOfDelay = 500; // read and write indices long g_reader = 0; long g_writer = 0; //----------------------------------------------------------------------------- // name: callme() // desc: audio callback //----------------------------------------------------------------------------- int callme( void * outputBuffer, void * inputBuffer, unsigned int numFrames, double streamTime, RtAudioStreamStatus status, void * data ) { // cast SAMPLE * input = (SAMPLE *)inputBuffer; SAMPLE * output = (SAMPLE *)outputBuffer; // iterate for( int i = 0; i < numFrames; i++ ) { // read the next output sample from the delay buffer output[i] = g_delayBuffer[g_reader]; // put the next input samples in the delay buffer g_delayBuffer[g_writer] = output[i] * g_attenuation; // advance the indices g_writer++; g_reader++; // warp g_writer %= g_maxAmountOfDelay; g_reader %= g_maxAmountOfDelay; } return 0; } //----------------------------------------------------------------------------- // name: main() // desc: entry point //----------------------------------------------------------------------------- int main( int argc, char ** argv ) { // instantiate RtAudio object RtAudio audio; // variables unsigned int bufferBytes = 0; // frame size unsigned int numFrames = 512; // check for audio devices if( audio.getDeviceCount() < 1 ) { // nopes cout << "no audio devices found!" << endl; exit( 1 ); } // let RtAudio print messages to stderr. audio.showWarnings( true ); // set input and output parameters RtAudio::StreamParameters iParams, oParams; iParams.deviceId = audio.getDefaultInputDevice(); iParams.nChannels = MY_CHANNELS; iParams.firstChannel = 0; oParams.deviceId = audio.getDefaultOutputDevice(); oParams.nChannels = MY_CHANNELS; oParams.firstChannel = 0; // create stream options RtAudio::StreamOptions options; // go for it try { // open a stream audio.openStream( &oParams, &iParams, MY_FORMAT, MY_SRATE, &numFrames, &callme, NULL, &options ); } catch( RtError& e ) { // error! cout << e.getMessage() << endl; exit( 1 ); } // compute bufferBytes = numFrames * MY_CHANNELS * sizeof(SAMPLE); // test RtAudio functionality for reporting latency. cout << "stream latency: " << audio.getStreamLatency() << " frames" << endl; // allocate the delay buffer g_delayBuffer = new SAMPLE[g_maxAmountOfDelay]; // iterate for( int i = 0; i < g_maxAmountOfDelay; i++ ) { g_delayBuffer[i] = 2*(rand() / (SAMPLE)RAND_MAX) - 1; } // set indices g_reader = g_writer - g_amountOfDelay; // wrap if( g_reader < 0 ) g_reader += g_maxAmountOfDelay; cerr << "reader: " << g_reader << " writer: " << g_writer << endl; // go for it try { // start stream audio.startStream(); do { // get input float input; std::cout << "enter frequency: "; std::cin >> input; // TODO: check for crazy values // compute delay length float length = MY_SRATE / input; // round to nearest integer g_amountOfDelay = (int)(length + .5); // set indices g_reader = g_writer - g_amountOfDelay; // wrap if( g_reader < 0 ) g_reader += g_maxAmountOfDelay; // pluck by filling with white noise for( int i = 0; i < g_maxAmountOfDelay; i++ ) { g_delayBuffer[i] = 2*(rand() / (SAMPLE)RAND_MAX) - 1; } }while( true ); // stop the stream. audio.stopStream(); } catch( RtError& e ) { // print error message cout << e.getMessage() << endl; goto cleanup; } cleanup: // close if open if( audio.isStreamOpen() ) audio.closeStream(); // done return 0; }