チュートリアル44:
detonate を用いたシーケンス

シーケンス能力の拡張

この章では、 MIDI ノートイベントのシーケンスを行なうための detonate オブジェクトの使用法を示します。そして、ノンリアルタイムなステップ入力、連続した再生テンポの変化、個別のノートのコマンドによるトリガなどのより高度なシーケンス機能の実装を、detonate によってどのように実現できるかについて説明します。また、このパッチはかなり複雑であるため、様々なタスクをそれぞれ個別のサブパッチにカプセル化することによって、オブジェクト間で迷路のようになった通信を組織化する方法の例としても参考になるでしょう。

このパッチの機能は以下のようなものです。

  1. 入力される MIDI ノートのレコーディング
  2. レコーディングされたMIDI ノートのテンポを変更しながらの再生
  3. コンピュータ・キーボード、または MIDI キーボードから個々のノートをトリガすることによって、レコーディングされたシーケンスを1つずつ進める

1つの機能から他の機能への切り替えは、スクリーン上のボタン(実際にはメッセージボックス)をクリックすることによって、あるいはコンピュータのキーボードからキーコマンドを入力することによって行なうことができます。

パッチの使用

このパッチの構造を調べる前に、このパッチをつかってみて、実際に何を行なうかを知っておくとよいでしょう。

・ Record というメッセージボックスをクリック、または r を入力し、少なくとも15秒ほど、MIDI キーボードでメロディーまたはアルペジオを演奏して下さい。

・演奏が終了したら、Play というメッセージボックスをクリック、または p を入力することによって、その演奏をプレイバックして聴くことができます。[tempo] ウィンドウの hslider をドラッグして、プレイバックのテンポをオリジナルの 1/2 から 2 倍まで変更することができます。

・テンポを 1 に戻し、Step というメッセージボックスをクリック、または s を入力して下さい。MIDI キーボードの任意のキーを押すことによって、あるいは、コンピュータキーボードから Macintosh では [Return] または [Enter] キー、Windows では [Enter]キーを押すことによって、レコーディングされたノートを1回に1つずつ演奏することができます。

・終了したら、Off をクリック、または o を入力して下さい。detonate オブジェクトをダブルクリックすることによって、レコーディングした音の編集を行なうことができます。

タスクのカプセル化

このパッチを、整然とした、わかりやすいものにしておくためには、このパッチがそれぞれ異なったタスクを実行するものであると考え、それぞれのタスクを独自のサブパッチとしてカプセル化するよう努める必要があります。そのため、コンピュータのキーボードから入力されるコマンドをキャプチャするパッチャー、実際にコマンドを実行するパッチャー、MIDI 入力を受け取ってそれを detonate に送信するパッチャー、detonate からのデータを MIDI 出力に送信するパッチャー、そして、detonate によって演奏されるノートのテンポを変更するパッチャーが用意されています。

p commands のようなサブパッチは、他のすべてのサブパッチと通信を行なう必要があるため、パッチコードは複雑に絡み合った網のようになってしまいます。そのため、ユーザがクリックしたメッセージボックスから送られるコマンドや detonate オブジェクトから送信されるコマンドは、インレットとアウトレットを結ぶパッチコードによる直接的な通信を用い、他のサブパッチへの値の送信やMIDI メッセージのフロー制御は、send および receive オブジェクトによるパッチコードを用いない間接的な通信を用いることにしました。

ユーザーからのコマンドの受信

ほとんどのパッチは、ユーザからのコマンド入力による何らかのコントロールを必要とします。このケースでは、レコーティング、 プレイバック、レコーディングされているノートのステップ進行という、排他的な関係にある3つのアクションの中から1つを選択する必要があります。そして、4番目のアクションとしてoff が追加されています。これらはメッセージボックスの中に書かれた、4つのクリック可能なコマンドによって容易に作成できます。

コマンドに素早くアクセスするために、特定の ASCII 値を検出し、キーが押されたときにメッセージボックスに bang を送信するキーボード・ショートカットを作成することができます。コンピュータのキーボードで押されたキーを検出する方法については、チュートリアル 20 で紹介しています。キーの検出は非常に簡単で、非常に重要なタスクです。そのため、このタスクはp keycommand サブパッチの中に容易にカプセル化することができ、このサブパッチのアウトレットはコマンドメッセージボックスに直接接続されています。

