<?xml version='1.0' encoding='UTF-8'?>

<?xml-stylesheet href="./_c74_tut.xsl" type="text/xsl"?>
<chapter name="Tutorial 45: Introduction to using Jitter within JavaScript">
<setdocpatch name="45jJavaScriptIntro" patch="45jJavaScriptIntro.maxpat"/>

<previous name="jitterchapter44">Flash Interactivity</previous>
<next name="jitterchapter46">Manipulating Matrix Data using Javascript</next>
<parent name="jitindex">Jitter Tutorials</parent>



<h1>Tutorial 45: Introduction to using Jitter within JavaScript</h1>
<p>The Max <o>js</o> object, introduced in Max 4.5, allows us to use procedural code written in the JavaScript language within Max. In addition to implementing the core JavaScript 1.5 language, the Max <o>js</o> object, contains a number of additional objects and methods specific to Max, e.g. the Patcher object (designed for interfacing with the Max patcher) or the post() method (for printing messages into the Max Console). There are a number of extensions to the <o>js</o> object that allow us to perform Jitter functions directly from the JavaScript language when working with Jitter. For example, the Jitter extensions to <o>js</o> allow us to:</p>

<bullet>Instantiate Jitter objects directly within JavaScript and create function chains of Jitter processes within procedural code.</bullet>
<bullet>Create Jitter matrices with JavaScript and access and set the values and parameters of Jitter matrices from within JavaScript functions.</bullet>
<bullet>Use Jitter library operations (e.g. jit.op operators and jit.bfg basis functions) to do fast matrix operations on Jitter matrices within JavaScript to create low-level Jitter processing systems.</bullet>
<bullet>Receive callbacks from Jitter objects by listening to them and calling functions based on the results (e.g. triggering a new function whenever a movie loops).</bullet>
<p>Before beginning this tutorial, you should review the basics of using JavaScript in Max by looking at the JavaScript tutorials starting with <i><link type="tutorial" module="max" name="javascriptchapter01">Basic JavaScripting</link></i> and <i><link type="tutorial" module="max" name="javascriptchapter02">JavaScript Scripting</link></i>. These tutorials cover the basics of instantiating and controlling a function chain of Jitter objects within <o>js</o> JavaScript code.</p>

<bullet>Open the tutorial patch.</bullet>
<p>The tutorial patch shows us two columns of Max objects side-by-side. The right column contains a patch that processes a movie through an effect and displays it. All of this is done using Jitter objects connected within the Max patch between the <o>qmetro</o> object and the <o>jit.pwindow</o> object. The left column shows the <o>qmetro</o> and <o>jit.pwindow</o> objects, but contains only a <o>js</o> object loading the JavaScript file <i>45jWakefilter.js</i> in between. As we will learn, the two sides of the patch do pretty much the exact same thing. First, we'll look at the patch on the right side to see what's happening.</p>

<h2>Waking Up</h2>
<bullet>On the right side of the patch, click the <o>toggle</o> box labeled <i>Display Processing using Patcher</i>. Click the <o>message</o> box that reads <m>read countdown.mov</m>, also on the right side.</bullet>
<div>
<techdetail>We use <o>qmetro</o> objects instead of <o>metro</o> objects in our patch because of the potential for scheduler backlog when working with JavaScript. The normal behavior of the Max <o>js</o> object is for it to create a queue of pending events while it executes the current one; as a result, a fast <o>metro</o> object will quickly accumulate a large backlog of <m>bang</m> messages for the <o>js</o> object to deal with. The <o>qmetro</o> object sends <m>bang</m> messages to the back of the low priority queue where they can be <i>usurped</i> by subsequent messages. See <i><link type="tutorial" module="jit" name="jitterchapter16">Tutorial 16:</link> Using Named Jitter Matrices</i> for a more in-depth discussion on this topic.</techdetail>
</div>
<bullet>The movie should appear in the <o>jit.pwindow</o> with a gradually changing colored effect.</bullet>
<illustration><img src="images/jitterchapter45a.png"/>A typical Jitter video effect chain.</illustration>
<p>This side of the patch plays back a movie (using a <o>jit.movie</o> object) into an edge detection object (<o>jit.robcross</o>), which is then multiplied by the output of a named matrix called <m>bob</m> (using <o>jit.op</o>). The matrix output by <o>jit.op</o> is then processed by a <o>jit.wake</o> object, which applies a temporal feedback and spatial convolution to the matrix, the parameters of which can be controlled independently for each plane. The output of the <o>jit.wake</o> object is then brightened slightly (with a <o>jit.brcosa</o> object) and then stored back into our named matrix (<m>bob</m>). The output of our effects chain as seen in the <o>jit.pwindow</o> is the output of the <o>jit.wake</o> object.</p>

