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でやっているから精度が足りないんせいなんだろうなぁ……。