/**/

チュートリアル 16:
名前を持ったJitterマトリックスを使う

このチュートリアルでは、複数のソースからのデータを同じマトリックスに書き込む場合、 jit.matrix オブジェクトの name アトリビュートをどのように使ったらよいかということについて学びます。さらに、新しいマトリックスへコピーをする際にマトリックスのサイズをどのようにスケール(拡大・縮小)するかについて、また、 より時間のかかるタスクに合わせてMaxイベントの優先順位を下げるために、Maxの低い優先順位のキューを使う方法についても見ていきます。

・Jitter Tutorialフォルダの16jNamedMatrices というチュートリアルパッチを開いて下さい。

チュートリアルパッチは5つの色分けされた領域にわかれています。中央(ライトブルー)の領域には2つの jit.qt.movie オブジェクトがあります。パッチが開かれる際、loadbang オブジェクトによって、2つのムービー(rain.movとtraffic.mov)が jit.qt.movie オブジェクトに読み込まれます。


ムービーの読み込み

これまでに見て来たチュートリアルパッチと異なり、このパッチの jit.qt.movie オブジェクトは send および receive オブジェクトを使って、パッチの他の部分との通信を行います。m1とm2という名前を持つ receive オブジェクトは2つの jit.qt.movie オブジェクトにメッセージを送ります。2つのオブジェクトが出力するマトリックスは(sendオブジェクトを使って)パッチ内にある movie1movie2 という名前の receive オブジェクトに送られます。

パッチ上部の黄色の領域には、パッチのJitter処理を駆動するための metro オブジェクトがあります。


metro オブジェクトは2つのメッセージボックスの片方を動作させます。

・トグルボックスをクリックして metro をスタートさせて下さい。パッチ内の3つの jit.pwindow オブジェクトでイメージの表示が始まります。

重要な順序

metro オブジェクトは Ggate オブジェクトおよび jit.qball(これについては後ほど説明します)と呼ばれるオブジェクトを経由してgate オブジェクトに接続されています。metro によって出力される bang メッセージは gate によって2つのメッセージボックスオブジェクトのうちの1つにルーティングされます。最終的な出力マトリックス(パッチの一番下にある jit.pwindow オブジェクトに表示されます)はどちらのメッセージボックスが bang メッセージを受け取るかによって変更されます。

gate の左インレット(1と2)に接続されている2つのメッセージボックスをクリックして下さい。一番下の jit.pwindow がどのように変化するかに注意して下さい。


最終的な出力マトリックスはパッチ内のメッセージの順序によって変化します

2つのメッセージボックスオブジェクトは、同じように3つの名前(m1、m2、output)を持った receive オブジェクトに bang メッセージを送信します。2つのメッセージボックスでは、メッセージを送る順番が違います。左のメッセージボックス( gateが 1 にセットされた場合に metro によって動作)は、最初にm2という名前の receive オブジェクトに、その後m1という名前の receive オブジェクトに、そして output という名前のreceiveオブジェクトに bang メッセージを送信します。これによって、まず右の jit.qt.movie オブジェクト(道路の情景を読み込んでいる)がマトリックスを出力し、左の jit.qt.movie オブジェクト(雨の映像を読み込んでいる)がそれに続きます。最後にパッチの一番下にある jit.matrix オブジェクトが bang メッセージを受け取り最終的なマトリックスが出力されます。右のメッセージボックス( gate が 2 にセットされた場合に metro によって動作)では、jit.qt.movie オブジェクトを動作させる2つの bang メッセージの順序が逆になっています。(左の jit.qt.movie が最初にマトリックスを出力し、右の jit.qt.movie オブジェクトがそれに続きます。)

これらのメッセージが発生する順序は、2つの jit.qt.movie オブジェクトと最後の jit.pwindow オブジェクトの間で起こることを見る場合にのみ重要になります。

名前とは?

