チュートリアル37:
データ構造

データ構造とは?

データ構造とは、個々の要素を容易に見つけることができるように、ある取り決めに基づいて格納されるデータのコレクションのことを言います。チュートリアル 32 では、table オブジェクトを使いました。これは、配列(array)と呼ばれるデータ構造を持ち、格納されている値にアクセスするためにインデックスアドレスを用いました。この章では、データのコレクションを作成したり、アドレスによってそれを取り出したりすることが可能ないくつかのオブジェクトを使います。

coll

Max の中で最も多目的に利用できるデータ構造オブジェクトが coll (collection の略)です。coll オブジェクトは任意の型、長さ(最大 256要素まで)を持つ、数多くの様々なメッセージのコレクションを格納し、それぞれのメッセージにナンバーアドレス、またはシンボル(語)アドレスを与えることができます。

coll はインレットでリストを受信すると、そのリストの最初の数値をアドレスとして使用し、リストの残りの要素をそのアドレスに格納します(リストとは、数値で始まり、スペースで区切られた任意の要素の集合であることを思い出して下さい)。例えば、coll36 sequencer start 2048 というメッセージを受信した場合、メッセージ sequencer start 2048をアドレス36 に格納します。その後、collは数値 36だけを受信した場合、アドレス(36)を2番目のアウトレットから送信し、メッセージ sequencer start 2048 を左アウトレットから送信します。

また数値の代わりにシンボルをアドレスとしてメッセージを格納することもできます。collに対して、単にシンボルから始まるメッセージを送信した場合、coll はシンボルをコマンドの一種として解釈しようして、残りのメッセージを格納しません。そのため、シンボルをアドレスとしてメッセージを格納するためには、シンボルの前に store という語を置くことが必要になります。

collstore という語から始まるメッセージを受信すると、store という語の後の最初の要素をアドレスとして使用し、メッセージの残りの部分をそのアドレスに格納します。coll がインレットでこのアドレスのみを受信すると、右アウトレットからそのアドレスを(symbol という語を前につけて)送信し、左アウトレットから格納されているメッセージを送信します。

次のものは、同じパッチですが、数値の代わりにシンボルをアドレスとして coll にメッセージを格納しています。

coll は シンボルアドレスの前に symbol という語をつけて2番目のアウトレットから送信するため、アドレスが他のオブジェクトによってコマンドとして解釈されることはありません。例えば、メッセージボックスは単語(シンボルアドレス)をコマンドの一種として解釈しようとするため、この単語によってトリガされません。しかし単語の前に symbol がある場合、メッセージボックスオブジェクトはトリガされ、単語はボックス内の可変アーギュメント$1に置き換えられます。

coll の内容の編集

coll の内容を見たり、編集したりするためには、このオブジェクトをダブルクリックしてテキストウィンドウを開きます。このテキストウィンドウに変更を加えた場合、テキストウィンドウを閉じる際に coll の内容の変更を保存するかどうかを尋ねられます。

coll の内容は特別なフォーマットで書かれています。詳細は Max リファレンスマニュアルの collを参照して下さい。

coll の内容の保存

coll にメッセージを格納した場合、これをパッチの一部として保存するように設定できます。パッチャーウィンドウ をアンロックして coll オブジェクトを選択し、Object メニューから Get Info... を選んで、インスペクタウィンドウの中の Save coll with Patcherをチェックして下さい。

また、coll の内容を別のファイルとして保存することができます(これにより、内容は複数のパッチで使用することができます)。別のファイルへの保存を行なうためには、coll の テキストウィンドウを開き、File メニューから Save as... を選びます。内容を別のファイルとして保存するためのもう1つの方法として、coll オブジェクトへの write メッセージの送信があります。これによって、Save as ダイアログ・ボックスが開きます。

collにファイルをロードするためには、アーギュメントとしてファイル名を書き込むか、collread メッセージを送信します。これによって、オープンドキュメントダイアログボックスが表示されます。

coll へのコードの格納

