いう変換ツールを発表しました。開発着手時に「既に優れたツールがあれば開発する必要はないのでは?」と思い各種MIDI2MMLプログラムを比較してみたものの、納得のいくものが見つかりませんでした。譜面の簡素化と演奏精度の保持を両方がんばっちゃおうという欲張りコンバータです。アーカイブファイルをダウンロードして適当なフォルダに展開します。ファイルをドラッグアンドドロップすることで変換が可能です。インストールとパス設定が行われていない状態なので、無料Javaソフトウェアをダウンロードしてください。コマンドオプションより高度な変換を行う場合、オプション指定を伴うと効果的です。オプションの一覧はバッチファイルをダブルクリックして起動すると表示されます。変数にオプションを記述します。--no-quantize"現時点で利用可能なオプションは下記の通りです。クオンタイズによるノート長の調整を行わない。タイミングが正確になる代わりに複雑な音符が多くなる。三連符らしき箇所を三連符記法に置換する(賢くなく、実用性に乏しい)*2使い方は以上です。技術的アプローチに関する説明です。知らなくても特に問題ありませんが、中身を知っているとお望みの変換がしやすくなるかもしれません。既存のツールの出力に満足できなかったので開発しました。いう簡素なツールだったのですが、連符や細かいタイミングに対応していないため精度は低く、ソースコード非公開のため修正もできませんでした。別のツールを探していくつも試してみたのですが、同じような問題を抱えていたり、複雑なMMLが出力されたりして、満足感が得られませんでした。処理の詳細は後述しますが、以下が変換の主な流れです。変換(ノート認識、クオンタイズ、拍子ごとに改行など)MML変換の難しさMIDI→MMLが難しい理由はいろいろありますが、理由の一つとして、解が一通りではないことが問題です。d16.r32上記の2つは同じ演奏情報を異なる形で表現しています。前提として愚直に変換すると複雑な音符が出力されてしまいます。値を適当に調整しなければならないのですが、果たしてどう調整すれば良いかが新たな問題となってきます。本書では、この譜面簡略化のための処理をクオンタイズ(処理)と呼ぶことにします。どのような結果を良しとするかは、目的や感性にも依存します。簡潔な譜面を求めていれば細かすぎる休符は邪魔になるでしょうし、逆に演奏精度を求めているのにノートが大幅に簡略化されてしまっては困ります。連符が使えないシステム向けに連符を綺麗に変換しても役に立ちません。そのため、良質なクオンタイズのためには簡略化の程度を示すパラメータを設けることが不可欠であると考えました。オプションは決して万能ではありませんが、これらの要求への柔軟性を与えるものとなっています。その他、下記のような問題が変換処理のハードルを上げているのではないでしょうか。変換、付点・連符への対応方法(これらも解が複数存在する)これらの諸問題に対する解法を一切知らなかったので、わたしは石油王を目指す間も惜しんで対応アプローチを自ら考えました。MIDI→MMLのロスレス変換はじつは難しくない?難しいのか難しくないのかはっきりして欲しいところですが、難しくないのです。ずれもなく変換することは常に可能です(tick表記は使用しない)。組み合わせで表現できることを証明します。現実には証明通りにMIDIファイルを処理するのは問題があります。いうノートに変換されますが、これほど細かい音符を扱えるMMLは稀なはずです。扱えないかと言えば、個々のMML音楽再生エンジンにも内部的な分解能があり、最小の音符の長さが決められているからです*4。この問題を解決するのは簡単で、MIDIファイルの分解能がMMLの分解能に一致するように前処理を行えば良いです。分解能の変更はtick単位で実施する処理なので、必要最低限しか精度が落ちることはありません。これで短すぎる未対応音符の存在は消えます。副次的な作用として、MMLの分解能を適当な因数で割ったより小さな分解能にすれば、出現するノートの種類をさらに制限することができます。分解能を8にすれば、32分音符より細かい音符が出現することはありません。タイを書き連ねたりしたら、ユーザーはわたしの家にくさや爆弾を仕掛けるかもしれません。N部音符の変換方法は一通りではありません。ノート同士をタイで結合しないと表現できない長さもあります。それらを単純な計算式で求めるのはおそらく困難でしょう。この問題は変換用のルックアップテーブルを用意することで難易度をぐっと下げられます。最大値を既定しなければいけませんが、じつはその必要はありません。長い音符については全音符×2個分で割った余りについての長さ表現をテーブルから取得して、頭に必要な数の全音符を付ければ良いのです。グッバイ!くさや!次なる問題はテーブルの内容と構築方法ですが、tick→音符変換のシンプルな解は次のようなものであると考えられます。タイを使わず単一のノートで表現できる解が最も良いノート2つの組み合わせはその次に良い、3つはその次に良い、etc.よって、次の手順でテーブルを構築します。簡潔な表現にて変換することができます。音長変換テーブルの内部形式ですが、単純な変換には音程を置換可能な文字列形式であれば問題ありません。クオンタイズを行おうと思うと、タイでつながれた個々のノートの長さや、付点を分解したときの最小の長さなどを知りたくなってきますので、文字列表現を保持すると同時に、tick数の組み合わせを保持しておくことをおすすめします。上述のアプローチで入力に忠実なMIDI→MML変換を行うことはできますが、半端な長さのノートが出現すると複雑なノートが出力されてしまいます。前処理で分解能を低くしておけばノートも単純になるのですが、発音開始タイミングも粗くなってしまうのはやや悩ましいところです。自然な譜面表現とは、よく紙の楽譜で見るような形だと思います。下記のような特徴があります。音符や休符は、M分音符の2等分または3等分の長さで表現される(Mは2の冪乗数、5連符などは一般的でない)演奏上の非常に短い休符などは記さず長い音符として扱い、スタッカートなどの奏法記号で補うよって、このような処理としました。ノートの発音開始タイミングは変更せず、終了タイミングのみを調整する。開始タイミングは変更時の感覚的な影響が大きいため保持する。開始・終了の両方を調整したければ入力分解能を変更する。ノートの長さを、M分音符の1/2や1/3などの綺麗な近似値に変更する(Mは2の冪乗数)非常に短い音符・付点表現を伴う場合は採用せず、より簡素になる近似値を採用する。発音間隔がそもそも短いなど、すべての候補が対象外になる場合は、クオンタイズ精度指定を無視して採用する。具体的な処理内容はおよそ下記のとおりです。調整前のノートのtick数(理想長:精度面で理想的な長さ)、次のノートまでのtick数(最大長:ノートが取り得る最大長)を取得する。長さ情報が全音符を超える場合、全音符で割った余りに変換する(全音符の数は記憶しておき、最後に付加する)理想長以上の長さのM分音符(Mは2の冪乗数)のうち、長さが最短となるMを求める。調整後の長さとする(最大長を超える場合は最大長とする)長い音符ほど相違が大きくなる特徴がありますが、代わりに表現はより簡潔になります。頭のなかで様々な方法を模索したのち上記の方法に落ち着いたのですが、考えてみればノートの長さを2と3の公倍数の粗い分解能に調整するのと、ほぼ変わらないような気もしてきました。様々なケースが考えられるため実際のところはわかりませんが、クオンタイズに関しては再考の余地があるような気がしてなりません。上記はMMLのqコマンドの値を一切考慮しない方法ですが「qコマンドの値の変化が少なくなる結果を良しとする」方法もあると思います。探索がより複雑になりそうなので今回は試みませんでしたが、うまく処理できれば結果は期待できるかもしれません。変換後のMMLは単純な文字列ではなく、コマンド文字列のリストで保持することをおすすめします。最適化や順序変更が行いやすいからです。あとがき改めて書きながら読み返してみると、特別に斬新でもなんでもないような気がしてきました。それでも良い結果が出せている(と思う)のを見ると、この情報もまんざら無駄でもないのではとも思います。本書が似たようなことに挑戦する人の一助になればうれしく思います。16分音符を指定しても、発音タイミングが細ければさらに短い休符等が出現することはある。三連符相当の音符は出現する。3の倍数を指定しなければ良い。略で、4分音符あたりのtick数のこと。N分音符までしか扱えないシステムの分解能はN/4になります。*5:表現可能な要素とは、すなわち長さをtick単位で求めた際の余りが0のノートである。»プロフィールid:GOCHADTM、TAS、プログラミングが趣味です。かわいいものがすきです。)にも興味があります。技術系の一般記事を書いています。動画にときどき投稿します。gochaはてなブログをはじめよう!GOCHAさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。