nul.jp > PureDataLab

Pure Data で簡易シーケンサを作る

このページでは Pd の基本的な仕組みを理解しながら簡易 MIDI シーケンサを作ることを目的とします。 目標とするのはいわゆるアナログシーケンサ的な 8 ステップのものです。

1. 配列を理解する

まずシーケンサを作るのに何が必要かを考えてみましょう。 八つの音を繰り返し発音するためにはどこかに八つの音程の情報を格納しておき、 それを繰り返し順番に読んでいくということになります。 このようなタイプのデータを格納するための手段として最適なのは配列を使うことです。

1.1 配列の作成

まずは実際に配列を作ってみましょう。 [File]->[New] で Pd の新しいパッチをつくり、[Put]->[Array] とすると次のようなダイアログが出ます。

配列作成時のダイアログ: name で配列の名前を設定できる

name で配列の名前を付けることが出来ますが、音程データを格納するための配列なので note と名付けます。 OK を押すとパッチ画面に配列のグラフが現れます。 このグラフの X 座標が配列の個々のデータ、 Y 座標がその値を示します。

新しく出来た配列: 配列の初期値は中央の 0 になっている

今回配列に収めるデータの数は 8 で音程は MIDI で 0 から 127 までの数値で表現されるので、 配列オブジェクトを右クリックし、 Properties を選び、 X 座標を 0 から 7 まで(これで計八つ)、 Y 座標を 0 から 127 までに設定します。

配列の上限と下限を設定するダイアログ: from と to でそれぞれ下限と上限を設定

エディットモードから抜けてグラフの線をマウスでドラッグしてやると配列の値を変えることが出来ます。

配列内の値を変化させた結果

1.2 配列の値の書き換え

グラフをマウスでドラッグしても配列の値を変えることは出来るのですが、 tabwrite というオブジェクトを使用して書きかえることも出来ます。 tabwrite は二つの入力をもち、右側の入力で X 座標を指定したあと左側の入力に数値を送ると 指定された X 座標の値を書きかえることが出来ます。 また "y x" の形式のメッセージを左側の入力に送ることによっても書きかえることが出来ます。 例えば "60 3" というメッセージは X 座標が 3 のデータを 60 に設定します。

[tabwrite note] というオブジェクトの左の入力に数値ボックスと [60 3] というメッセージボックスを接続、右側の入力に数値ボックスを接続

なお、数値ボックスの値を動かすときに大きすぎたり小さすぎたりすることがないように上限と下限を設定しておくと便利です。 左側の数値ボックスを右クリック、 Properties を選んで lower limit を 0 、upper limit を 127 にします。 右側も同様に 0 から 7 までにしておきます。

1.3 配列の値の読み出し

これまででシーケンスデータの配列を用意することはできました。 次はこれを読み出すことを考えましょう。 Pd の配列の読み出しには tabread というオブジェクトを使います。 tabread は一つの入力を持ち、この入力に X 座標の値を指定して送るとそれに対応する Y 座標の値を出力します。 入力は数値ボックスからでもメッセージでも構いません。

オブジェクト [tabread] の入力にに数値ボックスとメッセージボックス [3] を接続、出力を数値ボックスで受け取る

この tabread に 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 ... という様に数値を送ることによって、 配列内に設定しておいた音程データが順番に出力されるはずです。

2. カウンタを作る

2.1 カウンタの仕組み

では次は 0 から 7 までカウントアップするカウンタを作ることにしましょう。 Pd では次のようにパッチを組むことでカウンタを作ることが出来ます。 bang を何回も押すと出力される数値が一つずつ上がっていくのが分かるはずです。

[int] オブジェクトの左入力に [bang] メッセージボックスを接続、出力を数値ボックスの入力とオブジェクト [+ 1] の左入力に接続。[+ 1] の出力は [int] の右入力に接続

この仕組みを順を追って説明することにしましょう。 int は整数値を格納するオブジェクトで、左側に数値を送るとその数値を(整数でなければ整数にして)出力します。 また右側に入力があるとその値を格納しますが出力はしません。 左側に bang メッセージが送られると格納した値を出力します。 + オブジェクトは左側に数値を送るとその入力に指定した数(ここでは 1 )を加算して出力します。

最初に bang が int に送られると int は初期値である 0 を下の数値ボックスと + オブジェクトに出力します。 + オブジェクトは送られてきた 0 に 1 を足した結果である 1 を int の右側入力に返し、int には 1 が格納されます。 もう一度 bang を送ると、int は今度は格納された 1 を下の数値ボックスと + オブジェクトに出力します。 + オブジェクトは送られてきた 1 に 1 を足した結果である 2 を int の右側入力に返し、int には 2 が格納されます。 あとはこの繰り返しで int オブジェクトの出力は 1 ずつカウントアップしていくというわけです。

2.2 カウンタをループさせる

