The previous tutorial chapters were concerned only with monophonic ToolKit instrument playback and control. At this point, it should be relatively clear that one can instantiate multiple instruments and perhaps sum together their outputs or even direct their outputs to separate channels. It is less clear how one might go about controlling a group of instruments. The stk::Voicer class is designed to serve just this purpose.
#include "BeeThree.h"
#include "Messager.h"
#include "Voicer.h"
#include "SKINImsg.h"
#include <algorithm>
using std::min;
struct TickData {
int counter;
bool haveMessage;
bool done;
TickData()
: counter(0), haveMessage(false), done( false ) {}
};
#define DELTA_CONTROL_TICKS 64
void processMessage( TickData* data )
{
StkFloat value1 = data->message.floatValues[0];
StkFloat value2 = data->message.floatValues[1];
switch( data->message.type ) {
case __SK_Exit_:
data->done = true;
return;
case __SK_NoteOn_:
if ( value2 == 0.0 )
data->voicer.noteOff( value1, 64.0 );
else {
data->voicer.noteOn( value1, value2 );
}
break;
case __SK_NoteOff_:
data->voicer.noteOff( value1, value2 );
break;
case __SK_ControlChange_:
data->voicer.controlChange( (int) value1, value2 );
break;
case __SK_AfterTouch_:
data->voicer.controlChange( 128, value1 );
case __SK_PitchChange_:
data->voicer.setFrequency( value1 );
break;
case __SK_PitchBend_:
data->voicer.pitchBend( value1 );
}
data->haveMessage = false;
return;
}
int tick( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
{
TickData *data = (TickData *) dataPointer;
StkFloat *samples = (StkFloat *) outputBuffer;
int counter, nTicks = (int) nBufferFrames;
while ( nTicks > 0 && !data->done ) {
if ( !data->haveMessage ) {
data->messager.popMessage( data->message );
if ( data->message.type > 0 ) {
data->counter = (long) (data->message.time * Stk::sampleRate());
data->haveMessage = true;
}
else
data->counter = DELTA_CONTROL_TICKS;
}
counter = min( nTicks, data->counter );
data->counter -= counter;
for ( int i=0; i<counter; i++ ) {
*samples++ = data->voicer.tick();
nTicks--;
}
if ( nTicks == 0 ) break;
if ( data->haveMessage ) processMessage( data );
}
return 0;
}
int main()
{
Stk::setSampleRate( 44100.0 );
Stk::setRawwavePath( "../../rawwaves/" );
int i;
TickData data;
for ( i=0; i<3; i++ ) instrument[i] = 0;
RtAudioFormat format = (
sizeof(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
unsigned int bufferFrames = RT_BUFFER_SIZE;
if ( dac.
openStream( ¶meters, NULL, format, (
unsigned int)Stk::sampleRate(), &bufferFrames, &tick, (
void *)&data ) ) {
goto cleanup;
}
try {
for ( i=0; i<3; i++ )
}
goto cleanup;
}
for ( i=0; i<3; i++ )
data.voicer.addInstrument( instrument[i] );
if ( data.messager.startStdInput() == false )
goto cleanup;
goto cleanup;
}
while ( !data.done )
Stk::sleep( 100 );
cleanup:
for ( i=0; i<3; i++ ) delete instrument[i];
return 0;
}
unsigned int RtAudioStreamStatus
RtAudio stream status (over- or underflow) flags.
Definition: RtAudio.h:178
unsigned long RtAudioFormat
RtAudio data format type.
Definition: RtAudio.h:105
Realtime audio i/o C++ classes.
Definition: RtAudio.h:268
unsigned int getDefaultOutputDevice(void)
A function that returns the ID of the default output device.
Definition: RtAudio.h:915
const std::string getErrorText(void)
Retrieve the error message corresponding to the last error or warning condition.
Definition: RtAudio.h:920
void closeStream(void)
A function that closes a stream and frees any associated stream memory.
Definition: RtAudio.h:916
RtAudioErrorType openStream(RtAudio::StreamParameters *outputParameters, RtAudio::StreamParameters *inputParameters, RtAudioFormat format, unsigned int sampleRate, unsigned int *bufferFrames, RtAudioCallback callback, void *userData=NULL, RtAudio::StreamOptions *options=NULL)
A public function for opening a stream with the specified parameters.
RtAudioErrorType startStream(void)
A function that starts a stream.
Definition: RtAudio.h:917
STK Hammond-oid organ FM synthesis instrument.
Definition: BeeThree.h:43
STK instrument abstract base class.
Definition: Instrmnt.h:20
STK input control message parser.
Definition: Messager.h:56
STK error handling class.
Definition: Stk.h:87
STK voice manager class.
Definition: Voicer.h:35
The STK namespace.
Definition: ADSR.h:6
The structure for specifying input or output stream parameters.
Definition: RtAudio.h:302
unsigned int nChannels
Definition: RtAudio.h:305
unsigned int deviceId
Definition: RtAudio.h:304
A message structure to store and pass parsed SKINI messages.
Definition: Skini.h:43