August 2009 Archives

MMLコンパイラが何となく落ち着いたような気分になったので、実際の打ち込みに使えるような音色エディタを作ろうと思っている。そこで初めて気付いたのだけど、音色エディタを作るなら、音色名リストがほしい。ネットで探せば有名どころの音源モジュールの音色リストはすぐ見つかるのだけど、どうせならバルクダンプで音色名リストが取れたりしないものかと思って、試しにプログラムを書いてみることにした。

基本的には、バルクダンプのためのエクスクルーシブを発行して、それからMIDI INポートで段部データのエクスクルーシブを受信すればいい。というわけで、そのようなコードを書いてみたのだけど、どうも受信が上手くいかなかった。それで、portmidiのCで書かれたサンプルを見て、初めて、API(Cのヘッダ)をもとに作成したP/Invokeバインディングではどうもだめらしいということに気付いた。バイト列としてのMIDI INメッセージの受信に適合していなかったというわけだ。というかportmidi.hがおかしいと思うんだけど...

なにぶん初めてINポートをいじったものだから、P/Invokeがまずいのか、portmidiが悪いのか、バルクダンプのやり方がまずいのか、そもそもケーブルの接続がまずいのか...といろいろ検証するのに時間がかかった。が、とりあえず受信は出来るようになった。ただ、受信したバッファの内容がどうにもおかしい。後の操作でバッファを上書きされているように見える。P/Invokeまわりはいろいろトラップがあるので、後でじっくり検証する必要がある。少なくともこれが動かないと、音色リストが生成できない。まあ生成できなくても、拾ってくればいいのだけど...

bulkdump (PortMidiSharp.csおよびSMF.csが必要)

mugene 0.3 release

| No Comments | No TrackBacks

ひっそりとmugeneのリリースを続けている。今回ようやくコンパイル速度を実用的なものにしようと思い立って実現した。プロファイルした結果から(というかしなくても)、マクロと変数の探索で時間がかかっていることはよく分かっていたので、そこさえ最適化してしまえば、残りはイマドキのCPUで大した問題にはならないわけだ。

これまではKeyValuePairのListをLINQのFirstOrDefault()でiterateするという、たいへん重いやり方をとっていたのだけど(それはトラック別マクロなどによる上書きを許しつつ検索を可能にするためだった)、処理するトラックごとに適用対象マクロのhash dictionaryを用意して検索することで、圧倒的に高速な処理になった。10倍くらい。ちなみに、.NET FrameworkにはHashtableをgenericにしたものが無いので、C5というジェネリックコレクションライブラリを使っている。

MMLコンパイラは実は10年くらい前にも書いたことがあって、その時もやはりマクロ名からマクロ定義を取得する部分の最適化をいろいろ考えた。当時は文字列のハッシュ検索なんて考えもしなかったので(MS-DOSでのプログラミングだ)、マクロ定義をソートして、A-zまでのインデックスを振って探索していた。ハッシュテーブルが簡単に使える今はずいぶん楽になったと思う。

ともあれ、とりあえずこれで最大の懸案事項が解決したので、あとはいろいろ試しながらチェックを続けようと思う。とりあえず昨日ひとつ、ナチュラルがきちんと処理できていないという問題に気づいた。まだ使っていない命令には、バグがけっこう潜んでいるかもしれない。

VSQの歌詞マクロ研究

| No Comments | No TrackBacks

VSQサポートMMLで歌詞とメロディが書けるようになったので、vocaloidのヘルプなどを見ながら埋めていた「あ」から「を」までのマクロを全て埋めてみた。これの発音記号が、単純なヘボン式ローマ字表記ではないのだ。

一番分かりやすいところでは、まず「う」段が'u'にならず、'M'になる。'u'が使われているのは「ゆ」だけだ。おそらく、日本語の「う」は一般に発音が不明瞭で、あえて声を出して聞かせる音にはなっていないのだろう。唯一の例外として「ゆ」はハッキリとuを発音するようにしないと、音が聞き取れないのだろうと思う。