このカウンタはまだ目的に適ったものではありません。 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 ... という風に 7 までいったら 0 に戻って繰り返したいのですが、 このカウンタは 7 より大きくなってもカウントアップを続けるからです。 カウンタのループは次のように % オブジェクトを使うことによって実現できます。

先ほどのパッチの [int] の出力を [% 8] オブジェクトにつなぎ、その出力を数値ボックスで受け取る

% オブジェクトは入力の数値を指定した数(ここでは 8 )で割った余りを出力するオブジェクトです。 こうすると入力が 8 になると 8 割る 8 の余りで 0 に戻り、 9 になると 9 割る 8 の余りで 1 、 という風にうまくループしてくれるわけです。 カウンタはこれで完成です。 tabread の入力につないで bang を押すたびに配列の値が順番に出力されるのを確認しましょう。

カウンタの出力を [tabread note] の入力に繋いだもの

3. MIDI ノートの生成

この出力から MIDI ノートを生成する作業を先にしておきましょう。 noteout オブジェクトは三つの入力を持ち、左からノート番号、ベロシティ、MIDI チャンネルを意味します。 これに例えばそれぞれ 60 100 1 を送るとチャンネル 1 の中央の C の音が強さ 100 で鳴ることになります。 しかし、そのままだとノートオフが送られないので音が(音色が持続音であれば)鳴りっぱなしになってしまいます。

これでは不便なので、ノートオンを送って一定の時間が経過したらノートオフを送るようにしたいのですが、 こういうときには makenote オブジェクトを使用することができます。 makenote オブジェクトは三つの入力を持ち、左からノート番号、ベロシティ、デュレーション(音の長さ、ミリ秒で指定)を意味します。 makenote オブジェクトの二つの出力はそのまま noteout の左二つの入力に繋げるだけで構いません。

さらに tabread の出力を makenote の左の入力に接続し、以下のようにしましょう。

[tabread note] の出力を オブジェクト [makenote] の左入力に接続、残り二つの入力に数値オブジェクトを繋ぐ。[makenote] の二つの出力をそれぞれオブジェクト [noteout] の左二つの入力につなぎ、[noteout] の右入力には数値ボックスを繋ぐ

これで bang を押すたびに Pd に繋がれた MIDI 音源が音を出すようになりました。

4. シーケンスさせる

シーケンサというからには手動で bang を押しつづけるわけにはいかないので、 一定の時間毎に bang を送るようにしたいものです。 この目的には metro オブジェクトを使用します。 metro オブジェクトは指定されたミリ秒毎に bang を出力するオブジェクトで、 左側の入力に bang を送ることによって開始し、 stop メッセージを送ることによって停止します。 下の例では 240 ミリ秒ごとに bang を生成します。

カウンタの [int] の入力に [bang] の変わりにオブジェクト [metro 240] を接続、[metro 240] の左入力にはメッセージボックス [bang] と [stop] を接続

5. インターフェイスの改善

ここまででシーケンサとしての大まかな骨組みは出来たことになりますが、 配列(=シーケンス)の値を設定するときに、 このままではかなり面倒なこと(いちいち X 座標を決めてから値を変化させる)をしなければなりません。 もう少しステップシーケンサらしい使い勝手にするために、 八つのステップのそれぞれの値を個別に設定するための数値オブジェクトを付けてしまいましょう。

[tabwrite note] の入力に [$1 0] から [$1 7] まで八つのメッセージボックスを繋ぎ、それぞれの入力に数値ボックスを繋げる

tabwrite の左側の入力に "y x" という書式のメッセージを送ることができることはすでに説明しました。 ここで説明を要するのは $1 というシンボルについてです。 $1$2$3 ... といったシンボルは入力のリストの値を順番に格納する変数です。 と書いても分かりにくいので次のようなパッチを作ってみましょう。

[print $1 $2 $3 $4] というオブジェクトの入力に数値ボックスとメッセージボックス [3 6 9 11] を接続

print $1 $2 $3 $4 というオブジェクトが "3 6 9 11" というメッセージのリストを受け取ると Pd は $1 から $4 までをそれぞれ "3 6 9 11" に置き換えます。 その結果コンソール(Windows なら DOS プロンプト)への出力は print: 3 6 9 11 のようになります。 数値ボックスからの入力のように単一の数値の場合は $1 に代入されており、 数値ボックスの値を動かすとコンソールにその数値が出力されるのがわかるはずです。

さらに音程だけでなくベロシティーの方もいじれるようにして見ましょう。 音程のときと同様にベロシティー用の配列を用意し、 makenote の二番目の入力に繋ぎます。

完成品

これで簡易シーケンサは一応の完成です。 あとは応用をきかせてもっと面白いことが出来るようなパッチを作ってみてください。

http://nul.jp/2002/pd_seq
文書作成: 2002-08