<?xml version='1.0' encoding='UTF-8'?>

<?xml-stylesheet href="./_c74_tut.xsl" type="text/xsl"?>
<chapter name="Tutorial 26: MIDI Control of Video">
<setdocpatch name="26jMIDIControl" patch="26jMIDIControl.maxpat"/>

<previous name="jitterchapter25">Tracking the Position of a Color in a Movie</previous>
<next name="jitterchapter27">Using MSP Audio in a Jitter Matrix</next>
<parent name="jitindex">Jitter Tutorials</parent>



<h1>Tutorial 26: MIDI Control of Video</h1>
<h2>The MIDI&#x2013;Video Relationship</h2>
<p>When Max was first developed it was mainly for the interactive control of musical instruments via MIDI. As computer processor speeds increased, it became practical to use Max for processing audio signals directly with MSP, and to process large matrices of data such as video images with Jitter. The great power of Max is that it gives you access to all of the digital information in each of these domains &#x2014;MIDI, audio, and video&#x2014;and helps you program interesting correlations between them. This tutorial will focus on using incoming MIDI data to control aspects of video playback in Jitter.</p>

<p>The two main benefits of using MIDI for controlling video are 1) the advantage of using a physical interface&#x2014;a slider, wheel, etc.&#x2014;rather than a mouse dragging an onscreen control, and b) the potential to make interesting relationships between music and video in realtime performance. There are many available MIDI controllers that provide useful physical interfaces for video: banks of multiple sliders on fader boxes or digital mixers, jog wheels, etc. Even most synthesizer keyboards have buttons, sliders, wheels, and foot pedals in addition to the obvious piano-like keys. For this tutorial we'll limit ourselves to the controls that are commonly available on most MIDI keyboards.</p>

<p>This tutorial makes the assumption that you have a 61-key MIDI synthesizer keyboard with a modulation wheel and a pitchbend wheel connected to your MIDI interface.</p>

<p>In this tutorial patch we'll play a movie, we'll use the notes from the MIDI keyboard to move around in the movie, and we'll use various types of MIDI messages to apply effects to the video and modify it in real time.</p>

<h2>Mapping MIDI Data for Use as Video Control Parameters</h2>
<p>The data in MIDI channel messages (notes, pitchbend, aftertouch, etc.) is in the range 0 to 127. For the most part, the attributes of Jitter objects expect arguments in the range 0 to 1&#x2014;especially when handling 4-plane 2D matrices of <i>char</i> data, as with video. So one of the first tasks we need to do is map the MIDI data into the appropriate range for controlling parameters of the Jitter objects. In the tutorial patch we show some examples of how to do this.</p>


<p>In the yellow portion of the patch we have various MIDI input objects, for gathering the data generated by a keyboard controller attached to <o>ctlin</o> <m>1</m> for the modulation wheel, <o>ctlin</o> <m>7</m> for the volume pedal, <o>bendin</o> for the pitchbend wheel, and <o>notein</o>  for the keyboard. (If necessary,double click on the above objects to choose a MIDI port.) The most straightforward controls for our use are continuous controllers like the mod wheel and the volume pedal. It's a simple matter to map their values into the 0 to 1 range, just by dividing by 127.0. </p>

<illustration><img src="images/jitterchapter26a.png"/>Map MIDI control data into a more useful 0-to-1 range</illustration>

<p>Even though both controllers have a range from 0 to 127, the mod wheel's normal resting position is at 0 (modulation off), while the volume pedal's usual resting position is at some non-zero position such as 100 or 127 (volume on). Thus, they might be useful to us in slightly different ways for controlling video effects.</p>

<p>The pitchbend wheel uses still another normal position. It's resting position is at 64, and it springs back to that position when released by the user. So we want it to give us a value of 0.5 when at rest. The problem is that 64 is not <i>exactly</i> half way between 0 and 127; if we simply divide by 127, a bend value of 64 will give us a result of about 0.504. So we have to treat the <i>downward bend</i>  and <i>upward bend</i> values differently, as shown in the following example.</p>