<div>
<techdetail>The technique of using named Jitter matrices for feedback is covered in <i><link type="tutorial" module="jit" name="jitterchapter17">Tutorial 17:</link> Feedback Using Named Matrices</i>. The <o>jit.robcross</o> object applies the <i>Robert's Cross</i> edge detection algorithm (a similar object that allows us to use two other algorithms is called <o>jit.sobel</o>). The <o>jit.wake</o> object contains an internal feedback matrix that is used in conjunction with image convolution to create a variety of motion and spatial blur effects (similar effects could be constructed using objects such as <o>jit.slide</o> and <o>jit.convolve</o>).</techdetail>
</div>
<bullet>Open the <o>patcher</o> object named <m>random_bleed</m>.</bullet>
<p>The key to the variation of our processing algorithm is this subpatch, containing twelve <o>random</o> objects that are controlling different parameters of the <o>jit.wake</o> object in the main processing chain. The output of these <o>random</o> objects is scaled for us (with <o>scale</o> objects) to convert our integer random numbers (<m>0</m> to <m>999</m>) into floating-point values in the range <m>0</m> to <m>0.6</m>. These values are then smoothed with the two <o>*</o> objects and the <o>+</o> object, implementing a simple one-pole filter:</p>

<p>                                                            y<sub>n</sub> = 0.01x<sub>n</sub> + 0.99y<sub>n-1</sub></p>

<p>These smoothed values then set the attributes of <o>jit.wake</o> that control how much bleed occurs in different directions (up, down, left, right) in different planes (specified as the color channels red, green, and blue). You'll notice that the smoothing algorithm is such that the values in all of the <o>number</o> box objects showing the smoothed output tend to hover around <m>0.3</m> (or half of <m>0.6</m>). Our Jitter algorithm exhibits a slowly varying (random) color shift because of the minute differences between these sets of attributes.</p>

<bullet>Back in the main tutorial patcher, try changing movies by clicking the <o>message</o> box objects reading <m>read wheel.mov</m> and <m>read dozer.mov</m>. Compare the effects on these two movies with the effect on the "countdown" movie. Note that when we read in new movies, we initialize the <m>bob</m> matrix to contain all values of <m>255</m> (effectively clearing it to white).</bullet>
<h2>The Javascript Route</h2>
<bullet>Shut off the <o>qmetro</o> object on the right side of the patch by clicking the <o>toggle</o> box above it. Activate the <o>qmetro</o> object on the left side of the patch by clicking the <o>toggle</o> box attached to it.</bullet>
<p>Click the <o>message</o> box that reads <m>read countdown.mov</m> on the left side of the patch.</p>

<br/><br/><illustration><img src="images/jitterchapter45b.png"/>Look familiar?</illustration>
<p>The video on the left side of the patch looks strikingly familiar to that displayed on the right side. This is because the <o>js</o> object on the left side of the patch contains all the objects and instructions necessary to read in our movie and perform the matrix processing for our effect.</p>

<bullet>Double-click the <o>js</o> object in our Tutorial patch. A text editor will appear, containing the source code for the <o>js</o> object in the patch. The code is saved as a file called &#x2018;45jWakefilter.js' in the same folder as the Tutorial patch.</bullet>
<p>Our JavaScript code contains the familiar comment block at the top, describing the file, followed by a block of global code (executed when the <o>js</o> object is instantiated) followed by a number of functions we've defined, most of which respond to various messages sent into the <o>js</o> object from the Max patcher.</p>