2つの jit.qt.movie オブジェクトは、bang メッセージを受信するとそれぞれ下にある send オブジェクトにマトリックスを出力しますが、これらは順番に movie1movie2 という名前の receive オブジェクトへマトリックスを送信します。2つの receive オブジェクト(パッチの右側にある同じような2つの領域にあります)は2つの名前付きの jit.matrix と同様、 jit.pwindow にも接続されています。


名前を持ったjit.matrixオブジェクト

パッチの右側にある2つの jit.matrix オブジェクトは(パッチの下部の最終的な jit.pwindowの上にある jit.matrix オブジェクトと同じ)名前(name)を持っています。この3つのオブジェクトにつけられた名前は composite です。その結果、3つの jit.matrix オブジェクトは compositeという名前の Jitter マトリックスを内容とする同じマトリックスデータを共有します。

2つの jit.qt.movie オブジェクトが(同じ名前を共有する別々の jit.matrix オブジェクトを経由して)同じ Jitterマトリックスにデータを書き込んでいるということがわかれば、bang メッセージの順序が重要である理由は理解できると思います。左の jit.qt.movie が最初にマトリックスを出力する場合、この jit.qt.moviecomposite マトリックスにデータを書き込み、その後、右の jit.qt.movie が同じマトリックスに書き込みます。もし、この2つのマトリックスが共通するセルに書き込みを行ったとすると(下記参照)、最後に到着したマトリックスがすでにセルが持っているデータを上書きします。

