MMLからWAV生成、そして自由な波形プログラミングへ
2025/04/25

きっかけ
最近、Phel-langでMML文字列を埋め込んだコードからWAVファイルを生成するツール phel-mml2wav を作成しました。
初めは素のsin波だけを生成していましたが、波形を切り替えられるようにしたらたのしくなって、短時間で「瞬間シンセ」として現在の形を持つに致りました。
機能追加の歴程
- **osc-fnを外部指定可能に** – sin波に限らず、短波、短切波、三角波なども生成できるように
- **FM/モジュレーションによる挿入的な作音**
- **:effects で音を加工できるように** – ゲイン・ボリュームの変更 – ディストーション (tanh) – tremolo (AM)
設計方針
波形を作る部分(オシレーター)と、それを加工する部分(エフェクター)を分離した構成にしました。
ギターで言うなら、「ピックアップの生の音」に「エフェクターの加工」を追加するといった感覚です。
osc-fn
:(freq t amp idx total sr) -> float
:effects
:[(fn [x sr] -> sequence)]
Sweet Child O’ Mineのイントロフレーズ
音符をMMLで書き起こし、下記のようなコードでWAVを生成しました:
(let [fp (php/fopen "example_sweet_child_intro.wav" "w")
mml "T120 O4 L8 D->D-<AG>G<A>F+<A D->D-<AG>G<A>F+<A E->D-<AG>G<A>F+<A E->D-<AG>G<A>F+<A G->D-<AG>G<A>F+<A G->D-<AG>G<A>F+<A D->D-<AG>G<A>F+<A D->D-<AG>G<A>F+<A"
osc-fn (fn [freq t amp idx total sr]
(+ (* amp 0.8 (php/sin (* 2 php/M_PI freq t)))
(* amp 0.5 (php/sin (* 2 php/M_PI (* 2 freq) t)))
(* amp 0.3 (php/sin (* 2 php/M_PI (* 3 freq) t)))
(* amp 0.1 (php/sin (* 2 php/M_PI (* 4 freq) t)))))
# ディストーション:サンプルごとに sr を受け取るように修正
distortion (fn [wave sr]
(map |(* 0.4 (php/tanh (* 4 $))) wave))
opts {:osc-fn osc-fn
:effects [distortion]}]
(converter/process-mml-to-wav-stream mml 44100 fp opts)
(php/fclose fp))
mml
は、MMLでSweet Child O’ Mine のイントロのギターフレーズを書いてあります。
osc-fn
は、波長を作る関数です。倍音を含む波長を表現する配列を生成する関数です。
distortion
は、ディストーション(歪みエフェクター)の加工を行なう関数です。
音量注意!
おわりに
今回の設計は、音を生成する部分と、それを加工する部分を分離することで、楽器のシンセ化を意識したものとなりました。
- 波形は
osc-fn
で指定 - エフェクトは
:effects
の配列で指定
自作シンセの入り口としても楽しめると思います。ディレイなどのエフェクターも作ってみたいです。