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