<h2>Creating Matrices</h2>
<bullet>Look at the code for the global block (i.e. the code before we arrive at the bang() function).</bullet>
<p>Our code begins with the familiar statement of how many inlets and outlets we'd like in our <o>js</o> object:</p>


<p>
<pre><code language="javascript">// inlets and outlets
inlets = 1;
outlets = 1;</code></pre>
</p>


<p>Following this, we have a number of statements we may never have seen before:</p>

<p>
<pre><code language="javascript">// Jitter matrices to work with (declared globally)
var mymatrix = new JitterMatrix(4, "char", 320, 240);
var mywakematrix = new JitterMatrix(4, "char", 320, 240);
var myfbmatrix = new JitterMatrix(4, "char", 320, 240);

// initialize feedback matrix to all maximum values
myfbmatrix.setall(255, 255, 255, 255);</code></pre>
</p>


<p>This block of code defines that we will be working with a number of Jitter matrices within our <o>js</o> object.  The variables <i>mymatrix</i>, <i>mywakematrix</i>, and <i>myfbmatrix</i> are defined to be instances of the JitterMatrix object, much as we would declare an Array, Task, or instance of the <o>jsui</o> sketch object.  The arguments to our new JitterMatrix objects are exactly the same as would be used as arguments to a <o>jit.matrix</o> object, i.e. an optional <m>name</m>, a <m>planecount</m>, a <m>type</m>, and a list of values for the <m>dim</m>. </p>

<div>
<techdetail>It's important not to confuse the <i>name</i> attribute of a Jitter matrix with the <i>variable</i> name that represents it inside the JavaScript code.  For example, we've created a JitterMatrix object in our code assigned to the variable <i>mymatrix</i>.  Sending the message <m>jit_matrix mymatrix</m> to a <o>jit.pwindow</o> in our Max patch would not, however, display that matrix.  Our <i>mymatrix</i> object has a <i>name</i> property that is generated automatically if not provided using the same convention used in other Jitter objects (e.g. <i>uxxxxxxxxx</i>).  The distinction is similar to that employed by the JavaScript Global object used to share data with Max patches.</techdetail>
</div>
<p>All three of our JitterMatrix objects are created with the same typology.  On the fourth line of this part of our code, we take the JitterMatrix <i>myfbmatrix</i> and set all its values to <m>255</m>.  The setall() method of the JitterMatrix object does this for us, much as the <m>setall</m> message to a <o>jit.matrix</o> object would.  In fact, all of the messages and attributes used by the <o>jit.matrix</o> object are exposed as methods and properties of the JitterMatrix object within JavaScript.  A few examples:</p>


<p>
<pre><code language="javascript">// set all the values in our matrix to 0:
mymatrix.clear();
// set the variable foo to the value of cell (40,40):
var foo = mymatrix.getcell(40,40);
// set cell (30,20) to the values (255,255,0,0):
mymatrix.setcell2d(30,20,255,255,0,0);</code></pre>
</p>

<div>
<techdetail>The setcell2d() method allows us to set a value of a single cell in a matrix using an array of values where the first two arguments are assumed to be the position in the matrix.  The cell is then set to the values contained in subsequent arguments.  There are also utility functions for one- and three-dimensional matrices (setcell1d() and setcell3d(), respectively).  For a general purpose solution, we can use the plain setcell() function just as we would in a Max message, e.g. mymatrix.setcell(20, 30, "val", 0, 0, 255, 255).</techdetail>
</div>
<h2>Creating Objects</h2>
<bullet>Continue perusing the global block.  Now that we've created some matrices to work with, we have to create some objects to manipulate them with.</bullet>

<p>
<pre><code language="javascript">// Jitter objects to use (also declared globally)
var myqtmovie = new JitterObject("jit.movie", 320, 240);
var myrobcross = new JitterObject("jit.robcross");
var mywake = new JitterObject("jit.wake");
var mybrcosa = new JitterObject("jit.brcosa");</code></pre>
</p>


