Gauche:MML->PCM変換

Gauche:MML->PCM変換

MML->PCM変換

MML(Music Macro Language) の文字列を解釈して、PCMデータに変換するモジュールを作りました。
結果をwavファイルとして出力できます。
https://github.com/Hamayama/mmlproc

特徴としては、@コマンドで指定する各音色を 数式で生成しています。
@500のピアノ(仮)、@501のオルガン(仮)、@502のギター(仮)は試行錯誤の末、以下の数式にしました。
(できればドラム等も作りたかったのですが、うまく数式が作れませんでした。。。)

  ;; 音色生成関数(内部処理用)
  (define (make-progfunc prog)
    (case prog
      ;; 方形波
      ((0)   (lambda (t phase) (if (> (sin phase) 0) 1 -1)))
      ;; 正弦波
      ((1)   (lambda (t phase) (sin phase)))
      ;; のこぎり波
      ((2)   (lambda (t phase) (- (* (mod phase (* 2 pi)) 1/pi) 1)))
      ;; 三角波
      ((3)   (lambda (t phase) (* 2 (asin (sin phase)) 1/pi)))
      ;; ホワイトノイズ
      ((4)   (lambda (t phase) (- (* (mt-random-real0 mr-twister) 2) 1)))
      ;; ピアノ(仮)
      ((500) (lambda (t phase) (* 1.3 (if (> (sin phase) 0) 1 -1) (exp (* -5 t)))))
      ;; オルガン(仮)
      ((501) (lambda (t phase) (* (if (> (sin phase) 0) 1 -1) 13 t (exp (* -5 t)))))
      ;; ギター(仮)
      ((502) (lambda (t phase) (* 5 (cos (+ phase (cos (* phase 0.5)) (cos (* phase 2)))) (exp (* -5 t)))))
      ;; 方形波
      (else  (lambda (t phase) (if (> (sin phase) 0) 1 -1)))))

  各パラメータは以下になる
    t    : 時間(sec)
    phase = 2 * pi * freq * t
    pi   : 円周率
    freq : 音符の周波数(Hz)(オクターブ4のラが440Hzになる)
  計算結果は以下になる
    wave : 波形(-1~1 (ピアノ(仮)とギター(仮)は範囲を超えてしまうのでクリッピングが必要))

また 苦労した点として、複数チャンネルの同時演奏で、テンポがずれるケースがありました。
1つの音符Xが鳴っている間に他のチャンネルでテンポを変えられてしまうと、音がずれてしまうのです。
この場合、Xの鳴っている残り時間を、新しいテンポで再計算しないといけないようでした。

最終的に2パス方式にして、パス1でテンポ変更情報を取り出して実時間テーブルを作ることで、
どうにか計算できるようになりました。

現状、変換にはけっこう時間がかかります(MMLが長くなると数10秒くらい)。
ほとんどの時間は add-note 手続きの do ループのところで費やしているので、
この部分を例えばC言語で計算するようにしたら 速くなるかもしれないと考えています。

hamayama(2014/11/03 14:42:44 UTC)


その後、計算の部分をC言語のDLLで行うようにしてみました。
https://github.com/Hamayama/mmlproc
家のPCでは4倍くらい高速になりました。
Scheme側で確保したs16vectorの領域を、C言語側から上書きするようにしています。
また、DLLが存在しない場合は、今まで通りSchemeのみで計算します。

外部パッケージ作成手順のメモ(ただしGauche v0.9.4以上の場合)を作ったので、
参考用に以下に置いておきます。
https://gist.github.com/Hamayama/d20ab805b50756ce1d9d

hamayama(2014/11/08 03:09:24 UTC)(2014/11/27 10:46:55 UTC)

More ...