今日はとりあえず表題の課題を2つ片付けたのだけど(あとバグ潰しとか)、どちらもやっつけ対策という感じになってしまった。 ループは√1,3 √2 ... のようなMMLをサポートするようにしているので(文法上は[cd :1,3 ef :2 ga]4 のような表記になる)、これを展開する部分がトリッキーでバグのもとになり、そして現在のところコンパイル結果を繰り返すような実装になってしまっている。つまり [ cde> ]3 と書いてもオクターブは変わらないし、[c)]12 と書いても音量が上がらない。これでは表現の幅が狭まるので(段階的に変化させ「ない」方法はソースレベルのループ展開でも可能だが、段階的に変化「させる」方法が出力レベルのループ展開では不可能だ)、修正しなければならないだろう。ややこしいことになりそうだが...
和音のやっつけ実装については、結局和音を計算するための特殊命令を仕込むことにした。発音と消音がインターバル無しで行われるケースは、通常はあり得ない(発音即消音にする意味が無いのでユーザが書くことも無い)。これをMMLレベルでの発音コマンドで識別して、インターバルが無いものについては、その消音コマンドを蓄積しておき、後でインターバルのある音があった時に、その消音コマンドのタイムライン上の位置を後ろに回して、インターバルを合わせるということをやっている。これで c0e0g4 という命令は、正しく c0,4e0,4g4,4 として処理されるようになる。この「蓄積」やタイムライン位置補正は、特殊な命令をコンパイラが処理することで、既存の仕組みに影響をあまり及ぼさずに行っている。
和音は面倒かなと思っていたのだけど、それなりに簡単に実装出来たので助かった。こんな感じで少しずつほしい機能を実現していきたい。
Leave a comment