<p>These four lines create instances of the JitterObject objects.  We need four of them (<i>myqtmovie</i>, <i>myrobcross</i>, <i>mywake</i>, and <i>mybrcosa</i>) corresponding to the four equivalent objects on the right side of our Max patch (<o>jit.movie</o>, <o>jit.robcross</o>, <o>jit.wake</o>, and <o>jit.brcosa</o>).  These JitterObject objects behave just as the equivalent Jitter objects would in a Max patcher, as we'll see a bit later on.  The first argument when we instantiate a JitterObject is the class of Jitter object we'd like it to load (e.g. "jit.movie" will give us a <o>jit.movie</o> object loaded into JavaScript).  Further arguments to the object can be passed just as they would in Max patchers, so that we can tell our new <o>jit.movie</o> JitterObject to have a <m>dim</m> of 320x240 by supplying those values as arguments.<u/></p>

<p>Just as we would initialize attributes by typing them into the object box following the object's name (e.g. <o>jit.brcosa</o> <m>@saturation 1.1</m>), we can use our global JavaScript code to initialize attributes of our the JitterObject objects we've created:</p>

<p>
<pre><code language="javascript">myrobcross.thresh = 0.14; // set edge detection threshold
mywake.rfb = 0.455; // set wake feedback for red channel
mywake.gfb = 0.455; // set wake feedback for green channel
mywake.bfb = 0.455; // set wake feedback for blue channel
mybrcosa.brightness = 1.5; // set brightness for feedback stage</code></pre>
</p>


<p>Note that the properties of a JitterObject correspond directly to the attributes used by the Jitter object loaded into it, e.g. a JitterObject loading a <o>jit.brcosa</o> object will have properties for <i>brightness</i>, <i>contrast</i>, and <i>saturation</i>.  In our code above, we initialize the <m>thresh</m> property of the JitterObject <i>myrobcross</i> to <m>0.14</m>, mirroring the <o>jit.robcross</o> object on the right side of our patch.  In the same way, we initialize attributes for our <i>mywake</i> and <i>mybrcosa</i> objects as well.</p>

<h2>JavaScript Functions calling Jitter Object Methods</h2>
<bullet>Look at the code for the read() function.  This function is called when our <o>js</o> object receives the <m>read</m> message.</bullet>