<illustration><img src="images/jitterchapter26b.png"/>There are 64 pitchbend values below the central value, and 63 above the center.</illustration>
<p>For the pitch information from the keyboard, the problem is a bit more complicated. First of all, most keyboards do not have keys for all pitches 0 to 127; the normal 5-octave keyboard sends out MIDI key numbers 36 to 96. But even more importantly, we're usually concerned not only with pitch "height" (where it lies in the 0 to 127 range), but also the musical significance of the pitch <i>class</i>  (C, C#, D, etc.). In our patch, we use both ways of viewing pitch. We map the key range 36 to 96 into the 0-to-1 parameter range, and we derive the pitch class with a <o>%</o> <m>12</m> object. (All <i>C</i>s will be <m>0</m>, all <i>C#</i>s will be <m>1</m>, etc.)</p>

<illustration><img src="images/jitterchapter26c.png"/>Using the note-on key value to derive pitch height and pitch class</illustration>
<p>In the above example we use a couple of other handy objects to thin out the incoming note data. The <o>poly</o> <m>1 1</m> object allows only one note-on message to go through at a time; it turns off the preceding note (sends it out with a velocity of <m>0</m>) before passing the new note through. That's because we only want to try to track one key number at a time. If the user plays with <i>legato</i> technique (plays a note before releasing the previous one) or plays several notes in a chord "simultaneously" (i.e., nearly simultaneously; nothing is really simultaneous in MIDI) it might be hard to tell which note our patch is actually tracking. The <o>poly</o> <m>1 1</m> object ensures that all notes except the most recently played one will be turned off in our patch, even if the notes are still being held down on the actual MIDI keyboard. The <o>stripnote</o> object suppresses note-off messages, so only the note-on key numbers will get through. We don't want to track the pitches as the notes are being turned off, we only want the get the key number when the note is first played.</p>

<div>
<techdetail>Note: We've set up the patch so that you don't <i>really</i> need a MIDI keyboard to try it out. You can play (silent) pseudo-notes by clicking on the keys of the <o>kslider</o> object, and you can generate other values by dragging on the <o>number</o> boxes labeled <i>Mod.</i>, <i>Vol.</i>, <i>Bend</i>, <i>Key</i>, and <i>Vel</i>. Needless to say, the mouse will be a bit less gratifying than a MIDI keyboard as a physical interface, but you can at least test the patch and try out the things that are explained in this chapter.</techdetail>
</div>
<bullet>Try out your MIDI keyboard (and wheels) to verify that MIDI messages are getting into Max OK. If not, double-click on the MIDI input objects to select the proper input device.</bullet>
<h2>Using <m>send</m> and <m>receive</m></h2>
<p>The workings of this patch may be a bit difficult to follow because we make liberal use of the <o>send</o> and <o>receive</o> objects. We do this mainly to avoid what would otherwise be a ludicrous mess of patch cords. It's particularly appropriate here because we'll be sending so many messages into and out of the <o>jit.movie</o> object from/to so many other places in the patch. So we use <o>receive</o> and <o>send</o> objects for the input and output of the <o>jit.movie</o> object, and all other objects in the patch can now communicate with it remotely.</p>

<illustration><img src="images/jitterchapter26d.png"/>We can communicate with <o>jit.movie</o> no matter where it's located.</illustration>
<p>Just in case you're not familiar with the use of a semicolon (<m>;</m>) in a <o>message</o> box, we'll take a moment to point out that you can put a semicolon, the name of a <o>receive</o> object, and a message in a <o>message</o> box, and when that <o>message</o> box is triggered it will function exactly as if you had sent that message into a <o>send</o> object. See the following example.</p>

<illustration><img src="images/jitterchapter26e.png"/>A semicolon in a <o>message</o> box is like using a <o>send</o> object.</illustration>
<p>So, let's trace what happens when we send a read message to <o>jit.movie</o>.</p>