p keycommand オブジェクトをダブルクリックして、その内容を見て下さい。

メッセージボックスをトリガするための、 o、r、p、 s というニーモニックな(記憶しやすい)キーコマンドに加え、 [ESC] キーがoff と同じ意味で使われています。また、Macintoshでは[Return]と[Enter]キー、Windows では [Enter] キーがスコアのステップ進行のために使われています。 r keysteps オブジェクトが 1 を受け取った場合、Macintoshでは[Return]と[Enter]キーが、Windows では [Enter] キーが、s bangnext オブジェクトを経由して他のサブパッチにある next メッセージをトリガします。

中央のコマンド・ポスト

パッチ内の様々な機能の分析によって、ユーザインターフェイスが実際に非常に簡単であることがわかりました。ユーザインターフェイスは、キーボード・ショートカットを持った、4つのクリック可能なコマンドによって作られています。しかし、実際には、それぞれのコマンドはパッチ全体を通して様々な動作をトリガしなければなりません。p commands サブパッチは、コマンドを受け取った場合に、これらの動作が適切な順序で実行されることを保証するためのものです。

・[keycommands] ウィンドウを閉じ、p commands オブジェクトをダブルクリックして、その内容を見て下さい。

クリックすることが可能なそれぞれのメッセージボックスの出力は p commands のインレットの1つに送られ、 b 1 オブジェクトによって bang に変換されます。この bang がそれぞれのコマンドで実行する必要があるものすべてをトリガします。

ノートがレコーディング処理されている間に入力される新しいコマンドは、detonate のレコーディングを停止させる可能性を潜在的に持っています。そのため、個々のコマンドで最初に行なわなければならないのは、p input サブパッチの中にあるflush オブジェクトに bang を送信し、入力されている MIDI ノートをオフにすることです。

厳密に言えば必ずしも必要でない場合もあるのですが、入力される個々のコマンドは新しい命令を与える前に、 detonate を停止させ、detonate が演奏中であった場合には、p output サブパッチの中に存在する可能性があるディレイされた bang を停止させます。

そして、最後に、入力される個々のコマンドは p inputp output サブパッチの中の適切な gate オブジェクトの開閉を行ない、適切なコマンドを detonate に送信します。そのため、例えば、Off コマンドの場合、次のように動作します。

  1. p input サブパッチ内でオンのままになっているノートを除去します。
  2. p output サブパッチ内にあるディレイされた bang を停止させます。
  3. detonate を停止させます。
  4. p keycommands サブパッチに 0 を送信し、[Retrun] キー や [Enter] キーが効果を及ぼさないようにします。
  5. p input サブパッチ内の gate を閉じ、MIDI ノートが入力されないようにします。
  6. p output サブパッチ内でオンのままになっているノートを除去します。

detonate への MIDI 入力

[comands]ウィンドウを閉じ、p input オブジェクトをダブルクリックして下さい。

gate オブジェクトは、入力される MIDI ピッチナンバーを適切な場所にルーティングするために用いられています。detonate が停止、または演奏を行なっているとき、入力される MIDI 情報を無視する必要があるため gate は閉じられます。レコーディングを行なっているとき、ピッチは gate の左アウトレットから送信され、ノートのステップ進行を行なっているとき、 gate の右アウトレットから送信されます。

detonate がレコーディングを行なっているとき、ノート情報だけでなく、前のメッセージからの経過時間も送信する必要があります。そのため、 sel 1 オブジェクトを使って、レコーディングがオンになったときに timer をスタートさせています。レコーディングの間、ピッチ値は直接 detonate に行き、さらに timerbang を送信して経過時間を報告させます。その後、次に入力されるノート・メッセージのために timer を再スタートさせます。timer によって報告された時間はデルタタイムとして使用され、ピッチ、べロシティ、チャンネルナンバーと結合されて detonate の中にノートイベントとしてレコーディングされます。

Step コマンドが選択された場合、gate の右アウトレットを開くために数値 2 が送信されます。ピッチナンバーは timerdetonate ではなく strinote に行きます。stripnote オブジェクトはノートオフ・メッセージを取り除き、ノートオン・ピッチだけを使用して detonate へ送信する next メッセージをトリガします(p commands サブパッチに戻ります)。

detonate からのノートイベント