patcher coll_examples オブジェクトをダブルクリックして、サブパッチウィンドウを開いて下さい。

・MIDI キーボードで長い音をいくつか弾いて下さい。キーボードのそれぞれの鍵には固有なの3声のコードが割り当てられています。

coll オブジェクトにはコードが格納されていて、キーナンバー(演奏されるノートのピッチ)がアドレスとして使用されています。

・パッチ 1 の collオブジェクトをダブルクリックして、どのようにコードが格納されているかを見て下さい。コードを変更したい場合には、テキストウィンドウの中の数値を編集して下さい。その後、ウィンドウを閉じて coll の内容を更新して下さい。

インレットでピッチ値を受信すると、coll はそのアドレスに格納された3つの要素を持つリストを出力します。このリスト は iter オブジェクトによって連続した数値に分割され、数値は(実際にはほとんど同時に) noteout に送信されて、MIDI キーボードで演奏されるノートオン、あるいはノートオフ・べロシティと結合されます。

パッチ 1 の残りは coll に作成したコードを格納するためのものです。ピッチ・データが Ggate の右アウトレットにルーティングされると、ノートオン・ピッチが thresh オブジェクトに送信されます。

thresh オブジェクトは iter の反対の動作を行なうようなオブジェクトです。特定の時間のスレッショルド(閾値)の中で受信されたピッチは、その順序で一緒にパックされます。スレッショルドとは、受信した数値と前の数値との間の時間の最大値をミリ秒単位で表したものです。一定の時間内に新しい数値が何も受信されない場合、それまでの数値がリストとして送信されます。

このため、コードの音を同時に(それぞれの間隔が 50ミリ秒以内で)弾いた場合、それらはリストとしてパックされ、50ミリ秒後に送信されます。unpack オブジェクトは最初の3つの数値を選択して、それらを pack に格納します。その後、ナンバーボックス に数値を入力してアドレスを選択すると、アドレスと伴奏のコードがすべてリストとして coll に送信され、格納されます。ナンバーボックスは、アドレス入力のためのスライダとして使用することができるように、マウスアップのみを送信するように設定されています。この設定が行なわれていない場合、ドラッグした際には、それぞれの数値のアドレスにこのコードが格納されてしまいます。

Ggate をクリックし、矢印が右アウトレットに向くようにして下さい。

coll に格納したい3声のコードを弾いて下さい。最初に4声のコードを弾いて、最終的に coll をトリガするために用いるアドレスの音と一緒に聴いてみて下さい。その後、3声のコードを弾いて pack に格納して下さい。

・ナンバーボックス を用いてコードを格納するアドレスを選択して下さい。

・必要なコードをすべて格納するまで上記のステップを繰り返した後、再度 Ggate をクリックして、演奏されたピッチが coll に直接届くようにルーティングを戻して下さい。アドレス・ノートを演奏して、その結果を聴いて下さい。

新しいコードを保存したい場合には、再度 coll オブジェクトのテキストウィンドウを開き、File メニューから Save As... を選ばなければなりません。

coll のデータ構造の分析

パッチ 2 は、collを使ってシンボルアドレスを持ったメッセージを格納する方法、そして、複雑なメッセージをcollに格納し、送信後にそれを分析する方法を示しています。

・パッチ 2 で様々なメッセージをクリックして下さい。

・パッチ 2 の collをダブルクリックし、その内容を見て下さい。

この collのデータ構造のフォーマットとして、metro に対するコマンド、テンポ(デュレーション)、ノートべロシティという形式を選択しました。その理由は、それぞれのメッセージが同じ順序でデータに格納されるため、データ構造の中の個々の要素にアクセスでき、一定の方法で要素を使うことができるからです。

