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

きっかけ
最近、Phel-langでMML文字列を埋め込んだコードからWAVファイルを生成するツール [phel-mml2wav](https://github.com/smeghead/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`の配列で指定
自作シンセの入り口としても楽しめると思います。ディレイなどのエフェクターも作ってみたいです。