Home Information Classes Download Usage Mail List Requirements Links Tutorial
The STK Voicer class is a relatively simple voice manager. The user can dynamically add and delete instruments from its "control", with the option of controlling specific instruments via unique note tags and/or grouping sets of instruments via a "channel" number. All sounding instrument outputs are summed and returned via the tick()
function. The Voicer class responds to noteOn, noteOff, setFrequency, pitchBend, and controlChange messages, automatically assigning incoming messages to the voices in its control. When all voices are sounding and a new noteOn is encountered, the Voicer interrupts the oldest sounding voice. The user is responsible for creating and deleting all instrument instances.
In the following example, we modify the controlbee.cpp
program to make use of three BeeThree instruments, all controlled using a Voicer.
// threebees.cpp #include "BeeThree.h" #include "RtWvOut.h" #include "Messager.h" #include "Voicer.h" #include "SKINI.msg" int main() { // Set the global sample rate before creating class instances. Stk::setSampleRate( 44100.0 ); int i; RtWvOut *output = 0; Messager *messager = 0; Voicer *voicer = 0; bool done = FALSE; Instrmnt *instrument[3]; for ( i=0; i<3; i++ ) instrument[i] = 0; try { // Define and load the BeeThree instruments for ( i=0; i<3; i++ ) instrument[i] = new BeeThree(); // Define and open the default realtime output device for one-channel playback output = new RtWvOut(1); } catch (StkError &) { goto cleanup; } try { // Create a Messager instance to read from a redirected SKINI scorefile. messager = new Messager(); } catch (StkError &) { goto cleanup; } // Instantiate the voicer for a maximum of three voices. voicer = new Voicer( 3 ); for ( i=0; i<3; i++ ) voicer->addInstrument( instrument[i] ); // Play the instrument until the end of the scorefile. int nTicks, type; MY_FLOAT byte2, byte3; while (!done) { // Look for new messages and return a delta time (in samples). type = messager->nextMessage(); if (type < 0) done = TRUE; nTicks = messager->getDelta(); try { for ( i=0; i<nTicks; i++ ) output->tick( voicer->tick() ); } catch (StkError &) { goto cleanup; } if ( type > 0 ) { // Process the new control message. byte2 = messager->getByteTwo(); byte3 = messager->getByteThree(); switch(type) { case __SK_NoteOn_: voicer->noteOn( byte2, byte3 ); break; case __SK_NoteOff_: voicer->noteOff( byte2, byte3 ); break; case __SK_ControlChange_: voicer->controlChange( (int) byte2, byte3 ); break; case __SK_AfterTouch_: voicer->controlChange( 128, byte2 ); break; } } } cleanup: for ( i=0; i<3; i++ ) delete instrument[i]; delete output; delete messager; delete voicer; return 0; }
Assuming the program is compiled as threebees
, the three-voice SKINI scorefile bachfugue.ski
(also located in the scores
directory with the examples) could be redirected to the program as:
threebees < bachfugue.ski
For more fun, surf to Kern Scores for a huge assortment of other scorefiles which can be downloaded in the SKINI format.
Another easy extension would be to use the STK_MIDI
constructor argument to the Messager class and then play the instruments via a MIDI keyboard.
The Synthesis ToolKit in C++ (STK) |
©1995-2004 Perry R. Cook and Gary P. Scavone. All Rights Reserved. |