このページでは Thomas Grill 氏の作成した py オブジェクトを使用して、 スクリプト言語 Python で Pd の external を作成する方法について取り上げます。
C 言語で external を記述する通常の方法に比べて py オブジェクトを使うと何がいいのでしょうか。 以下に思いつく理由をあげます。
C で Pd のオブジェクトを書こうとすると、 実質的な計算を行う部分の他にも構造体の定義やメソッドの追加などのコードが必要になり結構煩雑です。 しかし py オブジェクトはこうした部分をうまく吸収してくれているため、 実質的な計算をする部分のコードを記述するだけで済みます。
C で external を開発するときはコードを改変するたびに Pd を終了、 DLL の再コンパイル、Pd の再起動(と DLL のリロード)をしなければいけませんが、 py オブジェクトは左側の入力に reload メッセージを送ることでスクリプトをリロードしてくれるのでこうした手間が省けます (Windows98 で試すと Pd 実行中はスクリプトファイルがロックされており書き換えが出来ないのでこのメリットは享受できません。 Windows XP では可能でした)。
ただし py オブジェクトには GUI オブジェクトや DSP オブジェクトを作成することが不可能などの制限もあります。 こうしたことも考慮に入れて使い道を考えましょう。
py/pyext のページ (http://www.parasitaere-kapazitaeten.net/Pd/ext/py/) で Windows 向けと Linux 向け両方の py オブジェクトが入手できます。
Python の処理系は Python Language Website で手に入るものと ActiveState が配布している ActivePython のがあります。 py オブジェクトの作者は Windows では前者を使用しているようです。 このページの筆者は Windows98 に ActivePython 2.2 をインストールしていますが、特に問題は無いようです。
例としてカウンタのオブジェクトを Python で書いてみることにしましょう。 このオブジェクトは bang メッセージを入力にとり、その都度数値をカウントアップして出力します。
# counter.py
import sys # あとで sys.argv を使うときに必要
# スクリプトへの最初の引数で count 変数を初期化
# 引数が与えられてないときは 0 で初期化される
try:
count = int(sys.argv[1])
except:
count = 0
# bang でトリガーされる場合、関数は引数をとらない
def counter():
global count # 関数内からグローバル変数にアクセスできるように
ret = count # 現在の count 変数の値を一時的に退避
count += 1 # count 変数をインクリメント
return ret # 退避しておいた値を戻り値として返す
同じ機能が C で実装された Johannes M. Zmoenig 氏のカウンタオブジェクトの例 と比較してみてください。
これを counter.py というファイル名で保存し、Pd のパスが通った場所 (起動時に -path で指定したディレクトリのどこか)に置いてください。 Pd のパッチからは以下のようにして利用します。
![[py counter counter 0] というオブジェクトの二つある入力の右側に [bang] メッセージボックスを繋ぎ、出力は数値ボックスに繋ぐ](pd_py_pycounter.gif)
py オブジェクトに入力が二つありますが、左側は py オブジェクト自体を制御するメッセージを送るためのもので、
counter.py にメッセージを送るには右側の入力を使います。
py オブジェクトが三つの引数をとっていますが、
最初の counter は Python スクリプトのファイル名で、
二つ目の counter は counter.py の中の counter 関数を使うという指定です
(つまり一つのファイル内に複数の関数を入れてこの引数の値で切りかえるることも出来ます)。
三つ目の 0 は counter.py に与えられる引数で、
sys.argv を使って取り出すことが出来ます。
ここではカウンタの初期値を指定するのに使います。
ところで py オブジェクトにはひとつ困ったことがあります。
今作ったカウンタを一つのパッチに複数置いてみると分かるのですが、
たとえば一方のカウンタを 30 までカウントアップしたら、
何もしていないもう一方のカウンタも 30 まで引き上げられた状態になってしまいます。
つまり複数の py オブジェクトのインスタンスを作ってもグローバル変数は共有されてしまうようです。
これを回避するには別名のカウンタスクリプトをもう一つ作るなどの必要があります。
Python を取り入れた Pd プログラミングに興味を感じたら「py オブジェクトでアルペジエータを作る 」も読んでみてください。
2002-09-10 追記:
py-0.0.1 では sys.argv[0] でスクリプトへの最初の引数を取り出していましたが、
py-0.1.0 では sys.argv[0] には py または pyext という文字列が入り、
sys.argv[1] に最初の引数が入るようになったため、
それにあわせて記述を変更しました。