データ構造は coll から出力された後で分析されます。メッセージは最初に route に送信されます。メッセージの第1の要素が 1 ( metro のオンを意味します)の場合、メッセージ内の残りの要素を使って makenote にデュレーションを、metro にテンポを、makenote にべロシティを渡します。メッセージの第1の要素が 1 でない場合(このケースでは、 0は単に別の可能性というだけです)、送信する必要があるものは何もないため、route はメッセージを無視します。必要なデータが metromakenote に渡された後、第1の要素は metro のオン、オフを切り替えるために使用されます。

coll のその他の機能

これらの例は coll の使い方のセンスを身につけさせてくれるでしょう。coll が理解するコマンド・メッセージはこれ以外にも数多くあるため、このチュートリアルではその詳細までカバーすることはできません。例えば、gotonextprev コマンドによって coll 内の様々なメッセージを読み通すことができます。また、nth (メッセージ内の n 番目の要素を取得する)、sub (メッセージ内の要素を置換する)、merge (メッセージの最後に要素を追加する)のようなコマンドによって、格納されたメッセージの個別の要素を選択、あるいは変更することができます。これらのコマンドの詳細は、Max リファレンスマニュアルの collを参照して下さい。

・他のサブパッチを見る前に、[coll_example] ウィンドウの中のコード演奏パッチを使用不可にしておく必要があるでしょう。Ggate の矢印を右アウトレットに向けるか、タイトルバーの MIDI enable/disable アイコンをクリックしてウィンドウ内の MIDI を使用不可にして下さい。[coll_example] サブパッチ・ウィンドウを閉じて下さい。

訳注:現行バージョンでは、「タイトルバーの MIDI enable/disable アイコン」は存在しません。

menu

menu オブジェクトは パッチャーウィンドウの中にポップアップメニューを作成します。これは、他のメニューと同じように、マウスでコマンドを選ぶために使うことができます。またインレットで menu の項目の数値を受信したときにメッセージを表示することもできます。

menu 内の項目がマウスで(あるいはインレットで数値が受信されることによって)選択されると、menu の項目の数値が左アウトレットから送信されます。menu の項目には、0 から始まる番号がつけられます。

menu オブジェクトを作成した後、Object メニューから Get Infoを選ぶと、menu インスペクタが開きます。インスペクタウィンドウの中の大きなテキストフィールドに、カンマで区切って menu 項目を書き込んで下さい。menu 項目には、数値、リスト 、単語、文章など、任意のタイプのメッセージが使用できます。menuコマンドの中にカンマを含めたい場合には、その前にバックスラッシュ( / )を置く必要があります。

インスペクタウィンドウでEvaluate Item Text がチェックされている場合、menu は右アウトレットから項目のテキストを送信します。Auto Size オプションがチェックされている場合、menu の幅は menu コマンドのテキストの長さに従って自動的に調節されます。

patcher menu_examples オブジェクトをダブルクリックし、サブパッチ・ウィンドウを開いて下さい。

パッチャープログラムのユーザインターフェイスの向上のために menu を使う方法について、視覚的な示唆を与えるために、このサブパッチの中のオブジェクトの多くは非表示にされています。

・ウィンドウの左側部分にあるシーケンサmenu を使用して、MIDI シーケンスをレコーディング、プレイバックして下さい。

一連のメッセージボックスをクリックするより、1つの menuを使用する方が簡単です。それは見た目にも美しく、最後に選択したコマンドを表示するという利点も持っています。

・[menu_examples] window をアンロックして、menu がどのように接続されているかを見て下さい。

右アウトレットは、実際のテキストメッセージを seq に送信します。

もう1つのパッチでは、menu は値の送信と、受信した値の表示という2つの目的を持っています。シンセサイザで数多くの様々なサウンドが利用できる場合、すべてのプログラムチェンジ・ナンバーを覚えることは不可能かもしれません。menu はプログラムチェンジの値(項目のナンバー)とサウンド名( menu 項目のテキスト)を結びつける手助けをすることができます。

