haiku-website/static/legacy-docs/bebook/BMidi_Overview.html

307 lines
32 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>The Be Book - System Overview - The Midi Kit</title><link rel="stylesheet" href="be_book.css" type="text/css" media="all" /><link rel="shortcut icon" type="image/vnd.microsoft.icon" href="./images/favicon.ico" /><!--[if IE]>
<link rel="stylesheet" type="text/css" href="be_book_ie.css" />
<![endif]--><meta name="generator" content="DocBook XSL Stylesheets V1.73.2" /><meta name="keywords" content="Access, BeOS, BeBook, API" /><link rel="start" href="index.html" title="The Be Book" /><link rel="up" href="TheMidiKit_Overview.html" title="The Midi Kit" /><link rel="prev" href="TheMidiKit_Introduction.html" title="Introduction" /><link rel="next" href="BMidiPort_Overview.html" title="BMidiPort" /></head><body><div id="header"><div id="headerT"><div id="headerTL"><a accesskey="p" href="TheMidiKit_Introduction.html" title="Introduction"><img src="./images/navigation/prev.png" alt="Prev" /></a> <a accesskey="u" href="TheMidiKit_Overview.html" title="The Midi Kit"><img src="./images/navigation/up.png" alt="Up" /></a> <a accesskey="n" href="BMidiPort_Overview.html" title="BMidiPort"><img src="./images/navigation/next.png" alt="Next" /></a></div><div id="headerTR"><div id="navigpeople"><a href="http://www.haiku-os.org"><img src="./images/People_24.png" alt="haiku-os.org" title="Visit The Haiku Website" /></a></div><div class="navighome" title="Home"><a accesskey="h" href="index.html"><img src="./images/navigation/home.png" alt="Home" /></a></div><div class="navigboxed" id="navigindex"><a accesskey="i" href="ClassIndex.html" title="Index">I</a></div><div class="navigboxed" id="naviglang" title="English">en</div></div><div id="headerTC">The Be Book - System Overview - The Midi Kit</div></div><div id="headerB">Prev: <a href="TheMidiKit_Introduction.html">Introduction</a>  Up: <a href="TheMidiKit_Overview.html">The Midi Kit</a>  Next: <a href="BMidiPort_Overview.html">BMidiPort</a></div><hr /></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h2 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BMidi_Overview"></a>BMidi</h2></div></div></div><a id="id592713" class="indexterm"></a><p><a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>
is an abstract class that defines protocols and default
implementations for functions that most of the other Midi Kit classes
inherit. The functions that
<a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>
defines fall into four categories:</p><dl class="variablelist"><dt><span class="term">Connection functions.</span></dt><dd><p>The connection functions let you connect the output of one
<a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>
object to the input of another
<a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>
object.</p></dd><dt><span class="term">Performance functions.</span></dt><dd><p><a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>
objects that generate MIDI data (by
reading from a port or file, as examples) implement the
<a class="link" href="BMidi.html#BMidi_Run" title="Run()"><code class="methodname">Run()</code></a>
hook function.
<a class="link" href="BMidi.html#BMidi_Run" title="Run()"><code class="methodname">Run()</code></a>
is the brains of a MIDI performance;
<a class="link" href="BMidi.html#BMidi_Start" title="Start()"><code class="methodname">Start()</code></a> and
<a class="link" href="BMidi.html#BMidi_Stop" title="Stop()"><code class="methodname">Stop()</code></a>
control the performance.</p></dd><dt><span class="term">"Spray" functions.</span></dt><dd><p>The "spray" functions send MIDI messages to each
of the objects that are connected to the output of the sprayer. There's
a spray function for each type of MIDI message; for example,
<a class="link" href="BMidi.html#BMidi_SprayNoteOn"><code class="methodname">SprayNoteOn()</code></a>
corresponds to MIDI's Note On message.</p></dd><dt><span class="term">"MIDI hook" functions.</span></dt><dd>
The "MIDI hook" functions define the object's
response to a particular type of MIDI message. There's a hook function
for each MIDI message
(<a class="link" href="BMidi.html#BMidi_NoteOn" title="NoteOn(), SprayNoteOn()"><code class="methodname">NoteOn()</code></a>,
<a class="link" href="BMidi.html#BMidi_NoteOff" title="NoteOff(), SprayNoteOff()"><code class="methodname">NoteOff()</code></a>,
etc.). The hook functions
are invoked automatically as "upstream" objects call the corresponding
spray functions.
</dd></dl><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BMidi_Overview_FormingConnections"></a>Forming Connections</h3></div></div></div><p>MIDI data streams through your application, passing from one
<a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>-derived
object to another. Each object does whatever it's designed
to do: Sends the data to a MIDI port, writes it to a file, modifies it
and passes it on, and so on.</p><p>You form a tree of
<a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>
objects through <a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>'s
<a class="link" href="BMidi.html#BMidi_Connect" title="Connect()"><code class="methodname">Connect()</code></a>
function, which takes a single
<a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>
argument. By calling
<a class="link" href="BMidi.html#BMidi_Connect" title="Connect()"><code class="methodname">Connect()</code></a>,
you connect the output of the calling object to the input of the argument object.
(i.e. the caller is the source; the argument is the destination.)</p><p>Let's say you want to connect a MIDI keyboard to your computer, play it,
and have the performance recorded in a file. You connect a
<a class="link" href="BMidiPort.html" title="BMidiPort"><code class="classname">BMidiPort</code></a>
object, which reads data from the MIDI port, to a
<a class="link" href="BMidiStore.html" title="BMidiStore"><code class="classname">BMidiStore</code></a> object,
which stores the data that's sent to it and can write it to a file:</p><pre class="programlisting example cpp"><span class="comment">/* Connect the output of a BMidiPort to the input of a BMidiStore. */</span>
<code class="classname">BMidiPort</code> <code class="varname">m_port</code>;
<code class="classname">BMidiStore</code> <code class="varname">m_store</code>;
<code class="varname">m_port</code>.<code class="methodname">Connect</code>(&amp;<code class="varname">m_store</code>);</pre><p>You also have to tell the
<a class="link" href="BMidiPort.html" title="BMidiPort"><code class="classname">BMidiPort</code></a>
to start listening to the MIDI port,
by calling its
<a class="link" href="BMidi.html#BMidi_Start" title="Start()"><code class="methodname">Start()</code></a>
function. This is explained in a later section.</p><p>Once you've made the recording, you can play it back by re-connecting the
objects in the opposite direction:</p><pre class="programlisting example cpp"><span class="comment">/* We'll disconnect first, although this isn't strictly necessary. */</span>
<code class="varname">m_port</code>.<code class="methodname">Disconnect</code>(&amp;<code class="varname">m_store</code>);
<code class="varname">m_store</code>.<code class="methodname">Connect</code>(&amp;<code class="varname">m_port</code>);</pre><p>In this configuration, a
<a class="link" href="BMidi.html#BMidi_Start" title="Start()"><code class="methodname">Start()</code></a>
call to <code class="varname">m_store</code> would cause its MIDI
data to flow into the
<a class="link" href="BMidiPort.html" title="BMidiPort"><code class="classname">BMidiPort</code></a>
(and thence to a synthesizer, for example, for realization).</p><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h4 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BMidi_Overview_SourcesAndDestinations"></a>Sources and Destinations</h4></div></div></div><p>A <a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>
object can be the source for any number of other objects:</p><pre class="programlisting example cpp"><code class="varname">a_midi</code>.<code class="methodname">Connect</code>(&amp;<code class="varname">b_object</code>);
<code class="varname">a_midi</code>.<code class="methodname">Connect</code>(&amp;<code class="varname">c_object</code>);
<code class="varname">a_midi</code>.<code class="methodname">Connect</code>(&amp;<code class="varname">d_object</code>);</pre><p>A source can get a list of its destinations through the
<a class="link" href="BMidi.html#BMidi_Connections" title="Connections()"><code class="methodname">Connections()</code></a>
function.</p><p>A BMidi object can be the destination for any number of sources:</p><pre class="programlisting example cpp"><code class="varname">b_midi</code>.<code class="methodname">Connect</code>(&amp;<code class="varname">e_object</code>);
<code class="varname">c_midi</code>.<code class="methodname">Connect</code>(&amp;<code class="varname">e_object</code>);
<code class="varname">d_midi</code>.<code class="methodname">Connect</code>(&amp;<code class="varname">e_object</code>);</pre><p>However, a destination can't get a list of its sources.</p></div></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BMidi_Overview_GeneratingMIDIMessages"></a>Generating MIDI Messages</h3></div></div></div><p>If your class wants to generate new MIDI data (as opposed to filtering or
realizing the data it receives), it must implement the
<a class="link" href="BMidi.html#BMidi_Run" title="Run()"><code class="methodname">Run()</code></a>
function. An implementation of
<a class="link" href="BMidi.html#BMidi_Run" title="Run()"><code class="methodname">Run()</code></a>
should include a <span class="code">while()</span> loop that broadcasts one
or more MIDI message on each pass (typically it broadcasts only one), by
invoking a spray function. To predicate the loop you must test the value
of the
<a class="link" href="BMidi.html#BMidi_KeepRunning" title="KeepRunning()"><code class="methodname">KeepRunning()</code></a>
boolean function.</p><p>The outline of a
<a class="link" href="BMidi.html#BMidi_Run" title="Run()"><code class="methodname">Run()</code></a>
implementation looks like this:</p><pre class="programlisting example cpp"><span class="type">void</span> <code class="classname">MyMidi</code>::<code class="methodname">Run</code>()
{
while (<code class="methodname">KeepRunning</code>()) {
<span class="comment">/* Generate a message and spray it. For example... */</span>
<code class="methodname">SprayNoteOn</code>(...);
}
<span class="comment">/* You MUST exit when KeepRunning() returns false. */</span>
}</pre><div class="admonition warning"><div class="title">Warning</div><div class="graphic"><img class="icon" alt="Warning" width="32" src="./images/admonitions/Stop_32.png" /><div class="text"><p>The <a class="link" href="BMidi.html#BMidi_Run" title="Run()"><code class="methodname">Run()</code></a>
function <span class="emphasis"><em>must</em></span> exit when
<a class="link" href="BMidi.html#BMidi_KeepRunning" title="KeepRunning()"><code class="methodname">KeepRunning()</code></a>
returns <code class="constant">false</code>. If it doesn't, you'll leak threads.</p></div></div></div><p>To tell an object to perform its
<a class="link" href="BMidi.html#BMidi_Run" title="Run()"><code class="methodname">Run()</code></a>
function, you call the object's
<a class="link" href="BMidi.html#BMidi_Start" title="Start()"><code class="methodname">Start()</code></a>
function—you never call
<a class="link" href="BMidi.html#BMidi_Run" title="Run()"><code class="methodname">Run()</code></a>
directly.
<a class="link" href="BMidi.html#BMidi_Start" title="Start()"><code class="methodname">Start()</code></a>
causes the object to spawn a thread (its "run" thread) and execute
<a class="link" href="BMidi.html#BMidi_Run" title="Run()"><code class="methodname">Run()</code></a>
within it. When you're tired of the object's performance, you call its
<a class="link" href="BMidi.html#BMidi_Stop" title="Stop()"><code class="methodname">Stop()</code></a>
function.</p><p>Keep in mind that the
<a class="link" href="BMidi.html#BMidi_Run" title="Run()"><code class="methodname">Run()</code></a>
function is only needed in classes that
introduce new MIDI data into a performance. As examples,
<a class="link" href="BMidiStore.html" title="BMidiStore"><code class="classname">BMidiStore</code></a>'s
<a class="link" href="BMidi.html#BMidi_Run" title="Run()"><code class="methodname">Run()</code></a>
sprays messages that correspond to the MIDI data that it stores,
and <a class="link" href="BMidiPort.html" title="BMidiPort"><code class="classname">BMidiPort</code></a>
reads data from the MIDI port and sprays messages accordingly.</p><p>Another point to keep in mind is that the
<a class="link" href="BMidi.html#BMidi_Run" title="Run()"><code class="methodname">Run()</code></a>
function can run ahead of
real time. It doesn't have to generate and spray data precisely at the
moment that the data needs to be realized. This is further explained in
the section
"<a class="xref" href="BMidi_Overview.html#BMidi_Overview_Time" title="Time">Time</a>".</p><div class="admonition note"><div class="title">Note</div><div class="graphic"><img class="icon" alt="Note" width="32" src="./images/admonitions/Info_32.png" /><div class="text"><p>The
<a class="link" href="BMidiSynthFile.html" title="BMidiSynthFile"><code class="classname">BMidiSynthFile</code></a>
class differs from the other classes in the way that
it implements and uses its
<a class="link" href="BMidi.html#BMidi_Run" title="Run()"><code class="methodname">Run()</code></a>
function; in particular, it doesn't
spawn a run thread. See the
<a class="link" href="BMidiSynthFile.html" title="BMidiSynthFile"><code class="classname">BMidiSynthFile</code></a>
class for more information.</p></div></div></div></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BMidi_Overview_SprayFunctions"></a>Spray Functions</h3></div></div></div><p>The spray functions send data to the
<a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>
objects that are connected to
the running object's output. There's a separate spray function for each
of the MIDI message types:
<a class="link" href="BMidi.html#BMidi_SprayNoteOn"><code class="methodname">SprayNoteOn()</code></a>,
<a class="link" href="BMidi.html#BMidi_SprayNoteOff"><code class="methodname">SprayNoteOff()</code></a>,
<a class="link" href="BMidi.html#BMidi_SprayPitchBend"><code class="methodname">SprayPitchBend()</code></a>,
and so on. Spray functions are always found within a
<a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>'s
<a class="link" href="BMidi.html#BMidi_Run" title="Run()"><code class="methodname">Run()</code></a>
loop, but they can be found in other places as well. For
example, if you're creating a MIDI filter, you would use spray functions
in the implementations of the object's MIDI hook functions (as explained
next).</p></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BMidi_Overview_MIDIHookFunctions"></a>MIDI Hook Functions</h3></div></div></div><p>The MIDI hook functions are hooks that are invoked upon an object's
connections when the object sprays MIDI data. The functions take the
names of the MIDI messages to which they respond:
<a class="link" href="BMidi.html#BMidi_NoteOn" title="NoteOn(), SprayNoteOn()"><code class="methodname">NoteOn()</code></a>
responds to a Note On message,
<a class="link" href="BMidi.html#BMidi_NoteOff" title="NoteOff(), SprayNoteOff()"><code class="methodname">NoteOff()</code></a>
responds to a Note Off, and so on. For example, this…</p><pre class="programlisting example cpp"><code class="varname">a_midi</code>.<code class="methodname">Connect</code>(&amp;<code class="varname">b_midi</code>);
<code class="varname">a_midi</code>.<code class="methodname">SprayNoteOn</code>(...);</pre><p>…causes <code class="varname">b_midi</code>'s
<a class="link" href="BMidi.html#BMidi_NoteOn" title="NoteOn(), SprayNoteOn()"><code class="methodname">NoteOn()</code></a>
function to be invoked. The arguments that are passed to
<a class="link" href="BMidi.html#BMidi_NoteOn" title="NoteOn(), SprayNoteOn()"><code class="methodname">NoteOn()</code></a>
are taken directly from the
<a class="link" href="BMidi.html#BMidi_SprayNoteOn"><code class="methodname">SprayNoteOn()</code></a>
call.</p><p><a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>
doesn't provide default implementations for any of the MIDI hooks;
it's up to each
<a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>-derived
class to decide how to respond to MIDI messages.</p><p>Every <a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>
object automatically spawns an "inflow" thread when it's
constructed. It's in this thread that the spray-invoked MIDI hooks are
executed. The inflow thread is always running—the
<a class="link" href="BMidi.html#BMidi_Start" title="Start()"><code class="methodname">Start()</code></a> and
<a class="link" href="BMidi.html#BMidi_Stop" title="Stop()"><code class="methodname">Stop()</code></a>
functions don't affect it. As soon as you construct an object,
it's ready to receive data.</p><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h4 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BMidi_Overview_CallingMIDIHooksDirectly"></a>Calling MIDI Hooks Directly</h4></div></div></div><p>You can also feed MIDI data to a
<a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>
object by invoking the MIDI hook
functions directly. For example, let's say you just want to play a note
on the General MIDI synthesizer. You don't have to create your own
<a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>
class simply to implement a
<a class="link" href="BMidi.html#BMidi_Run" title="Run()"><code class="methodname">Run()</code></a>
function that sprays the note; instead, all you have to do is this:</p><pre class="programlisting example cpp"><code class="classname">BMidiSynth</code> <code class="varname">midiSynth</code>;
<span class="comment">/* Initialize the BMidiSynth as described in that class. */</span>
...
<span class="comment">/* Play a note. */</span>
<code class="varname">midiSynth</code>.<code class="methodname">NoteOn</code>(...);</pre><p>Keep in mind that when you invoke a hook function directly, it executes
synchronously in the calling thread. Furthermore, the object may also be
receiving MIDI messages in its inflow thread. For the Midi Kit-defined
classes, this isn't a problem.</p></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h4 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BMidi_Overview_CreatingAMIDIFilter"></a>Creating a MIDI Filter</h4></div></div></div><p>Some BMidi objects "act as filters: They receive data, modify it, and
then pass it on. To do this, you call the appropriate spray functions
from within the implementations of the MIDI hooks. Below is the
implementation of the NoteOn() function for a proposed class called
Transposer. It takes each Note On, transposes it up a half step, and then
sprays it:</p><pre class="programlisting example cpp"><span class="type">void</span> <code class="classname">Transposer</code>::<code class="methodname">NoteOn</code>(<span class="type">uchar</span> <code class="parameter">channel</code>, <span class="type">uchar</span> <code class="parameter">keyNumber</code>,
<span class="type">uchar</span> <code class="parameter">velocity</code>, <span class="type">uint32</span> <code class="parameter">time</code>)
{
<span class="type">uchar</span> <code class="varname">new_key</code> = <code class="function">max</code>(<code class="parameter">keyNumber</code> + 1, 127);
<code class="methodname">SprayNoteOn</code>(<code class="parameter">channel</code>, <code class="varname">new_key</code>, <code class="parameter">velocity</code>, <code class="parameter">time</code>);
}</pre><p>There's a subtle but important distinction between a filter class and a
"performance" class (where the latter is a class that's designed to
actually realize the MIDI data it receives). The distinction has to do
with time, and is explained in the next section. An implication of the
distinction that affects the current discussion is that it may not be a
great idea to invest, in a single object, the ability to filter and
perform MIDI data. Both
<a class="link" href="BMidiStore.html" title="BMidiStore"><code class="classname">BMidiStore</code></a> and
<a class="link" href="BMidiPort.html" title="BMidiPort"><code class="classname">BMidiPort</code></a>
are performance classes—objects of these classes realize the data they receive, the
former by caching it, the latter by sending it out the MIDI port. In
neither of these classes do the MIDI hooks spray data.</p></div></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BMidi_Overview_Time"></a>Time</h3></div></div></div><p>Every spray and MIDI hook function takes a final time argument. This
argument declares when the message that the function represents should be
performed. The argument is given in ticks (milliseconds). Tick 0 occurs
when you boot your computer; the tick counter automatically starts
running at that point. To get the current tick measurement, you call the
global, Kernel Kit-defined
<a class="link" href="TheKernelKit_Time.html#system_time" title="system_time()"><code class="function">system_time()</code></a>
function and divide by 1000
(<a class="link" href="TheKernelKit_Time.html#system_time" title="system_time()"><code class="function">system_time()</code></a>
returns microseconds).</p><p>By convention, time arguments are applied at an object's input. In other
words, a MIDI hook should look at the time argument, wait until the
designated time, and then do whatever it does that it does do. However,
this only applies to
<a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>-derived
classes that are designed to perform
MIDI data. Objects that simply filter data shouldn't apply the time
argument.</p><p>To apply the time argument, you call the
<a class="link" href="BMidi.html#BMidi_SnoozeUntil" title="SnoozeUntil()"><code class="methodname">SnoozeUntil()</code></a>
function, passing
the value of time. For example, a "performance"
<a class="link" href="BMidi.html#BMidi_NoteOn" title="NoteOn(), SprayNoteOn()"><code class="methodname">NoteOn()</code></a>
function would look like this:</p><pre class="programlisting example cpp"><span class="type">void</span> <code class="classname">MyPerformer</code>::<code class="methodname">NoteOn</code>(<span class="type">uchar</span> <code class="parameter">channel</code>, <span class="type">uchar</span> <code class="parameter">keyNumber</code>,
<span class="type">uchar</span> <code class="parameter">velocity</code>, <span class="type">uint32</span> <code class="parameter">time</code>)
{
<code class="methodname">SnoozeUntil</code>(<code class="parameter">time</code>);
<span class="comment">/* Perform the data here. */</span>
}</pre><p>If time designates a tick that has already tocked,
<a class="link" href="BMidi.html#BMidi_SnoozeUntil" title="SnoozeUntil()"><code class="methodname">SnoozeUntil()</code></a>
returns immediately; otherwise it tells the inflow thread to snooze until the
designated tick is at hand.</p></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><hr /><div xmlns:d="http://docbook.org/ns/docbook"><h3 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BMidi_Overview_SprayingTime"></a>Spraying Time</h3></div></div></div><p>If you're implementing the
<a class="link" href="BMidi.html#BMidi_Run" title="Run()"><code class="methodname">Run()</code></a>
function, then you have to generate a
time value yourself which you pass as the final argument to each spray
function that you call. The value you generate depends on whether your
class runs in real time, or ahead of time.</p><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h4 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BMidi_Overview_RunningInRealTime"></a>Running in Real Time</h4></div></div></div><p>If your class conjures MIDI data that needs to be performed immediately,
you should use the <code class="function">B_NOW</code> macro as the value of the time arguments that
you pass to your spray functions. <code class="function">B_NOW</code> is simply a cover for
(<a class="link" href="TheKernelKit_Time.html#system_time" title="system_time()"><code class="function">system_time()</code></a>/1000)
(converted to <span class="type">uint</span>). By using <code class="function">B_NOW</code> as the time
argument you're declaring that the data should be performed in the same
tick in which it was generated. This probably won't happen; by the time
the MIDI hooks are called and the data realized, a couple of ticks may
have elapsed. In this case, the MIDI hooks'
<a class="link" href="BMidi.html#BMidi_SnoozeUntil" title="SnoozeUntil()"><code class="methodname">SnoozeUntil()</code></a>
calls will see
that the time value has passed and will return immediately, allowing the
data to be realized as quickly as possible.</p></div><div class="section"><div xmlns="" xmlns:d="http://docbook.org/ns/docbook" class="titlepage"><div><div xmlns:d="http://docbook.org/ns/docbook"><h4 xmlns="http://www.w3.org/1999/xhtml" class="title"><a id="BMidi_Overview_RunningAheadOfTime"></a>Running Ahead of Time</h4></div></div></div><p>If you're generating data ahead of its performance time, you need to
compute the time value so that it pinpoints the correct time in the
future. For example, if you want to create a class that generates a note
every 100 milliseconds, you need to do something like this:</p><pre class="programlisting example cpp"><span class="type">void</span> <code class="classname">MyTicker</code>::<code class="methodname">Run</code>()
{
<span class="type">uint32</span> <code class="varname">when</code> = <code class="function">B_NOW</code>;
<span class="type">uchar</span> <code class="varname">key_num</code>;
while (<code class="methodname">KeepRunning</code>()) {
<span class="comment">/* Make a new note. */</span>
<code class="methodname">SprayNoteOn</code>(1, 60, 64, <code class="varname">when</code>);
<span class="comment">/* Turn the note off 99 ticks later. */</span>
<code class="varname">when</code> += 99;
<code class="methodname">SprayNoteOff</code>(1, 60, 0, <code class="varname">when</code>);
<span class="comment">/* Bump the when variable so the next Note On
* will be 100 ticks after this one.
*/</span>
<code class="varname">when</code> += 1;
}
}</pre><p>When a <code class="classname">MyTicker</code> object is told to start running, it generates a sequence
of Note On/Note Off pairs, and sprays them to its connected objects.
Somewhere down the line, a performance object will apply the time value
by calling
<a class="link" href="BMidi.html#BMidi_SnoozeUntil" title="SnoozeUntil()"><code class="methodname">SnoozeUntil()</code></a>.</p><p>But what keeps <code class="classname">MyTicker</code> from running wild and generating thousands or
millions of notes—which aren't scheduled to be played for
hours—as fast as possible? It's because the spray functions pass
data to the MIDI hooks through Kernel Kit ports that are 1 (one) message
deep. So, as long as one of the MIDI hooks calls
<a class="link" href="BMidi.html#BMidi_SnoozeUntil" title="SnoozeUntil()"><code class="methodname">SnoozeUntil()</code></a>,
the spraying object will never be more than one message ahead.</p><p>A useful feature of this mechanism is that if you connect a series of
<a class="link" href="BMidi.html" title="BMidi"><code class="classname">BMidi</code></a>
object that don't invoke
<a class="link" href="BMidi.html#BMidi_SnoozeUntil" title="SnoozeUntil()"><code class="methodname">SnoozeUntil()</code></a>,
you can process MIDI data
faster than real-time. For example, let's say you want to spray data from
one
<a class="link" href="BMidiStore.html" title="BMidiStore"><code class="classname">BMidiStore</code></a>
object, pass the data through a filter, and then store it in another
<a class="link" href="BMidiStore.html" title="BMidiStore"><code class="classname">BMidiStore</code></a>.
The <a class="link" href="BMidiStore.html" title="BMidiStore"><code class="classname">BMidiStore</code></a>
MIDI hooks don't call
<a class="link" href="BMidi.html#BMidi_SnoozeUntil" title="SnoozeUntil()"><code class="methodname">SnoozeUntil()</code></a>;
thus, data will flow out of the first object, through the
filter, and into its destination as quickly as possible, allowing you to
process hours of real-time data in just a few seconds. Of course, if you
add a performance object into this mix (so you can hear the data while
it's being processed), the data flow will be tethered, as described above.</p></div></div></div><div id="footer"><hr /><div id="footerT">Prev: <a href="TheMidiKit_Introduction.html">Introduction</a>  Up: <a href="TheMidiKit_Overview.html">The Midi Kit</a>  Next: <a href="BMidiPort_Overview.html">BMidiPort</a> </div><div id="footerB"><div id="footerBL"><a href="TheMidiKit_Introduction.html" title="Introduction"><img src="./images/navigation/prev.png" alt="Prev" /></a> <a href="TheMidiKit_Overview.html" title="The Midi Kit"><img src="./images/navigation/up.png" alt="Up" /></a> <a href="BMidiPort_Overview.html" title="BMidiPort"><img src="./images/navigation/next.png" alt="Next" /></a></div><div id="footerBR"><div><a href="http://www.haiku-os.org"><img src="./images/People_24.png" alt="haiku-os.org" title="Visit The Haiku Website" /></a></div><div class="navighome" title="Home"><a accesskey="h" href="index.html"><img src="./images/navigation/home.png" alt="Home" /></a></div></div><div id="footerBC"><a href="http://www.access-company.com/home.html" title="ACCESS Co."><img alt="Access Company" src="./images/access_logo.png" /></a></div></div></div><div id="licenseFooter"><div id="licenseFooterBL"><a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/" title="Creative Commons License"><img alt="Creative Commons License" style="border-width:0" src="https://licensebuttons.net/l/by-nc-nd/3.0/88x31.png" /></a></div><div id="licenseFooterBR"><a href="./LegalNotice.html">Legal Notice</a></div><div id="licenseFooterBC"><span id="licenseText">This work is licensed under a
<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/3.0/">Creative
Commons Attribution-Non commercial-No Derivative Works 3.0 License</a>.</span></div></div></body></html>