// started with ex9.cpp, by Woon Seung Yeo // modified to play stereo in and out. // added ability to process up to two arbitrary effects in callback. // added some error checking. // Mac OS X with StkX: // g++ -g -o s07 s07.cpp -framework StkX // Usage: ./s07 #include #include // struct for passing effects to callback struct TickData { Effect *effect1L; Effect *effect1R; Effect *effect2L; Effect *effect2R; int numEfx; }; // audio call back. can process up to two arbitrary effects (using polymorphism.) int tick_c(char *buffer, int bufferSize, void *dataPointer) { TickData *data = (TickData *)dataPointer; StkFloat *samples = (StkFloat *) buffer; if(2 == data->numEfx) { for ( int i=0; ieffect2L->tick(data->effect1L->tick(*samples)); *samples++ = data->effect2R->tick(data->effect1R->tick(*samples)); } } else if(1 == data->numEfx) { for ( int i=0; ieffect1L->tick(*samples); *samples++ = data->effect1R->tick(*samples); } } else { for ( int i=0; isetEffectMix(mix); // Wet/dry ratio chorus->setModDepth(depth); // Mod. depth chorus->setModFrequency(freq); // Mod. freq. return (Effect *)chorus; } Effect * AddEcho(float mix, long samps) { Echo* echo = new Echo(samps); echo->setDelay(samps); echo->setEffectMix(0.5); return (Effect *)echo; } Effect * AddPShift(float mix, float shift) { PitShift* pitshift = new PitShift(); // PitShift pitshift->setEffectMix(mix); pitshift->setShift(shift); return (Effect *)pitshift; } // main int main (int argc, char* const argv[]) { Stk::setSampleRate( 44100.0 ); TickData data; unsigned long samps = Stk::sampleRate()/2; // get user input char keyhit; char input[5]; std::cout << " Which effect would you like to add first?\n"; std::cout << " 1 - Chorus, 2 - Echo, 3 - Pitch Shift, 4 - None.\n"; fgets(input,sizeof(input),stdin); switch(atoi(input)) { case 1: std::cout<<"adding chorus...\n"; data.effect1L = AddChorus(0.6, 0.1, 2); data.effect1R = AddChorus(0.6, 0.1, 2); data.numEfx = 1; break; case 2: std::cout<<"adding echo...\n"; data.effect1L = AddEcho(0.6, samps); data.effect1R = AddEcho(0.6, samps); data.numEfx = 1; break; case 3: std::cout<<"adding pitch shift...\n"; data.effect1L = AddEcho(0.6, 2); data.effect1R = AddPShift(0.6, 2); data.numEfx = 1; break; default: std::cout<<"No Effects! Pass through.\n"; data.numEfx = 0; } if (data.numEfx) { std::cout << " Which effect would you like to add second?\n"; std::cout << " 1 - Chorus, 2 - Echo, 3 - Pitch Shift, 4 - None.\n"; fgets(input,sizeof(input),stdin); switch(atoi(input)) { case 1: std::cout<<"adding chorus...\n"; data.effect2L = AddChorus(0.6, 0.1, 2); data.effect2R = AddChorus(0.6, 0.1, 2); data.numEfx = 2; break; case 2: std::cout<<"adding echo...\n"; data.effect2L = AddEcho(0.6, samps); data.effect2R = AddEcho(0.6, samps); data.numEfx = 2; break; case 3: std::cout<<"adding pitch shift...\n"; data.effect2L = AddEcho(0.6, 2); data.effect2R = AddPShift(0.6, 2); data.numEfx = 2; break; default: std::cout<<"Only one effect.\n"; data.numEfx = 1; } } // get RtAudio and play RtAudio* audio; // RtAudio: realtime audio I/O RtAudioFormat format = ( sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32; int bufferSize = RT_BUFFER_SIZE; try { // motu audio: // audio = new RtAudio(2, 2, 2, 2, format, (int)Stk::sampleRate(), &bufferSize, 0); // default audio: audio = new RtAudio(0, 1, 0, 1, format, (int)Stk::sampleRate(), &bufferSize, 0); } catch (RtError &error) { error.printMessage(); goto cleanup; } try { audio->setStreamCallback(&tick_c, (void *)&data); audio->startStream(); } catch (RtError &error) { error.printMessage(); goto cleanup; } std::cout << "\nPlaying ... press [ENTER] to quit.\n"; std::cin.get(keyhit); audio->cancelStreamCallback(); audio->closeStream(); cleanup: delete audio; if(data.numEfx) { delete data.effect1L; delete data.effect1R; } if(data.numEfx == 2) { delete data.effect2L; delete data.effect2R; } return 0; }