<bullet>Click on the red <o>message</o> box that says <m>;</m> movieA read blading.mov; movieA vol 0.</bullet>
<p>This opens the movie <i>blading.mov</i>. When <o>jit.movie</o> has completed the  movie-opening operation, it sends a <m>read</m> message out its right outlet. If it opened the file successfully, the full message will be <m>read blading.mov 1</m>. (If it was unsuccessful, the last argument will not be <m>1</m>.) This message gets sent to the <o>receive</o> <m>Arightoutlet</m> object in the purple region in the bottom-left corner of the patch. We use the <o>route</o> objects to detect all the messages we expect to get out of that outlet and route the messages to the proper places elsewhere in the patch. The arguments of the <m>read</m> message get sent to the <link name="receive" type="refpage">r</link> <m>read</m> object in the green region in the bottom-right corner of the patch. With the <o>zl</o> <m>ecils 1</m> and <link name="select" type="refpage">sel</link> <m>1</m> objects we check to see if the last argument of the message was a <m>1</m>. If so, that means that the read was successful, so we then go ahead and get the movie's attributes.</p>

<illustration><img src="images/jitterchapter26f.png"/>If the movie was read in successfully, get its <m>framecount</m>, <m>fps</m>, <m>rate</m>, and <m>dim</m> attributes.</illustration>
<p>The remainder of the <m>read</m> message will be the name of the movie file, so we put that into a <o>message</o> box to show the user what file is now playing. If the read was unsuccessful, the <link name="select" type="refpage">sel</link> <m>1</m>object will trigger the message <m>failed to read movie</m> instead. (The <o>delay</o> object is there to ensure that the failure message gets put into the message box <i>after</i> the filename.)</p>