重要な注:Maxパッチの中で起こっていることの順序について確信が持てない場合、パッチの処理がどのように実行されているかを見るために「トレース」を行うことができます。TraceメニューのEnableコマンドを選択し、metro オブジェクトをオンにすると、ステップコマンド(command + [t])によるステップスルー(訳注:段階ごとに処理を見ていくこと)によってパッチがどのように処理をしていくかを見ることができます。(トレース機能を使ったMaxメッセージのトレースに関する詳細は、Max Tutorials and Topicsマニュアルの「Debugging」の章を参照して下さい。(訳注:現在のバージョンでは Max トピックスマニュアルの「デバッグ」です。)

デスティネーション(送り先)のディメンション(大きさ)

チュートリアルパッチの右側にある2つの jit.matrix オブジェクトは、usedstdim アトリビュートが1に設定されています。これによって、jit.qt.movie オブジェクトから送られて来るマトリックスをスケールし composite Jitterマトリックスの特定の領域だけに書き込むことができます。

p coords と表示された2つのサブパッチに接続されている x origin、y origin、scaleと表示されたナンバーボックスオブジェクトをいろいろ試してみて下さい。composite マトリックスの中に表示されている jit.qt.movie からの2つのイメージのサイズ変更や移動がどのように行なわれているかという点に注意して下さい。


画像の中の画像

サブパッチ p coords には、jit.matrixオブジェクトに送る dstdimstartdstdimend アトリビュートをフォーマット(形式化)するための同じヘルパーパッチが含まれています。これらのアトリビュートはそれぞれ、composite Jitterマトリックスにデータをコピーする際に使う範囲の左上隅と右下隅の座標値を指定します。usedstdim アトリビュートは単に、jit.matrix がデータをコピーする際にこれらのアトリビュートを使うよう指示しているだけです。usedstdim が 0に設定されていると、入力されたマトリックスは jit.matrix オブジェクトが参照するマトリックス全体を満たすようにスケールされます。


入力されるマトリックスは共有マトリックスに書き込まれる前にスケーリングされます

サブパッチに送信した3つの数値はMaxオブジェクト内部でフォーマットされ、入力マトリックスを置こうとする出力マトリックス中の領域の左上と右下が書かれたリストが生成されます。アウトレットの前のメッセージボックスは $ による代入を使って、リスト中の数値でアトリビュートに関連するアーギュメントを置き換えています。

2つのマトリックスが composite マトリックスに書き込まれた後、最後に bang メッセージが output という名前の receiveオブジェクトに送られます。


最終的な結果

チュートリアルパッチの一番下の領域には3番目の名前付き jit.matrix オブジェクトがあります。metro から送信された bangtrigger オブジェクトを通りますが、trigger オブジェクトは jit.matrix bang メッセージを送った後、直ちに clear メッセージを送信します。clear メッセージは composite という名前のJitterマトリックスの全てのセルを消去(値0に)します。マトリックスのクリアを行わない場合、いずれかの jit.matrix オブジェクトが dstdimstart および dstdimend アトリビュートの変更を行うと、ムービーがその前に出力された場所がそのまま残される結果になってしまう可能性があります。

キューをジャンプする

パッチの一番上にある jit.qball オブジェクトは、Maxが私たちの要求について行けないようなイベントにおいて、かけがえのないサービスを提供します。metro オブジェクト(50ミリ秒毎に bang メッセージを送信します)は3つの別々な処理を駆動しています(jit.qt.movie オブジェクトからの2つのマトリックスを名前を指定されたJitterマトリックスに書き込み、同時にデータを表示し、次の処理のためにマトリックスをクリアします)。jit.matrix オブジェクトは内部のJitterマトリックス(このケースでは composite という名前のマトリックス)にデータを書き込みますが、書き込みは次のメッセージによって処理が奪い取られる可能性をはらんだ方法で行われます。さらに、タスクが実行されている時に、高い優先順位によってスケジューリングされた他のMaxイベントが生じる可能性もあります。このことから、前の命令(動作)が完了する前にマトリックスの表示(あるいはマトリックスへのデータの書き込み)が行われ、画面のフリッカー(ちらつき)や他の予想外の結果を引き起こす可能性が生じます。jit.qball オブジェクトは、オブジェクトに入力されたメッセージをMax の低い優先順位をもつキューの最後に置きます。ここではこのメッセージ自身もまた他のメッセージによって処理を「奪い取られる」可能性があります。この方法では、jit.qball metro から bang メッセージを受け取った時点で全てのJitterのタスクが完了していない場合、jit.qball は低い優先順位を持つキューの全ての命令が完了するまで待ち、その後 bang を送信することになります。同様に、最初の bang が送信される前に他の bang が到着した(すなわちパッチの他の部分の全ての処理完了するまでに50ミリ秒以上かかってしまった)場合、最初の bang は処理を奪いとられ(捨てられ)」て2番目の bang に処理を譲ります。こうすることによって、イベントの累積が速すぎてオブジェクトの動作が維持できないのではないかという心配をせずに、イベントの最大のレート(速さ)を仮定してMaxパッチの中で設定することができます。

・"jit.qball bypass switch"と表示された Ggate をクリックして、metro オブジェクトの出力が jit.qball オブジェクトをバイパスするようにして下さい。パッチの下部にある jit.pwindow の中の合成されたイメージがちらつき始めると思いますが、これはメッセージの到着が限度を超えていることを示しています。

通常、Jitterオブジェクトに bang メッセージを送ると、そのオブジェクト内の未了のイベント(例えば、すでの到着しているが、まだオブジェクトによって取り扱われていない bang メッセージ)の処理を「奪い取り」ます。それに対して、jit.qball オブジェクトは、このような制御をJitterオブジェクトの複数のチェーンに関して行い、自動的にイベントを「奪い」(「フレーム落ち」を生じます)メッセージが正しい順序で到着することを保証します。

まとめ

複数の jit.matrixに1つの名前を付けることによって、パッチの異なった部分で共通のJitterマトリックスへの書き込み、読み出しを行うことができます。jit.matrix オブジェクトが内部的に持つマトリックスにコピーを行う際、usedstdim アトリビュートを1に設定し、dstdimstartdstdimend というアトリビュートを使うことによって、コピーしたいJitterマトリックスのスケーリングを行うことができます。jit.qball オブジェクトは、Maxイベントを低い優先順位のキューに置くことによって、その優先度を低くすることを可能にします。このキューでは、実行できるだけの時間がとれない場合、次のイベントによって処理を「奪われる」(イベントが捨てられる)可能性があります。