mirror of
https://github.com/thestk/stk
synced 2026-01-18 23:21:53 +00:00
Release 4.4.0 tarball
This commit is contained in:
committed by
Stephen Sinclair
parent
3706458166
commit
d2ed001eb5
@@ -8,8 +8,9 @@
|
||||
<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="faq.html">FAQ</a> <a class="qindex" href="tutorial.html">Tutorial</a></CENTER>
|
||||
<HR>
|
||||
<!-- Generated by Doxygen 1.4.4 -->
|
||||
<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>
|
||||
<!-- Generated by Doxygen 1.5.8 -->
|
||||
<div class="contents">
|
||||
<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. SKINI 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 SKINI 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 SKINI "scorefile" specifies:<p>
|
||||
<div class="fragment"><pre class="fragment">NoteOn 0.000082 2 55.0 82.3
|
||||
NoteOff 1.000000 2 55.0 64.0
|
||||
@@ -23,8 +24,8 @@ StringDetune 0.100000 2 12.0
|
||||
NoteOff 1.000000 2 69.0 64.0
|
||||
</pre></div><p>
|
||||
MIDI messages are easily represented within the SKINI 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 SKINI messages from STDIN and socket connections. Incoming messages are acquired asynchronously and saved to an internal message queue of <a class="el" href="structSkini_1_1Message.html">Skini::Message</a> types (MIDI messages are converted to the <a class="el" href="classSkini.html">Skini</a>:Message format). The user then uses the <a class="el" href="classMessager.html">Messager</a>:popMessage() function to retrieve incoming control messages. This function does not block, instead returning a message type of zero when no more messages are in the queue. 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 SKINI 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 SKINI messages read from a SKINI file.<p>
|
||||
The class <a class="el" href="classstk_1_1Messager.html" title="STK input control message parser.">stk::Messager</a> can be used to acquire and parse MIDI messages from a MIDI device and SKINI messages from STDIN and socket connections. Incoming messages are acquired asynchronously and saved to an internal message queue of <a class="el" href="structstk_1_1Skini_1_1Message.html" title="A message structure to store and pass parsed SKINI messages.">stk::Skini::Message</a> types (MIDI messages are converted to the <a class="el" href="classstk_1_1Skini.html" title="STK SKINI parsing class.">stk::Skini</a>:Message format). The user then uses the <a class="el" href="classstk_1_1Messager.html" title="STK input control message parser.">stk::Messager</a>:popMessage() function to retrieve incoming control messages. This function does not block, instead returning a message type of zero when no more messages are in the queue. Many of the example programs included with the ToolKit distribution use a <a class="el" href="classstk_1_1Messager.html" title="STK input control message parser.">stk::Messager</a> instance to accept control input from the accompanying tcl/tk graphical user interfaces, from external MIDI devices, or from SKINI 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="classstk_1_1Messager.html" title="STK input control message parser.">stk::Messager</a> class to allow control via SKINI messages read from a SKINI file.<p>
|
||||
<div class="fragment"><pre class="fragment"><span class="comment">// controlbee.cpp STK tutorial program</span>
|
||||
|
||||
<span class="preprocessor">#include "BeeThree.h"</span>
|
||||
@@ -35,6 +36,8 @@ In the following example, we'll modify the <code>bethree.cpp</code> program from
|
||||
<span class="preprocessor">#include <algorithm></span>
|
||||
<span class="keyword">using</span> std::min;
|
||||
|
||||
<span class="keyword">using namespace </span>stk;
|
||||
|
||||
<span class="keywordtype">void</span> usage(<span class="keywordtype">void</span>) {
|
||||
<span class="comment">// Error function in case of incorrect command-line</span>
|
||||
<span class="comment">// argument specifications.</span>
|
||||
@@ -46,9 +49,9 @@ In the following example, we'll modify the <code>bethree.cpp</code> program from
|
||||
<span class="comment">// The TickData structure holds all the class instances and data that</span>
|
||||
<span class="comment">// are shared by the various processing functions.</span>
|
||||
<span class="keyword">struct </span>TickData {
|
||||
<a class="code" href="classInstrmnt.html">Instrmnt</a> *instrument;
|
||||
<a class="code" href="classMessager.html">Messager</a> messager;
|
||||
<a class="code" href="structSkini_1_1Message.html">Skini::Message</a> message;
|
||||
Instrmnt *instrument;
|
||||
Messager messager;
|
||||
Skini::Message message;
|
||||
<span class="keywordtype">int</span> counter;
|
||||
<span class="keywordtype">bool</span> haveMessage;
|
||||
<span class="keywordtype">bool</span> done;
|
||||
@@ -104,7 +107,7 @@ In the following example, we'll modify the <code>bethree.cpp</code> program from
|
||||
<span class="comment">// control updates. It will be called automatically when the system</span>
|
||||
<span class="comment">// needs a new buffer of audio samples.</span>
|
||||
<span class="keywordtype">int</span> tick( <span class="keywordtype">void</span> *outputBuffer, <span class="keywordtype">void</span> *inputBuffer, <span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> nBufferFrames,
|
||||
<span class="keywordtype">double</span> streamTime, <a class="code" href="RtAudio_8h.html#a11">RtAudioStreamStatus</a> status, <span class="keywordtype">void</span> *dataPointer )
|
||||
<span class="keywordtype">double</span> streamTime, <a class="code" href="RtAudio_8h.html#80e306d363583da3b0a1b65d9b57c806" title="RtAudio stream status (over- or underflow) flags.">RtAudioStreamStatus</a> status, <span class="keywordtype">void</span> *dataPointer )
|
||||
{
|
||||
TickData *data = (TickData *) dataPointer;
|
||||
<span class="keyword">register</span> StkFloat *samples = (StkFloat *) outputBuffer;
|
||||
@@ -115,7 +118,7 @@ In the following example, we'll modify the <code>bethree.cpp</code> program from
|
||||
<span class="keywordflow">if</span> ( !data->haveMessage ) {
|
||||
data->messager.popMessage( data->message );
|
||||
<span class="keywordflow">if</span> ( data->message.type > 0 ) {
|
||||
data->counter = (long) (data->message.time * <a class="code" href="classStk.html#e0">Stk::sampleRate</a>());
|
||||
data->counter = (long) (data->message.time * Stk::sampleRate());
|
||||
data->haveMessage = <span class="keyword">true</span>;
|
||||
}
|
||||
<span class="keywordflow">else</span>
|
||||
@@ -143,31 +146,31 @@ In the following example, we'll modify the <code>bethree.cpp</code> program from
|
||||
<span class="keywordflow">if</span> ( argc != 2 ) usage();
|
||||
|
||||
<span class="comment">// Set the global sample rate and rawwave path before creating class instances.</span>
|
||||
<a class="code" href="classStk.html#e1">Stk::setSampleRate</a>( 44100.0 );
|
||||
<a class="code" href="classStk.html#e3">Stk::setRawwavePath</a>( <span class="stringliteral">"../../rawwaves/"</span> );
|
||||
Stk::setSampleRate( 44100.0 );
|
||||
Stk::setRawwavePath( <span class="stringliteral">"../../rawwaves/"</span> );
|
||||
|
||||
TickData data;
|
||||
<a class="code" href="classRtAudio.html">RtAudio</a> dac;
|
||||
<a class="code" href="classRtAudio.html" title="Realtime audio i/o C++ classes.">RtAudio</a> dac;
|
||||
|
||||
<span class="comment">// Figure out how many bytes in an StkFloat and setup the RtAudio stream.</span>
|
||||
<a class="code" href="structRtAudio_1_1StreamParameters.html">RtAudio::StreamParameters</a> parameters;
|
||||
parameters.<a class="code" href="structRtAudio_1_1StreamParameters.html#o0">deviceId</a> = dac.<a class="code" href="classRtAudio.html#a5">getDefaultOutputDevice</a>();
|
||||
parameters.<a class="code" href="structRtAudio_1_1StreamParameters.html#o1">nChannels</a> = 1;
|
||||
<a class="code" href="RtAudio_8h.html#a0">RtAudioFormat</a> format = ( <span class="keyword">sizeof</span>(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
|
||||
<a class="code" href="structRtAudio_1_1StreamParameters.html" title="The structure for specifying input or ouput stream parameters.">RtAudio::StreamParameters</a> parameters;
|
||||
parameters.<a class="code" href="structRtAudio_1_1StreamParameters.html#ffd27496c70c0986522056234c64e28e">deviceId</a> = dac.<a class="code" href="classRtAudio.html#3a3f3dbe13ea696b521e49cdaaa357bc" title="A function that returns the index of the default output device.">getDefaultOutputDevice</a>();
|
||||
parameters.<a class="code" href="structRtAudio_1_1StreamParameters.html#78798b65fada7941e1a7e47c11c9e627">nChannels</a> = 1;
|
||||
<a class="code" href="RtAudio_8h.html#afca92882d25915560018873221e44b8" title="RtAudio data format type.">RtAudioFormat</a> format = ( <span class="keyword">sizeof</span>(StkFloat) == 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;
|
||||
<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> bufferFrames = RT_BUFFER_SIZE;
|
||||
<span class="keywordflow">try</span> {
|
||||
dac.<a class="code" href="classRtAudio.html#a7">openStream</a>( &parameters, NULL, format, (<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>)<a class="code" href="classStk.html#e0">Stk::sampleRate</a>(), &bufferFrames, &tick, (<span class="keywordtype">void</span> *)&data );
|
||||
dac.<a class="code" href="classRtAudio.html#facc99740fa4c5606fb35467cdea6da8" title="A public function for opening a stream with the specified parameters.">openStream</a>( &parameters, NULL, format, (<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span>)Stk::sampleRate(), &bufferFrames, &tick, (<span class="keywordtype">void</span> *)&data );
|
||||
}
|
||||
<span class="keywordflow">catch</span> ( <a class="code" href="classRtError.html">RtError</a> &error ) {
|
||||
error.<a class="code" href="classRtError.html#a2">printMessage</a>();
|
||||
<span class="keywordflow">catch</span> ( <a class="code" href="classRtError.html" title="Exception handling class for RtAudio &amp; RtMidi.">RtError</a> &error ) {
|
||||
error.<a class="code" href="classRtError.html#da41f7472122f45bc5b4677f066e0943" title="Prints thrown error message to stderr.">printMessage</a>();
|
||||
<span class="keywordflow">goto</span> cleanup;
|
||||
}
|
||||
|
||||
<span class="keywordflow">try</span> {
|
||||
<span class="comment">// Define and load the BeeThree instrument</span>
|
||||
data.instrument = <span class="keyword">new</span> <a class="code" href="classBeeThree.html">BeeThree</a>();
|
||||
data.instrument = <span class="keyword">new</span> BeeThree();
|
||||
}
|
||||
<span class="keywordflow">catch</span> ( <a class="code" href="classStkError.html">StkError</a> & ) {
|
||||
<span class="keywordflow">catch</span> ( StkError & ) {
|
||||
<span class="keywordflow">goto</span> cleanup;
|
||||
}
|
||||
|
||||
@@ -175,23 +178,23 @@ In the following example, we'll modify the <code>bethree.cpp</code> program from
|
||||
<span class="keywordflow">goto</span> cleanup;
|
||||
|
||||
<span class="keywordflow">try</span> {
|
||||
dac.<a class="code" href="classRtAudio.html#a9">startStream</a>();
|
||||
dac.<a class="code" href="classRtAudio.html#ec017a89629ccef66a90b60be22a2f80" title="A function that starts a stream.">startStream</a>();
|
||||
}
|
||||
<span class="keywordflow">catch</span> ( <a class="code" href="classRtError.html">RtError</a> &error ) {
|
||||
error.<a class="code" href="classRtError.html#a2">printMessage</a>();
|
||||
<span class="keywordflow">catch</span> ( <a class="code" href="classRtError.html" title="Exception handling class for RtAudio &amp; RtMidi.">RtError</a> &error ) {
|
||||
error.<a class="code" href="classRtError.html#da41f7472122f45bc5b4677f066e0943" title="Prints thrown error message to stderr.">printMessage</a>();
|
||||
<span class="keywordflow">goto</span> cleanup;
|
||||
}
|
||||
|
||||
<span class="comment">// Block waiting until callback signals done.</span>
|
||||
<span class="keywordflow">while</span> ( !data.done )
|
||||
<a class="code" href="classStk.html#e7">Stk::sleep</a>( 100 );
|
||||
Stk::sleep( 100 );
|
||||
|
||||
<span class="comment">// Shut down the output stream.</span>
|
||||
<span class="keywordflow">try</span> {
|
||||
dac.<a class="code" href="classRtAudio.html#a8">closeStream</a>();
|
||||
dac.<a class="code" href="classRtAudio.html#90d599002ad32cf250a4cb866f2cc93a" title="A function that closes a stream and frees any associated stream memory.">closeStream</a>();
|
||||
}
|
||||
<span class="keywordflow">catch</span> ( <a class="code" href="classRtError.html">RtError</a> &error ) {
|
||||
error.<a class="code" href="classRtError.html#a2">printMessage</a>();
|
||||
<span class="keywordflow">catch</span> ( <a class="code" href="classRtError.html" title="Exception handling class for RtAudio &amp; RtMidi.">RtError</a> &error ) {
|
||||
error.<a class="code" href="classRtError.html#da41f7472122f45bc5b4677f066e0943" title="Prints thrown error message to stderr.">printMessage</a>();
|
||||
}
|
||||
|
||||
cleanup:
|
||||
@@ -206,12 +209,13 @@ Assuming the program is compiled as <code>controlbee</code> and the SKINI scoref
|
||||
<div class="fragment"><pre class="fragment">controlbee scores/bookert.ski
|
||||
</pre></div><p>
|
||||
Only a few basic SKINI 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 pipe, socket or MIDI connections. The <a class="el" href="classMessager.html">Messager</a> class provides <a class="el" href="classMessager.html#a5">Messager::startStdInput()</a>, <a class="el" href="classMessager.html#a6">Messager::startSocketInput()</a>, and <a class="el" href="classMessager.html#a7">Messager::startMidiInput()</a> functions for this purpose.<p>
|
||||
[<a href="tutorial.html">Main tutorial page</a>] [<a href="multichannel.html">Next tutorial</a>] <HR>
|
||||
This example could also be easily extended to accept "realtime" control input messages via pipe, socket or MIDI connections. The <a class="el" href="classstk_1_1Messager.html" title="STK input control message parser.">stk::Messager</a> class provides <a class="el" href="classstk_1_1Messager.html#04c70f97c899b03f3b7c1158943106e3" title="Initiate the "realtime" retreival from stdin of control messages into the...">stk::Messager::startStdInput()</a>, <a class="el" href="classstk_1_1Messager.html#180fd45d109a2058ecbd6a629b979cb7" title="Start a socket server, accept connections, and read "realtime" control...">stk::Messager::startSocketInput()</a>, and <a class="el" href="classstk_1_1Messager.html#49877209a4ee08e684de82a73f2d9df9" title="Start MIDI input, with optional device and port identifiers.">stk::Messager::startMidiInput()</a> functions for this purpose.<p>
|
||||
[<a href="tutorial.html">Main tutorial page</a>] [<a href="multichannel.html">Next tutorial</a>] </div>
|
||||
<HR>
|
||||
|
||||
<table>
|
||||
<tr><td><A HREF="http://ccrma.stanford.edu/software/stk/"><I>The Synthesis ToolKit in C++ (STK)</I></A></td></tr>
|
||||
<tr><td>©1995-2007 Perry R. Cook and Gary P. Scavone. All Rights Reserved.</td></tr>
|
||||
<tr><td>©1995-2009 Perry R. Cook and Gary P. Scavone. All Rights Reserved.</td></tr>
|
||||
</table>
|
||||
|
||||
</BODY>
|
||||
|
||||
Reference in New Issue
Block a user