・[input] ウィンドウを閉じ、再び p commands オブジェクトをダブルクリックして下さい。

ユーザーが Play をクリックしたとき、このコマンドは s delaygate から p output 内の r delaygate オブジェクトに 1 を送信し、その後 detonatestart メッセージを送信します。

・これらのメッセージの流れを見るために、[commands] ウィンドウを閉じ、p output オブジェクトをダブルクリックして開いて下さい。

r delaygate から送信された数値 1 は左インレットで受信した数値を通過させるためにgate を開きます。その後 detonate に送信された start メッセージによって最初のデルタタイムを報告させ、その値が p output の左インレットに送られて gate を通過します。数値は delay の右インレットに送られ、datonate に対して最初のノートのイベント情報をトリガする next メッセージに bang を送る前のディレイタイムとして使用されます。datonatenext メッセージに応答してイベント情報を送信するとき、同時に次のノートイベントのデルタタイムを出力します。この過程は datonate が停止するか、ノートがなくなるまで続けられます。detonate から送られてくるイベント情報に含まれるそれ以外の要素は、ピッチ、ノートオン・べロシティ、デュレーション、チャンネルです。makenote を使用してノートオフ・メッセージを与えれば良いように思われますが、残念ながらこのケースでは、ピッチとベロシティからチャンネル情報を切り離さなければならなくなってしまうため、ノートオフが間違ったチャンネルに送信されてしまう可能性が生じます(例えば、チャンネル2 のノートメッセージが、チャンネル 1 のノートオンのためのノートオフメッセージの直前に生じるような場合がそれにあたります)。

そのため、より良い方法として、pipe オブジェクトを使ってピッチとチャンネルの情報をまとめてディレイさせ、デュレーションの値によって指定されたミリ秒の値だけ待った後、0 のベロシティ値と共にこれらの値を送信することによってノートオフ・メッセージを作成しています。従って、このパッチでは、ノートオン・メッセージは直接 noteout に送信され、その後、対応した同じキーとチャンネルによるノートオフ・メッセージが pipe によって提供されます。

プレイバックテンポの変更

おそらく、デュレーション値とデルタタイム値がそれぞれ * 1. オブジェクトを通過することにすでに気付いているでしょう。その際、それらの値は r tempofactor オブジェクトから受け取ったスケーリング係数を掛けられます。このテンポをスケーリングする係数は p tempo サブパッチで生成されます。

・スケーリング係数がどのように生成されるかを見るために、[output] ウィンドウを閉じ、[tempo] ウィンドウを前面に移動させて下さい。[tempo]ウィンドウには非表示のオブジェクトがあります。そこで、その内容を見るためには、アンロック状態にして、タイトルバーの右隅にあるズームボックスをクリックする必要があります。(あるいは、単に、ここで示している図を参照するだけでもよいでしょう)


p tempo サブパッチの内容

hslider オブジェクトを使用して、ユーザがオリジナル・テンポの半分から2倍(0.5から2.0)までのスケーリング値を設定できるようにしてあります。これは、ちょっとした問題を提起します。それは、ここで使用したい係数は乗数なのですが、hslider は加算的な(線的に増加する)スケールであるということです。しかし、2 -1 = 0.5 、2 0 = 1、 2 1 = 2.0 であることを思い出せば、hslider を使って -1 から +1 の範囲の値を提供すればよいということがわかるでしょう。hslider を選択し、Object メニューから Get Info... を選んで、スライダの Range(範囲)を 201 という値に設定し、Offset(オフセット)を -100 に設定してあります。これで、hslider は -100 から +100 の値を送信できるようになります。expr オブジェクトでこの値を 100 で割り、その結果を pow() 関数の指数を表す引数として使うことによって 2 x を得ています。

しかし、実際にはテンポを2倍にするためには、デルタタイムとデュレーションを半分にする必要があり、逆に、テンポを半分にするにはデルタタイムとデュレーションを2倍にする必要があります。このことは、ユーザには 0.5 から 2.0 までの範囲の値を示しながら、実際には p output サブパッチの r tempofactor に対して 2.0 から 0.5 へ減少する値を送信しなければならないということを意味します。送信したい値は、表示する値の逆数になるため、実際には「 1 /テンポ係数」の値を送信しています。