<h2>Using MIDI Notes to Trigger Video Clips</h2>
<p>We have chosen to use the pitch class of the note played on the MIDI keyboard to decide where to go in the video. (There are, of course, many ways you could choose to use MIDI to navigate through a movie or select different video segments. This just happens to be the method we've picked for this tutorial. In a later tutorial chapter we demonstrate how to switch from one video to another.) So, we take the total number of frames in the movie (the <m>framecount</m> attribute of <o>jit.movie</o>) and divide that by 12. We then use each note's pitch class (<i>key % 12</i>) to leap to a certain twelfth of the movie.</p>

<p>The movie <i>blading.mov</i> is a 12-second long video consisting of twelve 1-second edits. So in this case each different pitch class takes us to a different scene of this short movie. (Of course, that's all very neat and convenient since we planned it that way.  But by using the movie's actual <m>framecount</m>, we've made it so our patch will successfully divide a movie of <i>any</i> length into twelfths.)</p>

<illustration><img src="images/jitterchapter26g.png"/>The pitch class (5) of F above middle C takes us to frame 75, 5/12 into the movie.</illustration>
<p>The note-on velocity will turn on the <o>toggle</o> that starts the <o>metro</o> that <m>bang</m>s the <o>jit.movie</o> object, and the note-off velocity will stop the <o>metro</o>.</p>

<bullet>Click on the <o>toggle</o> labeled <i>Show/Hide Display Window</i> make the <i>Display</i> window visible. Play some notes on your MIDI keyboard (or click on the <o>kslider</o>) to leap to different points in the movie.</bullet>
<p>The <o>jit.movie</o> object's matrices go to a <o>send</o> <m>Aleftoutlet</m> object, and eventually get to the <o>jit.pwindow</o> via a <o>receive</o> <m>display</m> object. Where do the <m>jit_matrix</m> messages go between <o>send</o> <m>Aleftoutlet</m> and <o>receive</o> <m>display</m>? They actually go into a subpatch for video effects processing. But before we examine that subpatch, we'll discuss how we intend to control those effects.</p>

<h2>Routing Control Information</h2>
<p>Earlier in this chapter we saw the various ways that the incoming MIDI data gets mapped into the 0-to-1 range for use in controlling Jitter attributes. If you look in the yellow region of the patch, you can see that that control information goes to five <o>send</o> objects: <link name="send" type="refpage">s</link> <m>pitch</m>, <link name="send" type="refpage">s</link> <m>vel</m>, <link name="send" type="refpage">s</link> <m>bend</m>, <link name="send" type="refpage">s</link> <m>mod</m>, and <link name="send" type="refpage">s</link> <m>vol</m>. These are five different sources of MIDI control , and we will use them to control up to eight different video effects linked in a series. The effects link is something like this:</p>

<p>movie -&gt; <i>rate control</i> -&gt; <i>volume control</i> -&gt; <i>brightness control</i> -&gt; <i>saturation control</i> -&gt; <i>edge&#x2013;detection</i> -&gt; <i>zoom&#x2013;in control</i> -&gt; <i>pixelation</i> -&gt;  <i>zoom&#x2013;out control</i> -&gt; display window</p>

<p>For maximum versatility, we'd like to be able to control any of those effects with any of our MIDI sources. To accomplish that, we use a combination of objects designed for just such a purpose: <o>matrixctrl</o> and <o>router</o>. The <o>router</o> object takes messages in its various inlets and routes those messages internally to any of its outlets that you specify. The <o>matrixctrl</o> object (designed for controlling the MSP <o>matrix~</o> object and the Max <o>router</o> object, not for controlling Jitter matrices <i>per se</i>) provides a user-interface for specifying those routings. Take a look at the <o>matrixctrl</o> object in the blue region of the patch.</p>

<illustration><img src="images/jitterchapter26h.png"/>Route fifth input (VOL) to second output (Volume)</illustration>
<p><o>matrixctrl</o> shows input sources on vertical grid lines and output destinations on horizontal grid lines. So, if we want to route the messages from the fifth source inlet of a <o>router</o> object to the second destination outlet, we need to click on the grid point where those meet. In this example, we're asking to route the <i>vol</i> data to control the <i>volume</i> effect. Clicking at that point on the <o>matrixctrl</o> grid sends a message to a <o>router</o> object that tells it to make this source&#x2013;destination connection internally. (Clicking again erases the red dot and breaks the connection in <o>router</o>.)  In our program the <o>router</o> object is inside the <o>patcher</o> <m>effects</m> subpatch, but if they were in the same patch, their connection would look like the following example.</p>

<illustration><img src="images/jitterchapter26i.png"/><o>router</o> is the"patchbay" for Max messages, and <o>matrixctrl</o> is its user interface</illustration>

<h3>Routing Around (Bypassing) Parts of the Patch</h3>
<p>If we aren't using some of the video effects at a certain time (for example, maybe we don't want any zooming or pixelation), we need to bypass those particular effects. In the <i>effects</i> subpatch we'll use <link name="gswitch2" type="refpage">Ggate</link> and <o>gate</o> objects to bypass some of the effects. To give the user easy control over which effects to use and which to bypass, we've set up checkboxes in the main patch, using the  <o>radiogroup</o> object.  When the user clicks on one of the checkboxes, <o>radiogroup</o> sends the on/off status of all of the checkboxes out its outlet, and we can use that information to switch the routing of the <link name="gswitch2" type="refpage">Ggate</link>s in the subpatch.</p>

<illustration><img src="images/jitterchapter26j.png"/>Zoom In, Pixelate, and Zoom Out effects are completely bypassed.</illustration>
<bullet>Double-click on the <o>patcher</o> <m>effects</m> object to see the contents of the <i>effects</i> subpatch.</bullet>
<illustration><img src="images/jitterchapter26k.png"/>The output of <o>radiogroup</o> is used to switch <o>gate</o> and <link name="gswitch2" type="refpage">Ggate</link> objects in the subpatch.</illustration>
<p>In the subpatch, the <o>receive</o> <m>Aleftoutlet</m> object receives <m>jit_matrix</m> messages from the <o>jit.movie</o> in the main patch. In the example above, the <link name="gswitch2" type="refpage">Ggate</link> object routes the <m>jit_matrix</m> message around the <link name="patcher" type="refpage">p</link> <m>brightness</m> subpatch&#x2014;bypassing that effect&#x2014;and the next <link name="gswitch2" type="refpage">Ggate</link> object routes the message through the <link name="patcher" type="refpage">p</link> <m>saturation</m> subpatch. Thus, the <link name="gswitch2" type="refpage">Ggate</link> objects serve as <i>Insert/Bypass</i> switches for each effect, and the checkboxes in the <o>radiogroup</o> provide the user interface for those switches. At the end of this chain of effects, the matrix is finally passed to a <o>send</o> <m>display</m> object, which sends the matrix to the <i>Display</i> window.</p>

<p>So, in the main patch we have two separate controls for the user to set up the routing of control data and effects. With the <o>matrixctrl</o> object, MIDI data from a source (or more than one source) can be routed to any (or many) of the effects. With the <o>radiogroup</o> checkboxes, the user can elect to insert effects or bypass one or more effect entirely.</p>

<bullet>Close the <i>[effects]</i> subpatch window. Use the checkboxes to select which video effects you want to insert, and use the <o>matrixctrl</o> to assign MIDI sources to the control of those effects. Play around with different combinations to see what types of control are most intuitive (and work in the context of a keyboard performance) for each effect.</bullet>
<h2>User Control of Video Effects</h2>
<p>Each video effect in this tutorial patch is pretty simple, so we won't describe each one in detail. We'll just point out a few traits that might be instructive as you decide how you want to apply realtime user control of video effects.</p>

<bullet>Double-click on the <o>patcher</o> <m>effects</m> object once again to open the effects subpatch
window. Double-click on the <link name="patcher" type="refpage">p</link> <m>brightness</m> object to see a typical one of these video effect subpatches.</bullet>

<illustration><img src="images/jitterchapter26l.png"/>The 0 to 1 data is scaled to the range 0 to 2 for controlling the brightness.</illustration>

<p>The <m>jit_matrix</m> message comes in the left inlet and the control data (in the range 0 to 1) comes in the right inlet. The control data is scaled to an appropriate range, and is used to alter an attribute in a Jitter object, and the processed matrix is passed on out to the next effect in the chain. The <link name="patcher" type="refpage">p</link> <m>saturation</m> and <link name="patcher" type="refpage">p</link> <m>zoomin</m> subpatches work pretty similarly.  The <link name="patcher" type="refpage">p</link> <m>zoomout</m> subpatch is also similar, but uses a slightly more involved mathematical expression, shown in the following example.</p>

<illustration><img src="images/jitterchapter26m.png"/>The 0 to 1 data is remapped as an exponential curve from 1 to 0.125.</illustration>
<p>In the above example the incoming control data (0 to 1) is used to calculate the exponent of a power of 2. When the control data is 0, the expression will be 2<sup>0</sup>=1. When the control data is 1, the expression will be 2<sup>-3</sup>=0.125. Thus, the actual control value is flipped to have reverse meaning and to describe an exponential curve instead of a linear change.</p>

<p>In the <link name="patcher" type="refpage">p</link> <m>edges</m> subpatch, the object that's really creating the effect is a Sobel edge detection object called <o>jit.sobel</o>. What we're controlling is the <i>mix</i> between the original input image and the edge-detector's output. So we're really just controlling the <m>xfade</m> parameter of a <o>jit.xfade</o> object (described in detail in <i>Tutorial 8</i>).</p>

<p>The <link name="patcher" type="refpage">p</link> <m>pixelate</m> subpatch reduces the dimensions of the image matrix (a process known as <i>downsampling</i>), so that some of the data must be discarded and the image will be pixelated when it's displayed in the 320x240 <i>Display</i> window. (This method of pixelation is detailed in <i>Tutorial 14</i>.)  We got the dimensions of the original image by retrieving the <m>dim</m> attribute of <o>jit.movie</o> (back when we first read in the movie), so we use our control data to scale those dimensions by some factor from 1 to 0.0625, and we use those new dimensions to set the <m>dim</m> attribute of a <o>jit.matrix</o> object, as shown in the following example.</p>

<illustration><img src="images/jitterchapter26n.png"/>Downsampling an image causes it to be pixelated when it's upsampled to its original dimensions.</illustration>
<p>The <link name="patcher" type="refpage">p</link> <m>rate</m> and <link name="patcher" type="refpage">p</link> <m>volume</m> subpatches are a bit different because we're not actually processing a matrix in those subpatches, we're just changing an attribute of <o>jit.movie</o> in the main patch. The following example shows the contents of the <link name="patcher" type="refpage">p</link> <m>rate</m> subpatch.</p>

<illustration><img src="images/jitterchapter26o.png"/>Send the result to any <link name="receive" type="refpage">r</link> <m>rate</m> object, and also use it so set the <m>rate</m> attribute of <o>jit.movie</o></illustration>

<h2>Summary</h2>
<p>The physical interface afforded by MIDI controllers gives you a good way to control video in real time in Jitter, and particularly to make correlations between music and video. Each type of controller&#x2014;keyboard, pitchbend wheel, modulation wheel, volume pedal, etc.&#x2014;implies a different type of control mapping. All the data of MIDI channel messages falls in the range 0 to 127, but the way you map that data to control Jitter attributes varies depending on the effect you're trying to produce. In this patch, as a starting point we mapped all the pertinent MIDI data into the range 0 to 1, then we scaled that range as necessary for each video effect.</p>

<p>Because Jitter objects receive so many different messages, it's often necessary to use a <o>message</o> box to construct the desired message. If you find yourself directing many different messages to the same place(s) from different parts of the patch, you might consider using the <o>message</o> box's remote message-sending capability&#x2014;a semicolon plus the name of a <o>receive</o> object&#x2014;to reduce the patchcord spaghetti in your patches.</p>

<p>If you need to send Max messages from many different sources to many different destinations, and you need the ability to reconfigure the routing of source messages to the desired destinations, the <o>router</o> object functions well as a configurable <i>patch bay</i> for Max messages. The <o>matrixctrl</o> object provides a readymade user interface for configuring the internal source&#x2013;destination patching within a <o>router</o>. in this patch, we used a <o>matrixctrl</o> and <o>router</o> to allow the user to direct any of five types of MIDI control data to any of eight different video effects. We used a <o>radiogroup</o> object to create a bank of checkboxes that act as <i>Insert/Bypass</i> switches for the video effects.</p>

	<seealsolist>
		<seealso name="bendin">Output received MIDI pitch bend messages</seealso>
		<seealso name="ctlin">Output received MIDI control values</seealso>
		<seealso name="jit.matrix">The Jitter Matrix!</seealso>
		<seealso name="jit.pwindow">In-Patcher Window</seealso>
		<seealso name="jit.movie">Play or edit a movie</seealso>
		<seealso name="jit.rota">Scale/rotate in 2D</seealso>
		<seealso name="jit.scalebias">Multiply and add </seealso>
		<seealso name="jit.sobel">Sobel and Prewitt gradient edge detector</seealso>
		<seealso name="jit.xfade">Crossfade between 2 matrices</seealso>
		<seealso name="matrixctrl">Matrix-style switch control</seealso>
		<seealso name="notein">Output received MIDI note messages</seealso>
		<seealso name="radiogroup">Radio button/check box user interface object</seealso>
		<seealso name="router">Matrix-compatible Max message router</seealso>
		<seealso name="stripnote">Filter out note-off messages, pass only note-on messages</seealso>
		<seealso name="zl">Multi-purpose list processor</seealso>
	</seealsolist>
	</chapter>
