mirror of
https://github.com/thestk/stk
synced 2026-01-13 13:01:52 +00:00
133 lines
8.8 KiB
HTML
133 lines
8.8 KiB
HTML
<HTML>
|
|
<HEAD>
|
|
<TITLE>The Synthesis ToolKit in C++ (STK)</TITLE>
|
|
<LINK HREF="doxygen.css" REL="stylesheet" TYPE="text/css">
|
|
</HEAD>
|
|
<BODY BGCOLOR="#FFFFFF">
|
|
<CENTER>
|
|
<img src="princeton.gif"> <img src="ccrma.gif"> <img src="mcgill.gif"><P>
|
|
<a class="qindex" href="index.html">Home</a> <a class="qindex" href="information.html">Information</a> <a class="qindex" href="classes.html">Classes</a> <a class="qindex" href="download.html">Download</a> <a class="qindex" href="usage.html">Usage</a> <a class="qindex" href="maillist.html">Mail List</a> <a class="qindex" href="system.html">Requirements</a> <a class="qindex" href="links.html">Links</a> <a class="qindex" href="tutorial.html">Tutorial</a></CENTER>
|
|
<HR>
|
|
<!-- Generated by Doxygen 1.3.6 -->
|
|
<h1><a class="anchor" name="controlin">Control Input</a></h1>Each Synthesis ToolKit instrument exposes its relevant control parameters via public functions such as setFrequency() and controlChange(). Programmers are free to implement the control scheme of their choice in exposing those parameters to the user.<p>
|
|
A text-based control protocol called <a href="skini.html">SKINI</a> is provided with the Synthesis ToolKit. <a class="el" href="classSKINI.html">SKINI</a> extends the MIDI protocol in incremental ways, providing a text-based messaging scheme in human-readable format and making use of floating-point numbers wherever possible. Each <a class="el" href="classSKINI.html">SKINI</a> message consists of a message type (e.g., NoteOn, PitchBend), a time specification (absolute or delta), a channel number (scanned as a long integer), and a maximum of two subsequent message-specific field values. Knowing this, it should be relatively clear what the following <a class="el" href="classSKINI.html">SKINI</a> "scorefile" specifies:<p>
|
|
<pre class="fragment"><div>NoteOn 0.000082 2 55.0 82.3
|
|
NoteOff 1.000000 2 55.0 64.0
|
|
NoteOn 0.000082 2 69.0 82.8
|
|
StringDetune 0.100000 2 10.0
|
|
StringDetune 0.100000 2 30.0
|
|
StringDetune 0.100000 2 50.0
|
|
StringDetune 0.100000 2 40.0
|
|
StringDetune 0.100000 2 22.0
|
|
StringDetune 0.100000 2 12.0
|
|
NoteOff 1.000000 2 69.0 64.0
|
|
</div></pre><p>
|
|
MIDI messages (with the exception of Sysex) are easily represented within the <a class="el" href="classSKINI.html">SKINI</a> protocol.<p>
|
|
The class <a class="el" href="classMessager.html">Messager</a> can be used to acquire and parse MIDI messages from a MIDI device and <a class="el" href="classSKINI.html">SKINI</a> messages from STDIN and socket connections. Many of the example programs included with the ToolKit distribution use a <a class="el" href="classMessager.html">Messager</a> instance to accept control input from the accompanying tcl/tk graphical user interfaces, from external MIDI devices, or from <a class="el" href="classSKINI.html">SKINI</a> scorefiles.<p>
|
|
In the following example, we'll modify the <code>bethree.cpp</code> program from the previous tutorial chapter and incorporate a <a class="el" href="classMessager.html">Messager</a> class to allow control via a <a class="el" href="classSKINI.html">SKINI</a> scorefile.<p>
|
|
<pre class="fragment"><div><span class="comment">// controlbee.cpp</span>
|
|
|
|
<span class="preprocessor">#include "BeeThree.h"</span>
|
|
<span class="preprocessor">#include "RtWvOut.h"</span>
|
|
<span class="preprocessor">#include "Messager.h"</span>
|
|
<span class="preprocessor">#include "SKINI.msg"</span>
|
|
<span class="preprocessor">#include <math.h></span>
|
|
|
|
<span class="keywordtype">int</span> main()
|
|
{
|
|
<span class="comment">// Set the global sample rate before creating class instances.</span>
|
|
<a class="code" href="classStk.html#e1">Stk::setSampleRate</a>( 44100.0 );
|
|
|
|
<a class="code" href="classInstrmnt.html">Instrmnt</a> *instrument = 0;
|
|
<a class="code" href="classRtWvOut.html">RtWvOut</a> *output = 0;
|
|
<a class="code" href="classMessager.html">Messager</a> *messager = 0;
|
|
<span class="keywordtype">bool</span> done = FALSE;
|
|
|
|
<span class="keywordflow">try</span> {
|
|
<span class="comment">// Define and load the BeeThree instrument</span>
|
|
instrument = <span class="keyword">new</span> <a class="code" href="classBeeThree.html">BeeThree</a>();
|
|
|
|
<span class="comment">// Define and open the default realtime output device for one-channel playback</span>
|
|
output = <span class="keyword">new</span> <a class="code" href="classRtWvOut.html">RtWvOut</a>(1);
|
|
}
|
|
<span class="keywordflow">catch</span> (<a class="code" href="classStkError.html">StkError</a> &) {
|
|
<span class="keywordflow">goto</span> cleanup;
|
|
}
|
|
|
|
<span class="keywordflow">try</span> {
|
|
<span class="comment">// Create a Messager instance to read from a redirected SKINI scorefile.</span>
|
|
messager = <span class="keyword">new</span> <a class="code" href="classMessager.html">Messager</a>();
|
|
}
|
|
<span class="keywordflow">catch</span> (<a class="code" href="classStkError.html">StkError</a> &) {
|
|
<span class="keywordflow">goto</span> cleanup;
|
|
}
|
|
|
|
<span class="comment">// Play the instrument until the end of the scorefile.</span>
|
|
<span class="keywordtype">int</span> i, nTicks, type;
|
|
MY_FLOAT byte2, byte3, frequency;
|
|
<span class="keywordflow">while</span> (!done) {
|
|
|
|
<span class="comment">// Look for new messages and return a delta time (in samples).</span>
|
|
type = messager-><a class="code" href="classMessager.html#a2">nextMessage</a>();
|
|
<span class="keywordflow">if</span> (type < 0)
|
|
done = TRUE;
|
|
|
|
nTicks = messager-><a class="code" href="classMessager.html#a4">getDelta</a>();
|
|
<span class="keywordflow">try</span> {
|
|
<span class="keywordflow">for</span> ( i=0; i<nTicks; i++ )
|
|
output-><a class="code" href="classRtWvOut.html#a6">tick</a>( instrument-><a class="code" href="classInstrmnt.html#a8">tick</a>() );
|
|
}
|
|
<span class="keywordflow">catch</span> (<a class="code" href="classStkError.html">StkError</a> &) {
|
|
<span class="keywordflow">goto</span> cleanup;
|
|
}
|
|
|
|
<span class="keywordflow">if</span> ( type > 0 ) {
|
|
<span class="comment">// Process the new control message.</span>
|
|
byte2 = messager-><a class="code" href="classMessager.html#a6">getByteTwo</a>();
|
|
byte3 = messager-><a class="code" href="classMessager.html#a7">getByteThree</a>();
|
|
|
|
<span class="keywordflow">switch</span>(type) {
|
|
|
|
<span class="keywordflow">case</span> __SK_NoteOn_:
|
|
frequency = (MY_FLOAT) 220.0 * pow( 2.0, (byte2 - 57.0) / 12.0 );
|
|
instrument-><a class="code" href="classInstrmnt.html#a2">noteOn</a>( frequency, byte3 * ONE_OVER_128 );
|
|
<span class="keywordflow">break</span>;
|
|
|
|
<span class="keywordflow">case</span> __SK_NoteOff_:
|
|
instrument-><a class="code" href="classInstrmnt.html#a3">noteOff</a>( byte3 * ONE_OVER_128 );
|
|
<span class="keywordflow">break</span>;
|
|
|
|
<span class="keywordflow">case</span> __SK_ControlChange_:
|
|
instrument-><a class="code" href="classInstrmnt.html#a10">controlChange</a>( (<span class="keywordtype">int</span>) byte2, byte3 );
|
|
<span class="keywordflow">break</span>;
|
|
|
|
<span class="keywordflow">case</span> __SK_AfterTouch_:
|
|
instrument-><a class="code" href="classInstrmnt.html#a10">controlChange</a>( 128, byte2 );
|
|
<span class="keywordflow">break</span>;
|
|
}
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
<span class="keyword">delete</span> instrument;
|
|
<span class="keyword">delete</span> output;
|
|
<span class="keyword">delete</span> messager;
|
|
|
|
<span class="keywordflow">return</span> 0;
|
|
}
|
|
</div></pre><p>
|
|
Assuming the program is compiled as <code>controlbee</code> and the <a class="el" href="classSKINI.html">SKINI</a> scorefile <a href="tutorial/bookert.ski"><code>bookert.ski</code></a> is in the <code>scores</code> directory, the scorefile could be redirected to the program as:<p>
|
|
<pre class="fragment"><div>controlbee < scores/bookert.ski
|
|
</div></pre><p>
|
|
Only a few basic <a class="el" href="classSKINI.html">SKINI</a> message type case statements are included in this example. It is easy to extend the program to support a much more elaborate set of instrument control parameters.<p>
|
|
This example could also be easily extended to accept "realtime" control input messages via STDIN, socket, or MIDI connections. The <a class="el" href="classMessager.html">Messager</a> class constructor takes an optional argument consisting of a bitmask of the following options: <code>STK_PIPE</code>, <code>STK_SOCKET</code>, and/or <code>STK_MIDI</code>.<p>
|
|
[<a href="multichannel.html">Next tutorial</a>] [<a href="tutorial.html">Main tutorial page</a>] <HR>
|
|
|
|
<table>
|
|
<tr><td><A HREF="http://www-ccrma.stanford.edu/software/stk/"><I>The Synthesis ToolKit in C++ (STK)</I></A></td></tr>
|
|
<tr><td>©1995-2004 Perry R. Cook and Gary P. Scavone. All Rights Reserved.</td></tr>
|
|
</table>
|
|
|
|
</BODY>
|
|
</HTML>
|