<p>
<pre><code language="javascript">function read(filename) // read a movie
{
   if(arguments.length="=0)"   {
      // no movie specified, so open a dialog
      myqtmovie.read();
   }
   else { // read the movie specified
      myqtmovie.read(filename);
   }
   // initialize feedback matrix to all maximum values
   myfbmatrix.setall(255, 255, 255, 255);
}</code></pre>
</p>


<p>Our read() function parses the arguments to the <m>read</m> message sent to our <o>js</o> object.  If no arguments appear, it will call the read() method of our <i>myqtmovie</i> object with no arguments.  If an argument is specified, our <i>myqtmovie</i> object will be told to read that argument as a filename.</p>

<bullet>Click the <o>message</o> box that labeled <m>read</m> on the left side of the patch.  Notice that a dialog box pops up, just as if you had sent a <m>read</m> message into a <o>jit.movie</o> object in a Max patcher.  Cancel the dialog or load in a new movie to see what our algorithm does to it.</bullet>

<p>If we wanted to, we could have looked at the Array returned by the read() method to ensure that it didn't fail.  For right now, however, we'll trust that the arguments to the <m>read</m> message sent to our <o>js</o> object are legitimate filenames of movies in the search path.</p>

<p>After we read in our movie (or instruct our <i>myqtmovie</i> object to open a <o>jit.movie</o> "Open Document" dialog), we once again intialize our JitterMatrix <i>myfbmatrix</i> to values of all <m>255</m>.</p>

<h2>The Perform Routine</h2>
<p>Just as a typical Jitter processing chain might run from <o>jit.movie</o> to output through a series of Jitter objects in response to a <o>qmetro</o>, our JavaScript Jitter algorithm performs one loop of its processing algorithm (outputting a single matrix) in response to a <m>bang</m> from an outside source.</p>

<bullet>Look at the bang() function in our JavaScript code.  Notice that, just as in our Max patcher, each JitterObject gets called in sequence, processing matrices in turn.</bullet>

<p>
<pre><code language="javascript">function bang()
// perform one iteration of the playback / processing loop
   {
      // setup

      // calculate bleed coefficients for new matrix:
      calccoeffs();

      // process

      // get new matrix from movie ([jit.movie]):
      myqtmovie.matrixcalc(mymatrix, mymatrix);

      // perform edge detection ([jit.robcross]):
      myrobcross.matrixcalc(mymatrix, mymatrix);

      // multiply with previous (brightened) output
      mymatrix.op("*", myfbmatrix);

      // process wake effect (can't process in place) ([jit.wake]):
      mywake.matrixcalc(mymatrix, mywakematrix);

      // brighten and copy into feedback matrix ([jit.brcosa]):
      mybrcosa.matrixcalc(mywakematrix,myfbmatrix);

      // output processed matrix into Max
      outlet(0, "jit_matrix", mywakematrix.name);
   }</code></pre>
</p>


<p>The calccoeffs() function called first in the bang() function sets up the properties of our <i>mywake</i> object (more on this below).  Following this is the processing chain of Jitter objects that take a new matrix from our <i>myqtmovie</i> object and transform it.  The matrixcalc() method of a JitterObject is the equivalent to sending a Jitter object in Max a <m>bang</m> (in the case of Jitter objects which <i>generate</i> matrices) or a <m>jit_matrix</m> message (in Jitter objects which <i>process</i> or <i>display</i> matrices).  The arguments to the matrixcalc() method are the input matrix followed by the output matrix.  Our <i>myqtmovie</i> object has a redundant argument for its input matrix that is ignored; we simply provide the name of a valid JitterMatrix.  If we were working with a Jitter object that needs more than one input or output (e.g. <o>jit.xfade</o>), we would supply our matrixcalc() method with Arrays of matrices set inside brackets ([, ]).</p>

<p>The op() method of a JitterMatrix object is the equivalent of running the matrix through a <o>jit.op</o> object, with arguments corresponding to the <m>op</m> attribute and the scalar (<m>val</m>) or matrix to act as the second operand.  In a narrative form, therefore, the following things are happening in the "process" section of our bang() function:</p>

<bullet>Our <i>myqtmovie</i> object generates a new matrix from the current frame of the loaded video file, storing it into the JitterMatrix <i>mymatrix</i>.</bullet>
<bullet>Our <i>myrobcross</i> object takes the <i>mymatrix</i> object and performs an edge detection on it, storing the results back into the <i>same</i> matrix (more about this below).</bullet>
<bullet>We then multiply our <i>mymatrix</i> JitterMatrix with the contents of <i>myfbmatrix</i> using the op() method to <i>mymatrix</i>.  This multiplication is done "in place" as in the previous step.</bullet>
<bullet>We then process the <i>mymatrix</i> JitterMatrix through our <i>mywake</i> object, storing the output in a third JitterMatrix, called <i>mywakematrix</i>.</bullet>
<bullet>Finally, we brighten the JitterMatrix <i>mywakematrix</i>, storing the output in <i>myfbmatrix</i> to be used on the next iteration of the bang() function.  In our JavaScript code, therefore, the matrix <i>myfbmatrix</i> is being used exactly as the named matrix <m>bob</m> was used in our Max patch.</bullet>
<div><br/>
<techdetail>Technical Note: Depending on the class of Jitter object loaded, a JitterObject may be able to use the same matrix for both its input and output in its matrixcalc() method.  This use of "in place" processing allows you to conserve processing time and memory copying data into new intermediary matrices.  Whether this works depends entirely on the inner workings of the Jitter object in question; for example, a <o>jit.brcosa</o> object will behave correctly, whereas a <o>jit.wake</o> object (because it depends on its previous output matrices for performing feedback) will not.  By a similar token, the op() method to a JitterMatrix object will do its processing "in place" as well.</techdetail>
</div>
<p>Our processed matrix (the output of the <i>mywake</i> object stored in the <i>mywakematrix</i> matrix) is then sent out to the patcher by using an outlet() function:</p>


   <p><pre><code>outlet(0, "jit_matrix", mywakematrix.name);</code></pre></p>

<p>We use the <m>name</m> property of our JitterMatrix in this call to send the matrix's <m>name</m> (u<i>xxxxxxxxx</i>) to the receiving object in the Max patch.</p>

<h2>Other Functions</h2>
<bullet>Take a look at the calccoeffs() function in our JavaScript code.  This function is called internally by the bang() function every time it runs.</bullet>
<p>
<pre><code language="javascript">function calccoeffs() // computes the 12 bleed coefficients for the convolution state of the [jit.wake] object
{
  // red channel
  mywake.rupbleed*=0.99;
  mywake.rupbleed+=Math.random()*0.006;
  mywake.rdownbleed*=0.99;
  mywake.rdownbleed+=Math.random()*0.006;
  mywake.rleftbleed*=0.99;
  mywake.rleftbleed+=Math.random()*0.006;
  mywake.rrightbleed*=0.99;
  mywake.rrightbleed+=Math.random()*0.006;
  // green channel
  mywake.gupbleed*=0.99;
  mywake.gupbleed+=Math.random()*0.006;
  mywake.gdownbleed*=0.99;
  mywake.gdownbleed+=Math.random()*0.006;
  mywake.gleftbleed*=0.99;
  mywake.gleftbleed+=Math.random()*0.006;
  mywake.grightbleed*=0.99;
  mywake.grightbleed+=Math.random()*0.006;

  // blue channel
  mywake.bupbleed*=0.99;
  mywake.bupbleed+=Math.random()*0.006;
  mywake.bdownbleed*=0.99;
  mywake.bdownbleed+=Math.random()*0.006;
  mywake.bleftbleed*=0.99;
  mywake.bleftbleed+=Math.random()*0.006;
  mywake.brightbleed*=0.99;
  mywake.brightbleed+=Math.random()*0.006;
}
calccoeffs.local = 1; // can't call from the patcher</code></pre>
</p>

<p>We see that the calccoeffs() function literally duplicates the functionality of the <m>random_bleed</m> <o>patcher</o> on the right side of our patch.  It sets a variety of properties of the <i>mywake</i> JitterObject, corresponding to the various attributes of the <o>jit.wake</o> object it contains.  Notice that we can use these properties as ordinary variables, getting their values as well as setting them.  This allows us to change their values using in place operators, e.g.:</p>


<p><pre><code language="javascript">
        mywake.rupbleed*=0.99;
        mywake.rupbleed+=Math.random()*0.006;
</code></pre></p>


<p>This code (replicated twelve times for different properties of the <i>mywake</i> object) uses the <i>current</i> value of the <m>rupbleed</m> property of <i>mywake</i> as a starting point, multiplies it by <m>0.99</m>, and adds a small random value (between <m>0</m> and <m>0.006</m>) to it.</p>

<h2>Summary</h2>
<p>You can use JavaScript code within Max to define procedural systems using Jitter matrices and objects.  The JitterMatrix object within <o>js</o> allows you to create, set, and query attributes of Jitter matrices from within JavaScript&#x2014;the setall() method of JitterMatrix, sets all of its cells to a certain value, for example.  You can also apply mathematical operations to a JitterMatrix "in place" using the op() method, which contains the complete set of mathematical operators used in the <o>jit.op</o> object.  Jitter objects can be loaded as classes into the JitterObject object.  Upon instantiation, a JitterObject acquires properties and methods equivalent to the Jitter object's messages and attributes.  The matrixcalc() method of a JitterObject performs the equivalent of sending the Jitter object a <m>bang</m> or a <m>jit_matrix</m> message, whichever is relevant for that class of object.  This allows you to port complex function graphs of Jitter processes into JavaScript.</p>

<p>In the next two Tutorials, we'll look at other ways to use JavaScript to expand the possibilities when working with Jitter.</p>

<h1> </h1>
<h2>Code Listing</h2>

<p>
<pre><code language="javascript">// 45jWakefilter.js
//
// a video playback processing chain demonstrating the use of
// Jitter objects and matrices within [js].
//
// rld, 6.05
//
// inlets and outlets
inlets = 1;
outlets = 1;

// Jitter matrices to work with (declared globally)
var mymatrix = new JitterMatrix(4, "char", 320, 240);
var mywakematrix = new JitterMatrix(4, "char", 320, 240);
var myfbmatrix = new JitterMatrix(4, "char", 320, 240);

// initialize feedback matrix to all maximum values
myfbmatrix.setall(255, 255, 255, 255);

// Jitter objects to use (also declared globally)
var myqtmovie = new JitterObject("jit.movie", 320, 240);
var myrobcross = new JitterObject("jit.robcross");
var mywake = new JitterObject("jit.wake");
var mybrcosa = new JitterObject("jit.brcosa");

// set some initial attributes for our JitterObjects
myrobcross.thresh = 0.14; // set edge detection threshold
mywake.rfb = 0.455; // set wake feedback for red channel
mywake.gfb = 0.455; // set wake feedback for green channel
mywake.bfb = 0.455; // set wake feedback for blue channel
mybrcosa.brightness = 1.5; // set brightness for feedback stage

function read(filename) // read a movie
{
  if(arguments.length="=0)" {
  // no movie specified, so open a dialog
	myqtmovie.read();
  }
  else { // read the movie specified
	myqtmovie.read(filename);
  }
  // initialize feedback matrix to all maximum values
  myfbmatrix.setall(255, 255, 255, 255);
}

function bang()
// perform one iteration of the playback / processing loop
{
  // setup

  // calculate bleed coefficients for new matrix:
  calccoeffs();

  // process

  // get new matrix from movie ([jit.movie]):
  myqtmovie.matrixcalc(mymatrix, mymatrix);

  // perform edge detection ([jit.robcross]):
  myrobcross.matrixcalc(mymatrix, mymatrix);

  // multiply with previous (brightened) output
  mymatrix.op("*", myfbmatrix);

  // process wake effect (can't process in place) ([jit.wake]):
  mywake.matrixcalc(mymatrix, mywakematrix);

  // brighten and copy into feedback matrix ([jit.brcosa]):
  mybrcosa.matrixcalc(mywakematrix,myfbmatrix);

  // output processed matrix into Max
  outlet(0, "jit_matrix", mywakematrix.name);
}

function calccoeffs() // computes the 12 bleed coefficients for the convolution state of the [jit.wake] object
{
  // red channel
  mywake.rupbleed*=0.99;
  mywake.rupbleed+=Math.random()*0.006;
  mywake.rdownbleed*=0.99;
  mywake.rdownbleed+=Math.random()*0.006;
  mywake.rleftbleed*=0.99;
  mywake.rleftbleed+=Math.random()*0.006;
  mywake.rrightbleed*=0.99;
  mywake.rrightbleed+=Math.random()*0.006;
  // green channel
  mywake.gupbleed*=0.99;
  mywake.gupbleed+=Math.random()*0.006;
  mywake.gdownbleed*=0.99;
  mywake.gdownbleed+=Math.random()*0.006;
  mywake.gleftbleed*=0.99;
  mywake.gleftbleed+=Math.random()*0.006;
  mywake.grightbleed*=0.99;
  mywake.grightbleed+=Math.random()*0.006;
  // blue channel
  mywake.bupbleed*=0.99;
  mywake.bupbleed+=Math.random()*0.006;
  mywake.bdownbleed*=0.99;
  mywake.bdownbleed+=Math.random()*0.006;
  mywake.bleftbleed*=0.99;
  mywake.bleftbleed+=Math.random()*0.006;
  mywake.brightbleed*=0.99;
  mywake.brightbleed+=Math.random()*0.006;
}
calccoeffs.local = 1; // can't call from the patcher</code></pre>
</p>

	<seealsolist>
		<seealso name="jit.brcosa">Adjust image brightness/contrast/saturation</seealso>
		<seealso name="jit.matrix">The Jitter Matrix!</seealso>
		<seealso name="jit.op">Apply binary or unary operators</seealso>
		<seealso name="jit.pwindow">In-Patcher Window</seealso>
		<seealso name="jit.movie">Play or edit a movie</seealso>
		<seealso name="jit.robcross">Robert's Cross edge detection</seealso>
		<seealso name="jit.wake">Feedback with convolution stage</seealso>
		<seealso name="js">Javascript in Max</seealso>
		<seealso name="qmetro">Queue-based metronome</seealso>
		<seealso name="random">Generate a random number</seealso>
	</seealsolist>
	</chapter>
