ChipTuneプロジェクト:音楽になった!

MMLと言うよりは、シーケンサのイベントリストに近い形のデータを解釈するルーチンを実装しました。

テストは以下をdo itです。

SSGGenerator testEnv.

……こういう場合は>>の記述を使わない方がいいよな、うん。コードの一部だし。
鳴らすにはこんな事をやります。

  • 音色オブジェクトの作成

音量変化と、音程変化を組み合わせて名前を付けて、「音色」という形で保持します。
「音色」はCTVoiceというクラスのインスタンス

hoge := CTEnvelope attackR: 0.01 decayR: -0.002 sustinL: 0.6 sustinR: -0.001 releaseL: 0.5 releaseR: -0.001.
voice := CTVoice name: 'Piano' ampObject: hoge.

  • 音色セットの作成

CTMMLParserで音色変化を行わせるための「プログラムチェンジセット」のようなものを作ります。これは順序を持つCollectionであれば何でもかまいません。

voices := { voice }.

  • SSGGeneratorを作り、CTMMLParserに関連づける

CTMMLParserは、「どのSSGGeneratorに対して音を出力するか」を指定しておきます。

og := SSGGenerator new.
player := CTMMLParser generator: og voices: voices.

  • 楽譜の指定

二次元の配列変数で持ちます。
二次元目の要素はこんな感じ

1
音程。[a-gA-G][#+-][1-8]の文字列
2
音量
3
拍数。ちなみにディフォルトのテンポは108bpm
4
ノートオン時間の割合。1で拍全てをノートオン

player playList: #( #('c4' 2000 2 0.8)
#('d4' 2000 1 0.8)
#('e4' 2000 1 0.8)
#('f4' 2000 4 0.8) ).

  • 鳴らす

sb2 := CTSoundBuffer newStereoSampleCount: (22050*2*5).
sb2 mix: og .
CTLLSoundPlayer playBuffer: sb2.

……なんか、微妙に音痴なのは時間管理をmsでやっているから精度が足りないんせいなんだろうなぁ……。