マウスで menu 項目を選択すると、項目のナンバーはプログラムチェンジ値として pgmout に送信されます。サウンド名がそのシンセサイザに固有なものであるように、シンセサイザのメーカによって使用されるナンバリングシステムもそれぞれ異なるかもしれません。MIDI プログラムチェンジ値がシンセサイザののサウンドナンバにどのように対応するかは、正確に理解している必要があります。この例では、メニュー項目 0 は空のままにしておき、メニュー項目 1 〜 32 を使ってサウンド名を格納しています。このため、サウンドを選択すると 1 〜 32 のプログラムチェンジ値が送信されます。

・シンセサイザ・サウンド menu の インスペクタを見て下さい。menu の最初の項目が(テキストをカンマで始めることによって)空にしてある点に注意して下さい。これによって、項目を 1 〜 32として使うことができます。

ダイアログボックスで入力するのが適当でないと思われるほど多くの項目を menu の中に書き込みたい場合、どのようにしたら良いでしょうか? 私たちはテキストウィンドウに項目を書き込み、コピーしてmenu インスペクタの中にペーストしました。

・用意されているサウンドリストを、自分の機材と対応したものに置き換えたいと考えるのではないでしょうか。

また、入力されたプログラムチェンジ値を表示するようにする必要もあるため、それらを menu のインレットへ送っています。しかしプログラムチェンジ値を再び送信する必要はないため、set メッセージを使用し、出力を行なわずに、指定された項目をmenu にセットしています。同様に menu からの数値を反映するナンバーボックスが必要ですが、その数値が再び menu に送り返されないようにする必要があります。そうでないと、これがスタックオーバーフローを引き起こすからです。繰り返して言いますが、set メッセージこそが、その解決方法です。

・[menu_examples] ウィンドウを閉じ、patcher preset_examples オブジェクトをダブルクリックして 、サブパッチウィンドウを開いて下さい。

preset

preset オブジェクトは、同じウィンドウの中にある、slider, uslider, ナンバーボックス, toggle オブジェクトのような、他のユーザインターフェイスオブジェクトの設定を保存し、復元することができます。保存された設定を呼び戻す(リコールする)と、preset は、これらすべてのオブジェクトを設定が保存されたときの状態に復元します。preset のアウトレットと table を接続することによって、 table オブジェクトの内容の様々なバージョンを保存、復元することも可能です。

preset は3通りの方法で操作することができます。presetの左アウトレットと他のユーザインターフェイスオブジェクトのインレットが接続されている場合、preset はそのオブジェクトの設定だけを保存、復元します。また、preset の右アウトレットと他のオブジェクトのインレットが接続されている場合、preset はそのオブジェクトを除く、ウィンドウの中のすべてのユーザインターフェイスオブジェクトの設定を保存、復元します。preset の左右のアウトレットに何も接続されていない場合には、preset はウィンドウの中のすべてのユーザインターフェイスオブジェクトの設定を保存します(table オブジェクトは preset の左アウトレットに接続することによってのみ保存することができるため、これは除きます)。

[preset_examples] ウィンドウでは、実際には preset オブジェクトは table とパッチコードで接続されていますが、美観を考えてそのパッチコードは非表示にされています。。

・パッチを使用する前に、Option メニューで All Windows Active を動作可能にして下さい。table をダブルクリックしてグラフィックエディタウィンドウを開いて下さい。 0 から 60 までのピッチ値(下の hslider の Offset によって、キーボードの範囲にトランスポーズすることができます)を描くことができ、上の hslider をドラッグして、それらのピッチを演奏することができます。

・テーブル・ウィンドウの中に任意のピッチによるカーブを描いたら、Store と表示されたナンバーボックスに数値を入力して下さい。table の値はpreset のその場所に格納されます。

table のプリセットをいくつか保存するまで同じ処理を繰り返して下さい。Recall と表示された ナンバーボックスに数値を入力すると、様々なプリセットを呼び出すことができます。

・それでは、[preset_examples] ウィンドウをアンロックして、その裏では何が行われているかを見て下さい。

Store, Recall, Clear と表示されたナンバーボックスは、実際には preset にメッセージを送信しています。