次にパターンが明白なのは「い」段のほとんどにシングルクォーテーション(')がつくことだ。これは、50音を埋めても濁点・半濁点を埋めても気付かなかったのだけど、「ぎゃ」などをどう表記するのか調べていて気がついた。「ぎ」は「ぎゃ」「ぎゅ」「ぎぇ」「ぎょ」などと同じパターンに位置づけられているのである。他のイ段の音もほとんどがこれだった。

サ行やタ行の発音記号表記は、「し」「す」「じ」「ず」「ち」「つ」などがバラバラの発音記号表記をもっていて一見かなりカオティックだけど、ここにはかなり豊富なバリエーションがあって、「ちゃ」だの「つぁ」だのといったトリッキーな配列の中に収まっている。ハ行もいろいろあるが、似たような体系の中に収まっている。ラ行など、ついにアルファベットのマッピングではなく、"4 a" "4 e"などの表記になっている。

しばらく肉体労働して、歌詞のマクロは一通り書き出した。ここまでの手応えとして、基本的にvocaloidは英語圏で開発されてきたソフトウェアなんだなと思った。

で、試しにガンダムの歌などを歌わせてみて(たまたま思いついたのがコレだっただけで特にガンダムびいきはない)、さっそく気付いたのが「ぎんがへ」と歌詞を書くとginga "he" となってしまうということだ。しかし「ぎんがえ」と記述するのはいかにも頭が悪いので、「_へ_」という命令を追加することにした。本当は「へ_」にしたかったのだけど、「_へ」という命令が既に存在していたので、両方を囲んだものは e と発音することにした。(多分これは後で追加する命令との関係で混乱のもとになるのだけど...)

次に気付いたのが促音(「っ」)のバラエティだ。はねる、というのは、単純に休符にマップ出来るものではない。実際には2通り(あるいは3通り)の解釈がある

  • 純然たる休符。椎名林檎が「あたしの名前をちゃんと呼んで 体を触って」と歌う時の「っ」は発音されない。
  • 前の母音を引っ張る。 「銀河へ向かって飛べよガンダム」の「っ」は、直前の「か」とキーが異なり、「あ」で発音される。フルノートで引っ張る場合と、スタッカートで半ば休符にする場合で区別する考え方もある。

基本的にmugeneのvsqサポートでは、歌詞コマンドひとつにノートオンひとつが対応していなければならない。休符の場合と、母音の場合とで、以下のように「っ」という命令と「っ_」という命令を使い分けることで、これらを区別することにした。

  • 母音の場合は前の母音でノートオンする。このために、歌詞命令の全てに、どの母音が使われたかを記録する変数を用意して、「っ」が出現したらこれでノートオンすることにした。
  • 休符の場合は何も発音しない。休符やスタッカートの休む部分については、メロディの記述としても休符が入るべきなので、整合性はとれる。

さてこれらは区別できた。次にハマったのが坂本九の「上を向いて歩こう」を打ち込もうとした時である。メロディは rffgafdc rf2gafdc で、まず「む」は実際には「むーいて」のようになり、「む」にaが、「ー」(長音)に f が割り当てられなければならない。歌詞として長音部分を記述するのはやや恥ずかしいものがあるが、何も書かないと識別できないので、仕方なく「ー」は先の「っ」で母音を引っ張るのと同様の処理を加えることにした。

しかし「ー」の解釈はそれだけではなかった。aikoが「あー テトラポットのぼって」と歌う時の「ー」には、ノートオンは割り当てられないのだ。ここでもやはり両者は区別されなければならない。こちらは休符ではないが、やはりノートオンが割り当てられないという点では同じなので、単純に処理をスキップすることにした。

そしてこれまで、実は「っ」を無音、「っ_」を母音という使い分けをしていたのだけど、長音の用途はどうも逆に無音の場合はそもそも「ー」を書かない場合の方が多そうに思えたので、むしろここで前のキーを引っ張る命令に「ー_」を割り当てることにして、それに合わせて「っ」と「っ_」の意味も入れ替えることにした。

さて、「上を向いて歩こう」にはまだ罠があった。「あるこう」の「こ」は先と同じ問題だったので、「あーるこーーう」と記述することで解決できたのだけど、最後の「う」は u (M) ではなかったのである。発音に忠実に書けば「ああるこおおお」すなわち o になる。例によって「あるこお」と記述するのは恥ずかしいので、ここでもやはり「う_」という命令を追加することにした。

そんなわけで、最終的な「上を向いて歩こう」のMMLはこうなった:

// ---- Master track ----
0   VSQ_INITIALIZE_MASTER t120 BEAT4,4

// ---- vocal body ----
1   VSQ_INITIALIZE_TRACK VSQ_SETUP_FIRST_TRACK VSQ_SETUP_DONE
1   うえをむーいて あるこーーう_
1   l4o5 rffgafdc rf2gafdc

1   OUTPUT_VSQ_TEXT

たったこれだけの歌詞を記述するのに、vsqサポートのマクロ定義には、何度か書き換えが行われた。でも「うえおむういて あるこおおお」と記述するよりは、だいぶマトモなのではないかと思う。こういう微妙な工夫で、歌詞がより自然言語に近いかたちで記述できるなら、無駄ではなかっただろうと思う。

いずれにせよ、まだ他のパラメータを何もいじっていないにもかかわらず、vocaloidの音声合成の深みを味わうことができて、これはこれでとても面白かった。

VSQ出力が出来た

| No Comments | No TrackBacks

VSQデータの出力に挑戦して5日目。ようやくVocaloid2 Editorが読み込んで発生することの出来る簡単なvsqデータをmugeneで生成できるようになった。MMLにこんな感じで記述して、コンパイルするだけで、.vsqファイルが出来上がる:

// マスタートラック
0   VSQ_INITIALIZE_MASTER t120 BEAT4,4

// ボーカルトラック
1   VSQ_INITIALIZE_TRACK VSQ_SETUP_FIRST_TRACK VSQ_SETUP_DONE
1   あいうえおが
1   l8o5 c4.d2efg2a2
1   OUTPUT_VSQ_TEXT

歌詞と発音コマンドが1つでも食い違うと例外が飛ぶという大変な状態だけど、これで音階と歌詞を別々に記述して効率よく打ち込みができるようになった(例によってMMLでないと嫌だという人にしか意味がないが)。

歌詞のマクロはかなりいかがわしいので、これでどこまできちんと書けるのか正直かなり疑わしいのだけど、とりあえずポルタメントなども指定できるはずなので(しかもスペクトラムが使える...はず)、ノウハウさえ分かっていれば、ブレシネスやオープンネスなど、NRPNやメタトラックでいじれるパラメータはvocaloid2 editor並にいじれるようになるのではないかと期待している(もういじれるのかもしれないが未確認)。

ちなみに、出来上がってから実験してみて気付いたのだけど、発音命令のためのNRPN出力を生成するためにいろいろがんばっていたのは、どうもあまり意味がなかったようで、この辺のNRPNは無くても再生できてしまうようだ(!)。まあRewireなどでデータを送る時にはmeta情報が切り捨てられることになるのかもしれないけど。その意味ではNRPN出力の正しさは全くもって未知数だ。

しかし当初はmugeneの機能のproof of conceptとして試作してみるつもりだったのに、気がついてみたらいろいろvsq対応のための特異な命令をいくつも追加してしまった。思えば拡張性を確保するためのリファクタリングを行ういい機会だったのかもしれない。まあ、コードを改善すること自体は目的ではなかったので(今でも目的はMMLの書きやすいコンパイラを作ることだ)、無理に手を出していたらいつまでも完成しなくてかえってやる気がなくなっていただろうから、これでいいのだろう。

実装がもう少し安定したらVSQ出力のデモになるサンプルMMLを書いてみようと思う。

VSQ出力に挑戦 3日目

| No Comments | No TrackBacks

3日目にしてようやくNRPN部分を眺め始めたのだけど、どうやら想像していたよりもはるかに厳しい問題になりそうだ。

ひとつには、NRPNの領域では、歌詞にかかる命令を、発音のタイミングでセットアップしておかなければいけないようだ、ということがある。現状では、歌詞の部分をあらわすMML命令("あ"とか"ぱ"とか)はステップカウントをすすめないことが前提になっていて、かつまとめて書きやすくなるように設計してある。ということは、歌詞をMMLで記述してから、音階をまとめて記述すると、音階のはじめの部分を書こうとした時点で、歌詞のMMLでハンドルを定義された際にNRPNも出力してしまうと、単純にNRPNのタイミングがおかしくなってしまうのである。

これを回避するためには、NRPN部分をノートオンに合わせて「後出し」するしかないわけだが、それを行う方法が無い。どうやらまた特殊命令を追加するしかないようだ。

そして、NRPNの中ではphoneticsすなわち歌詞のアルファベット部分も定義しなければならないようで、これが音によって長さが変わるので(たとえば「あ」は1バイトだけど「が」は2バイト、「ぎ」は3バイト)、これを柔軟に引数として指定できなければならない。ややこしいマクロ定義にすれば、現行のMML文法でも出来なくはないことはないが、なかなかハマりそうだ。

いずれにしろ、楽曲を書きやすい文法が実現できなかったら意味がないので、実現可能でないのであれば、この方面からは撤退するのもやむを得ないだろうと思っている。

VSQ出力に挑戦 2日目

| No Comments | No TrackBacks

ある程度予想されていたことではあるけど、mugeneにかなりいろいろ手を加えた。ほとんどがバグフィックスだ。一番びっくりしたバグは、識別子参照の解決で変数名を全く考慮していなかったということだ。よくこれまで動いていたな...。バグフィックス以外では、base count (time divisionsでもいい)を指定するディレクティブを追加して、192以外の値も受け付けるようにしたことがある。vsqだと480がよく使用されているようで、もしかしたら必須なのかもしれない。

メタトラック生成はだいぶ出来てきたのではないかと思う。もしかしたらもう出来ているかもしれない。とりあえず今書いてあるサンプルMMLと生成されたSMFを公開しておこう。実用するときもこれくらいシンプルなMMLで動けば良いのだが...

あと地味なところでは、歌詞の直接記述は LYRIC というマクロにしていたのを L にした。これはミクやリン/レンを使う場合には多分あまり問題にならないのだけど、ルカのサンプルvsqを眺めてみて、英語の歌詞入力が日本語の場合に比べてはるかに柔軟で難しいことを知ったためでもある。たとえば "give" に一音を割り当てて、複雑な発音記号を指定する場合がある。そのたびに LYRIC などと書いてはいられないだろう。

次回はそろそろVSQをvocaloid2 editorに食わせてみようかと思う。

VSQ出力に挑戦中

| No Comments | No TrackBacks

mugeneのdogfoodingも兼ねて、VocaloidのVSQを出力できるようにならないかと思って、実験的にマクロを組んでみている。個人的なメモや計画ノートはgoogle docsに書いていたので、全然整理されているわけではないけど公開しておこう

Vocaloidの演奏命令データのファイル形式はSMFに準拠していて、その内容はメタイベントとNRPNだけからなる。NRPNはNRPN命令とDTE命令を使えばダイレクトに指定できるので問題にならない。メタイベントの方はややこしい。NRPN以外の命令は、ひとつのメタテキストイベントとして処理される(実際にはSMFの制限上メタテキストイベントは127バイトずつに分割されるが)。その中に、イベントがタイムラインに沿って記述されるような形式になる。発音命令には歌詞への参照がついて回り、その歌詞も同じメタテキスト上にイベント定義として展開される。

VSQファイルのフォーマットについては、詳しく解説しているサイトがいくつかあるので、興味があったら適宜探してみるといいと思う。

さて。これまでのmugeneでは、コンパイル中にテキストを蓄積しておいて後で展開するような仕組みが無かったので、やっつけでbufferという型を新設して、そこに文字列を追加する命令も提供するということにしてみた。bufferの実体はStringBuilderで、Append()やAppendFormat()を使うことで、膨大な文字列結合に伴うメモリ消費を回避するという仕掛けになってもいる。

追加されるテキストの中には、現在のタイムライン上の位置を出力しなければならないものがいくつかあるが、演奏命令の絶対位置をユーザマクロで随時参照できるような気違いじみた仕組みにしておいて本当に助かった。普通のMMLコンパイラではこんなことはまず出来ないだろう。

VSQには、他にもマスタートラックの制御など、いくつかの点で従来のmugeneでは困った箇所があったのだけど、とりあえず気づいた部分は全て修正した。で、準備ができたと思って、少々骨の折れる作業ではあったものの、VSQサポート用の膨大なマクロを書いてみた

とはいえ、まだVSQが生成できるようになったわけではない。どうもコンパイラの変数定義まわりにバグがあって、正しく変数を参照できていないようだ。バグを修正してから、このマクロに足りない部分を多々補って、それでようやくVSQが生成できるようになる、かもしれない。これはまだしばらくかかりそうだ。

mugene 0.1 release

| No Comments | No TrackBacks

ようやくMonoDevelopでMakefile統合とtarballプロジェクトが期待通りに動くようになったので、リリースアーカイブを作ってmugene v0.1としてアップロードした。

シェルスクリプトでは、デフォルトのマクロを全て取り込んでいる。

スペクトラムまわりなどで、文法を多少変更する可能性があって、まだ文法仕様として安定しているとは言いがたいのだけど、とりあえず楽曲データを作れるだけの実用的なものにはなっていると思う。

そのうち公開できる曲データもサンプルとしてアーカイブに含めるようにしたい。

mugeneがある程度曲データをコンパイルできるようになって、mldspがそれなりにビジュアルに再生してくれるのであれば、これにMMLエディタを統合してしまえば、ちょっと便利なオーサリング環境が構築できるのではないかと思っている。デスクトップで実現するのであれば、エディタコンポーネントはちょいと心当たりがある。

しかし、それ以上に、web上で完結できるのであれば、それはそれでアリじゃないかと思い始めた。mldspはSilverlightアプリだから、ブラウザDOMへのインタラクティブなアクセスは可能だ。

その場合、ネックになるのはMIDIデバイスへのアクセスだ。FlashにもSilverlightにもMIDIデバイスのアクセスを許すAPIは無い(Flashであればustreamがユーザの承認のもとでWebCamにアクセスできるので、同じようにMIDIデバイスへのアクセスも可能なんじゃないかと考えたが、どうやらマイクとカメラだけらしい)。MIDIファイルを再生させるだけならembed要素などを使えば(uglyながら)可能だが、一時停止などSilverlightからの(Javascriptを介した)インタラクティブな操作ということになるとそうもいかない。

そこでまず思いついたのがHTML5のaudio要素だ。audio要素であれば、JavascriptからHTMLAudioElementを叩けば、再生や一時停止などが指示できる。もしかしてこれでmidiファイルがサポートされているのではないか、と期待して試してみたが、少なくともcontrols属性を付けて出てきたUIオブジェクトは、未サポートのメディアのものだった。そうすると、今度はカスタムメディアサポートをadd-onとして実装できないかというところに行き着くわけだけど、mozillaのMDCが落ちていていろいろ確認できない。

そしてもう一つの可能性に気づいた。Javaにはjavax.sound.midiというインターフェースがある。だから、Appletを作ってそこからMIDIファイルを再生するようにすればいいのではないか。AppletにはどうやらJavascriptを介した操作の仕組みがあるらしい(ほとんど知られていないそうだが)。MIDIデバイスへのアクセスについては、一度ユーザから認証を得る必要があるそうだが、それさえクリアできれば後は問題なくいけるようだ。

実現方法としては、NPAPIを調べてfirefoxのadd-onを作るより、Appletを書く方が簡単かもしれない(書いたこと無いけど)。ただ、今さらAppletかとも思うし、それならばNPAPIの勉強でもした方が面白いかもしれない。そもそも、カスタムメディアサポートがあるのかどうかも分からないのだけど。

条件コンパイル

| No Comments | No TrackBacks

MMLを書いていると、一部の命令をスキップしたり、特定のトラックだけコンパイルしたり、今書いているブロックだけ演奏して確認したくなることが少なからずある。これを実現するひとつの方法が、コンパイルするMMLを限定するプリプロセッサ ディレクティブを指定するというやり方だ。音楽の授業で特定のブロックから合奏練習を始めるのと同じようなものだ。

これは完全なものではないけど(特に音色指定やテンポ指定をどう処理するかという意味で)、とりあえずある程度の実用性はある。とりあえずブロック指定とトラック指定は実装した。じつのところ、今の時点でやるつもりではなかったのだけど、昔書いたMMLを移植するのに、これを使っていたのを取り外すのが面倒だったのでサポートすることにした。

他にも演奏デバッグ用の方法はいくつか考えられ、いくつかMMLのマニュアルにも記載してあるのだけど、実装が面倒なものがいくつかあるので、その辺は後で着手しようと思う。たとえば小節のサポートなどは、かなり面倒そうだ。同じ条件コンパイルディレクティブの手法では無理ではないかとも思っている。

yacc shaving

| No Comments | No TrackBacks

これまで、MMLパーサの解析は、手書きのlexerで解析したトークン列を、これまた手書きのparserでツリー構築する形でやっていたのだけど、式の優先順位がめちゃくちゃだったので、リリース前に他を一切直さないとしても(そんなことはないのだけど)これだけはどうしても直したかった。で、parserだけであれば普通にyaccっぽく書いてしまえということで、jayのC#版(monoに入っているやつ)を使って書いてみた。

そしたらハマるハマる。parserの時点では、トークン列の処理はだいぶ気を使っていたつもりではあったのだけど、それでもconflictが生じたりはしている。今は落ち着いているように見えるので、conflictの深入りはしていない(重要な問題ではなさそうに見えるけど)。もっとも、ハマりにハマったのは、大抵自分の書いたjayのコードの問題なのだけど...まさにyak shaving。':' とか '|' が抜けるだけで全く意味が変わってしまうので、jayのデバッグ出力やjayで生成されたコードに追加できるデバッグ出力などを読んで、問題点を探す作業でだいぶかかってしまった。

ともあれ、これで、おもちゃ過ぎて笑えてしまうような大きな部分が無くなって一安心である。あとはmakeでちゃんとしたスクリプトを生成するようにしないと、まさに自分専用ツールになってしまうので、その辺を少しいじったらリリースしてもいいかもしれない。いやそうしたら英文のMMLイントロダクションを作成しないといけないのだけど...

昨日は、portmidi-sharpのサンプルに付けている仮想MIDIキーボードにも、多少ユーザビリティを改善してみた。これまでほとんどproof of conceptに過ぎなかったのだけど、MMLを書く時にコレは手放せないので、今後どんどん重要な存在になっていくはず(自分的に)。

次はとりあえず、MML入門テキストに追加していた時に気がついた、ピッチベンドをスペクトラムで指定していった時に変な発音命令が出ているという妙な問題を解決する必要がある。たぶん何かのマクロが競合して悪さしているのだろうとは思うけど。何となく、柔軟な文法の副作用が紛れ込んでいるような気がしてならない。

MML文法のイントロダクションを書いてみた。最初の一歩から書くわけで、いろいろ気を使わなければならないはずなのだけど、どこまで配慮すべきなのか、いまいちよくわからない。そしてコマンドラインツールの使い方を説明していないことに気がついた(実のところ、シェルスクリプトが提供されたら、いくつかのマクロ定義ファイルはデフォルトで参照することになるので、exeの使い方とは多少異なることになる)。

こんなのを書いているということは少なからず現実逃避しているということでもある...いかんいかん。

mldsp 0.2

| No Comments | No TrackBacks

ちょっとMonoDevelopをいじる必要があったので、ついでにmldsp-gtkにMIDIデバイスセレクタを追加して、スペアナ付きの機能追加バージョンとしてリリースすることにした。downloads / web

相変わらず重いのだけど、0.1を試してみたらやはり重かったので、バージョンアップによる効果というより、そもそもmoonlightが重いようだ。

さて。

mldspに限らず、今作っているコードの多くは、組み合わせて利用するようになるだろうと思っている。mldspにはキーボード等の入力を反映し(mmk)、音色パッチエディタを組み込み、テキストから命令を一括送信する(mugene)機能が追加されるだろう。現在でもSMFを読み書きするライブラリ(SMF.cs)は、全てのライブラリで共通して使用されているが、全て手動でコピーしている。これは共有するようにした方が好ましいだろう。

mldspをメインにした統合アプリケーションを実現する予定は今のところ無いのだけど、そういうアプリケーションが多々出現する理由が何となく分かった気がする。

そんなわけで、そのうちgithub上にあるモジュールを全部一緒にすることになるかもしれない。

mugene MML sample #1

| No Comments | No TrackBacks

ようやくgithubにソースを移行して、プロジェクト名もmugeneにして、ソースを多少整理した。ソースは github に置いた。とりあえずMonoDevelopかVisualStudioでビルドするしかない(VSでビルドできるかどうかは知らない。少なくともパッケージプロジェクトは開けないはず。問題ないけど)。mugene.exe に default-macro.mml と自分のMMLを渡して実行することになる。default-macro.mmlはあくまでデフォルトなので、明示的に指定する必要がある。

本当はmakeでビルドできるようにしたいのだけど、いま動かしているMac版monodevelopでMakefile生成がうまくいかないので、とりあえず後で追加することにする。デフォルトマクロをmugene.exeに既定で追加したシェルスクリプトなども生成したい。.NETユーザがどう使うかは...知らない。自分でコマンドライン引数を追加してくれればいいと思う。

とりあえずモノトーンの単純な曲ということで、フリー宣言の出たFalcomのYs2から、曲というか効果音をひとつコピーしてみた生成されたSMFも置いておいた。(あまり本題と関係ないが、MacのQuickTimeでこれを聴いてみて、テンポ指定も無視するほどMIDIサポートのレベルが低いのかと驚いた。)

MMLを見てみると分かるように、いきなりスペクトラム引数などを使っている。これはテンポが緩やかに遅くなっていくためだ(すっかり忘れていた)。しかもいきなりスペクトラムの文法を変えることになった。やはり実際に使い始めてみるといろいろ問題が出てきて楽しいな。

次はもうちょっと複雑なサンプルを作ってみようと思う。

追記: しばらく前にSiONで作成した習作MMLを一部だけ移植してみたが、多少の問題を修正したら、概ねストレートに移植できた。いい感じだ。そろそろMMLのイントロダクションを書かないとなあ。

MML cleanups

| No Comments | No TrackBacks

今日はMMLコンパイラに細々とした修正を大量に加えて、仕様もいろいろ書き直した。必ずしも現状を表しきれていない部分はあるけど、概ねMML仕様ドキュメント通りのことは出来るようになったのではないかと思う。

今日はシステムエクスクルーシブまわりもいろいろ修正を加えて動作するようにした。と言っても特別な命令を追加することなく実装できた。GSチェックサム計算などは特別な命令が必要になるかと思っていたけど、'%' を剰余演算子として使うことにしたので、単純に計算式で解決できた。'%' はステップ値で音長を指定する時に使うので、競合すると思っていたのだけど、実際にはループ脱出命令の '/' と同じで、数値の後に続く場合は演算子として解釈が可能だった。

そして、剰余演算子を定義したことで、これを実現するために無理矢理関数の代わりを定義していた部分を全てとっぱらって式に置き換えることができた。これで問題になっていた部分を多くクリアできたと思う(テンポ指定やピッチベンドは複数バイトにまたがる命令だったので剰余が使われている)。そもそもこの辺は未実装のままだった。

SysExの実装にともなって、GSエクスクルーシブ命令を大量に定義したマクロを追加したので、GS音源を叩くための基盤は出来たと思う。ここから先はユーザマクロで書いてもらってもいいレベルだろう。

もうひとつ文法に加えた小さくない変更は、グローバル変数の削除だ。これはもともとゲートタイムの分母や、テンポなどトラック独立の変数を定義・参照するために存在していたのだけど、テンポ自体は相対値以外では変数参照なく指定できるし、複数トラックの間で特に相対値が期待通りに解決される可能性は高くない(グローバル変数といえど、トラックごとにMML展開中に解決されるものなので、結局ローカルで定義しているのと変わらない)。それならば、最初からローカル変数として全てを解決するのが妥当だろう。

ちなみに全音符のステップ数を定義している部分だけ、今まだ解決できていない問題が多少ある(音長型を数値型に変換する場合など)。グローバル変数のサポートは、実装してから無かったことにしたので、もしやっぱり必要だということになれば、戻すのは簡単だ(グローバル変数への代入命令だけ、文法的に存在していなかったので、それを追加する必要はあるが)。

曲タイトル等のディレクティブも実装したので、これで基本的な利用には耐えると思われる。今日はこんな時間になってしまったので、サンプルを書くのは次回ということになりそうだけど。

About this Archive

This page is an archive of entries from August 2009 listed from newest to oldest.

July 2009 is the previous archive.

September 2009 is the next archive.

Find recent content on the main index or look in the archives to find all content.

Categories

Pages

OpenID accepted here Learn more about OpenID
Powered by Movable Type 4.23-en