seq オブジェクトではそれぞれ異なる恒常的なテンポでプレイバックすることが可能ですが、ここで示した detonate の使用法は、MIDI ファイルや他の保存済みのノートイベントのシーケンスをプレイバックするテンポを連続的に変化させる方法として最も良いものです。

ノンリアルタイム・レコーディング

detonate にレコーディングされたシーケンスのリズムは、実際に detonate がイベントを受信した時間ではなく、detonate に与えられたイベントの開始時刻(つまり、個々のノートイベントについて受信したデルタタイム)によって決定されます。そのため、シーケンスは任意の時間をかけて、または一瞬でレコーディングすることも可能です。これは、p 'Another Example' サブパッチで示されています。このサブパッチは、サンプルパッチの中の他の部分とは完全に独立したプログラムになっています。

p 'Another Example' オブジェクトをダブルクリックし、開いて下さい。

expr オブジェクト内の計算は難しそうに見えるかも知れませんが、このパッチの基本的な動作はきわめてシンプルです。button をクリックすると次のような動作を行ないます。

  1. record メッセージが detonate に送信されます。
  2. uzi は 1 から1000まで増加する1000個の数値を送信します。(この数値はすぐに- 1 オブジェクトに送信されるため、事実上 0 から 999 になります)
  3. これらの数値を使って、ノートイベントの様々なパラメータを計算します。
  4. uzi の処理が完了すると、detonatestart メッセージが送信され、その後、直ちに next メッセージが続けられて最初のノートイベントが送信されます。
  5. イベントのパラメータは makenotenoteout (および、パンニングメッセージのための ctlout )によって MIDI メッセージに変換され、次のノートがいつトリガされるかを決定するためにデルタタイムが使用されます。

Max クロックの1つのティックの間に、およそ78秒の長さを持ったメロディが作曲され、レコーディングされます。それぞれのイベントパラメータはメロディの開始から終わりまでの間で特定のカーブを描く、固有の数式によって計算されます。

それぞれのパラメータの進行に対する個別のカーブが結合されると、絶え間なく変化しているものの、完全に予測可能なメロディが生成されます。パンニングは 4 ¼ サイクルのコサイン波によって移動します。これは、最初に一方のチャンネルから始まり、ゆっくりと左右に動いて、最後にステレオ音場の中央で終わります。ベロシティは 1 〜 32 に制限された範囲の乱数を指数曲線によって増加する値を加えたもので、結果として 96 〜 127 の範囲の値になります。ピッチの値は、キー66 を中心とし、振幅が 0 半音から始まり、最後には36 から 96 までの +/- 30 半音になる 480 サイクルのサイン波で与えられます。ノート間のデルタタイムは8回の指数曲線によって加速するように変化し、毎秒 5 個のノートから毎秒 50 個のノートの速さまで繰り返し加速されます。デュレーションは常に次のノートのデルタタイムの 5 倍になっているため、最も速いノートでも、少なくとも 100 ミリ秒の値になります。

button をクリックしてメロディーを作曲、レコーディング、演奏して下さい。

まとめ

detonate オブジェクトは、ノートのシーケンスをレコーディングしたり、プレイバックしたりする場合に役に立つもので、標準 MIDI ファイルの読み書きを行なうことが可能です。また、ノンリアルタイム・レコーディング、プレイバックの速さの連続的な変化、レコーディングされたノートを新しいリズムでプレイバックするといったような、あまり一般的には行なわれないようなシーケンスのタスクを実行するためにも役に立ちます。

detonate に MIDI ノートメッセージをレコーディングする場合、メッセージ間の経過時間を報告させるために timer を使う必要があります。detonate は、この値を個々のノートイベントの間のデルタタイムのパラメータとして記録します。プレイバックを行なう場合、このデルタタイムの値を使って、次のノートを演奏するまでにどのくらいの時間待たなければならないかを決定します。デルタタイムとデュレーションに 1 以外の値を掛けることによって、プレイバックの速さが変更されます。様々なチャンネルのノートオンに対してノートオフを供給する場合、makenote の代わりに pipe を使用すると便利です。

参照

detonate ノート・イベントのグラフィック・スコア。
Detonate

(Max トピックス) MIDI シーケンスのグラフィカルな編集。

Sequencing (Max トピックス) MIDI パフォーマンスのレコーディングとプレイバック。