プリセット場所に設定を保存するためには、プリセット場所の数値を後に続けた store メッセージを送信します。プリセットを復元するためには、そのプリセットナンバーだけを送信します。プリセットを消去するためには、プリセットナンバーを後に続けた clear メッセージを送信します。clearall は保存されているすべてのプリセットを消去します。

write メッセージによって preset の内容を別のファイルに保存することができ、read メッセージによってファイルをロードすることができます。

patcher another_examples オブジェクトをダブルクリックしてサブパッチのサブパッチを見て下さい。

[another_examples] ウィンドウの中の preset オブジェクトには、パッチの一部として、すでに16のプリセットが保存されています。presetの内容を、別のファイルではなく、パッチと共に保存するためには、presetオブジェクトを選択して、Object メニューから Get Info... を選び、 Save Presets with Patcherをチェックします。

このパッチはプリセットの保存、復元を行なう、もう1つの方法を示しています。プリセットを[Shift] + クリックすると、現在の設定を保存し、その後、このプリセットをクリックするだけで設定を復元することができます。preset オブジェクト内のプリセットを保存できる場所の数は、オブジェクトの物理的なサイズによるものではありません。たとえオブジェクトボックスの中に表示されていなくても、各々の preset オブジェクトは 256 のプリセットを保存できる場所を持っています。

・様々なプリセットボタンをクリックして、様々な toggle やナンバーボックスの設定を呼び出して下さい。独自の反復するパターンを作り、その設定を preset オブジェクトに保存してみて下さい。

このウィンドウには、非表示にされているパッチ・コードはありません。preset に何も接続されてない場合、ウィンドウの中のすべてのユーザ・インターフェイス・オブジェクトの設定を保存します。

まとめ

データ構造は、個別の要素に容易にアクセスできるような、データの格納を行なうために使用されます。

coll オブジェクトは数値、またはシンボルをアドレスとして使用して、任意の種類のメッセージを格納します。データの格納は、インレットからメッセージとして受信することによって、あるいは coll のテキストエディタウィンドウに書き込むことによって、行なうことができます。coll がインレットでアドレスを受信すると、2番目のアウトレットからアドレスを送信し、左アウトレットからそのアドレスに格納されたメッセージを送信します。

collの内容はパッチの一部として、あるいは別のファイルとして保存することができます。read メッセージを用いて、あるいはアーギュメントとしてファイル名を書き込むことによって、 collの中にファイルをロードすることができます。

coll によって送信されたメッセージは、他のオブジェクトによって分析し、データ構造から特定の要素を選択することができます。また個々のデータの要素は coll のインレットに特定のコマンドを用いて送信、変更することも可能です。

menu オブジェクトはパッチャーウィンドウ内のポップアップメニューで、 menu 項目(コマンド)には任意の種類のメッセージを使用できます。menuはマウスによるコマンドの選択やメッセージの表示に使用することができます。menuコマンドが、マウスによって、あるいはインレットで menu 項目ナンバーを受信することによって選択されると、menu はコマンドを表示し、(オプションとして)格納されたメッセージを右アウトレットから、また(常に)項目ナンバーを左アウトレットから送信します。

preset オブジェクトは、ウィンドウ内にあるすべてのユーザインターフェイスオブジェクトの、ある時点での設定を保存することができ、後でこれらの設定を呼び出すことができます。preset の左アウトレットがパッチコードによって特定のオブジェクトと接続されている場合、preset はそれらのオブジェクトの設定のみを保存、復元します。また preset を用いて table の内容を記憶させることができますが、tablepreset に接続されていなければなりません。preset オブジェクトは、すべてのユーザインターフェイスオブジェクトの様々な設定の集合を256個 まで保存、復元できます。

参照

coll 様々なメッセージのコレクションの格納と編集。
menu コマンドを送信、表示するポップアップ・メニュー。
preset 他のオブジェクトの設定を保存、復元します。
データ構造 (Max トピックス)Maxでデータを格納する方法。