PythonモジュールPYOを使ってみる

PYOは信号処理を行うPythonモジュールです。 PYOにはさまざまなオーディオ信号処理のクラスが含まれています。 オーディオ信号の生成、基本的な信号処理(フィルター、遅延、波形の合成)が可能です。また、グラニュラーシンセシスやオーディオを編集するための複雑なアルゴリズムを作ることもできます。 PYOはOSC(Open Sound Control)またMIDIをサポートしています。PYOを使用することで高度な信号処理アルゴリズムを実現することができます。(PYOホームページより)

PYOのインストール

Windows10 64biにインストールします。PYOはPythonのバージョンにセンシティブです。インストールのドキュメントによると、Python 2.7 (up to 1.0.1), 3.5 (up to 1.0.1), 3.6, 3.7 and 3.8と書かれています。2.7と3.5はバージョン1.0.1まで対応、3.6, 3.7, 3.8 は1.0.1以降に対応しています。

ここではPython3.8を使います。Pythonのダウンロードページから3.8.10のインストーラpython-3.8.10-amd64.exeをダウンロードしました。インストーラを起動し、Pythonをインストールすると、C:\Users\<UsetName>\AppData\Local\Programs\PythonフォルダーにPythonがインストールされます。

環境変数のPATHに、Python.exeとScriptの場所を追加します。

C:\Users\<UsetName>\AppData\Local\Programs\Python\Python38
C:\Users\<UsetName>\AppData\Local\Programs\Python\Python38\Scripts

追加の際に一つこつがあります。
C:\Users\<UsetName>\AppData\Local\Microsoft\WindowsAppsを一番下位に持っていきます。これを行わないと、コマンドラインで>python を起動した時、pythonが立ち上がらずMicrosoft Storeが立ち上がってしまいます。

PYOはコンソールから次のコマンドでインストールできます。インストールはここを参照しています。

# for python 3.8 under Windows (`py` is the python launcher command)
>py -3.8 -m pip install --user pyo
サンプルの動作

サンプルを動作させてみます。サンプルはここに掲載されています。

次にプログラムをsintest.pyとしてUTF-8で保存します。UTF-8でないと実行時にSyntaxError:エラーが発生します。

from pyo import *

# PYOのサーバを立ち上げる
s = Server().boot()

# 20 dBゲインを下げる
s.amp = 0.1

# 正弦波を生成し、out()で出力する
a = Sine().out()

# GUIを表示する
s.gui(locals())

コマンドプロンプトから実行すると、次のようなGUIが表示されます。Startボタンで音が鳴り始め、Amplitudeのノブを動かすと音の大きさが変わります。

>python sintest.py

GUIの下にあるInspectorにa.freq=200と記入、リターンキーを押すことで発信波形の周波数が200Hzに変更することができます。

以下のコマンドで上で定義した正弦波発信器のパラメータを編集するスライダーを表示することができます。

# パラメータ編集スライダー
a.ctrl(title="SIN Wave")

以下のコマンドで出力の波形そのモノを表示することができます。

# 波形表示
sp = Scope(a)
sp.setGain(0.5) # 縦軸の倍率 0.5 => -6dB
sp.poll(1)      # startボタンを押すと波形が表示される


種々の波形の生成

のこぎり波
のこぎり波生成のプログラムを以下に示します。テーブルを生成する行のorderは倍音の数、すなわち波形の形 のシャープさを決めています。数字が大きいと、波形の形がシャープになります。そのかわり波形の生成に時間がかかります。

from pyo import *

# PYOのサーバを立ち上げる
s = Server().boot()

# のこぎり波のテーブルを作成する
t = SawTable(order=12).normalize() # ←←←←←

# テーブルを使って波形を生成する
a = Osc(table=t, freq=100, mul=0.5).out()

# 波形表示
sp = Scope(a)
sp.setGain(0.5)
sp.poll(1)

# GUIを表示する
s.gui(locals())

矩形波
矢印のテーブルを生成している行を書き換えます。

# 矩形波のテーブルを作成する
t = SquareTable(order=15).normalize()

三角波
矢印のテーブルを生成している行を書き換えます。波形を見ると、三角波にしては丸い感じの波形が生成されます。

# 三角波のテーブルを作成する
t = TriangleTable(order=12).normalize()


MIDIの受信

MIDIを受信するには、RawMidiを使うのがわかりやすいです。

from pyo import *

# MIDIデバイスを列記する
pm_list_devices()

# PYOのサーバを立ち上げる
s = Server()

# サーバーのsetMidiInputDevice()に、目的のデバイスのID(pm_list_devices()
# でリストされている)を指定する。 ID=99は、接続されているすべてのMIDIデバイ
# スを開く。
s.setMidiInputDevice(99)

# サーバーを起動する前に、MIDIデバイスを起動しておく必要がある。
s.boot().start()

print("Play with your Midi controllers...")

# 受信したMIDIデータをHEXで表示する。
def event(status, data1, data2):
    print("%02x %02x %02x" % (status, data1, data2))

# MIDIの生データの受信
scan = RawMidi(event)

# GUIを表示する
s.gui(locals())

パソコンにMIDIデバイスを接続した後、上のプログラムを動作させるとMIDIデバイスを列記し、MIDIデータを表示することができます。



MIDIで音を鳴らす

キーボードを弾いて、PyoでMIDIのNote Onを受けて音を出すプログラムを作成しました。MIDI Note OnをNoteinという関数で受けます。ここ関数の持っている、弾いた強さを表すプロパティ'velocity'で音量を決めています。Portはポルタメントを生成する関数のようですが、ここでは鍵盤を押した時だけ音を出すための乗算係数pを生成しています。また、Noteinのプロパティ'pitch'は周波数を表していますので、このプロパティをそのまま発信周波数freqとし発信機Oscを制御しています。

from pyo import *

# MIDIデバイスを列記する
pm_list_devices()

# PYOのサーバを立ち上げる
s = Server()
s.setMidiInputDevice(99) # スタートの前でないとダメ

# PYOサーバスタートのおまじない
s.boot().start()

# 4音ポリでノートオンを受け取る
notes = Notein(poly=4, scale=1, mul=1.0) 

# のこぎり波のテーブルを作成する
t=SawTable(order=12).normalize()

# pは、ノートオンで1になり、オフでゼロになる
p = Port(notes['velocity'], .001, 0.01) 

# 発信のfreq周波数と音量mulを決めて発信開始
a = Osc(table=t,freq=notes['pitch'], mul=p).out()

sp=Scope(a)
sp.setGain(0.5)
sp.setLength(1.0) # 横軸を1秒に設定
sp.poll(1)

s.gui(locals())