ym2151-tone-editor
YM2151(OPM)FM音源音色エディタ。Windows用。TUI。Rustで書かれています。
状況
開発中です。現在の進捗率は80%。残り20%はkeybinds追加と音色管理。
- 今後の展望
- ※すべて検証用の仮仕様であり、頻繁に破壊的変更をします
- 音色保存とGitHub管理に適したセーブの仕組みを構築する。後述。
- 大幅なkeybind変更をする。後述。
特徴・機能
- YM2151音色パラメータを編集
- マウスだけでも操作可
- カーソルキーで移動、PageUp/PageDown/Home/Endで値を増減
PまたはSPACEキーで音色プレビューESCキーで終了- 終了時に音色を自動セーブし、次回に自動ロードして続きを編集可
- keybinds設定可
クイックスタートガイド
今後書く予定です WindowsにRustがインストールされていれば、GitHubから楽にインストールできます
コツ
- 画面いっぱいに表示したいとき:
- Windows Terminalなら、
ALT+ENTERやF11でウィンドウ最大化したあと、CTRL++でフォントを拡大できます
- Windows Terminalなら、
YM2151音色データ形式
Parameters
| Parameter | Name | Range | Description |
|---|---|---|---|
| DT | Detune | 0-7 | Fine frequency detuning (3 bits) |
| MUL | Multiplier | 0-15 | Frequency multiplier (4 bits) |
| TL | Total Level | 0-99 | Operator output level (7 bits, limited to 99) |
| KS | Key Scale | 0-3 | Key scaling (2 bits) |
| AR | Attack Rate | 0-31 | Envelope attack rate (5 bits) |
| D1R | Decay 1 Rate | 0-31 | First decay rate (5 bits) |
| D1L | Decay 1 Level | 0-15 | Sustain level (4 bits) |
| D2R | Decay 2 Rate | 0-15 | Second decay/sustain rate (4 bits) |
| RR | Release Rate | 0-15 | Envelope release rate (4 bits) |
| DT2 | Detune 2 | 0-3 | Coarse frequency detuning (2 bits) |
| AMS | AM Sensitivity | 0-3 | Amplitude modulation sensitivity (2 bits) |
動作要件
- Rust 1.70 以降
ビルド
cargo build --release
実行
cargo run
または、コンパイルされたバイナリを直接実行:
./target/release/ym2151-tone-editor
リアルタイム音声フィードバック(Windows限定)
エディタは、ym2151-log-play-serverライブラリのensure_server_ready()関数を使用して、サーバーの準備を自動的に確保します。これにより、サーバーのインストール、起動、準備状況チェックが自動的に処理されます。
# 音色エディタを実行するだけ - サーバーは自動的にセットアップ・起動されます
cargo run
動作モード
エディタは2つのモードで動作します:
インタラクティブモード(デフォルト)
インタラクティブモードでは、サーバーが継続的にオーディオをストリーミングし、パラメータ変更時にレジスタ書き込みコマンドのみを送信します。これにより、より効率的でスムーズな音声フィードバックが提供されます。
レガシーモード
デフォルトでは、エディタはsend_jsonを使用して名前付きパイプ経由で完全な音色データをJSON形式で送信します。パラメータが変更されるたびに、新しいJSON全体が送信されます。
比較
| 特徴 | レガシーモード | インタラクティブモード |
|---|---|---|
| データ送信 | 完全なJSON | レジスタ書き込みのみ |
| 効率性 | 低い(毎回全データ送信) | 高い(変更箇所のみ送信) |
| 音声連続性 | パラメータ変更時に再起動 | 継続的なストリーミング |
| 用途 | 比較検証用 | 通常の編集作業 |
操作方法
※今後、破壊的変更されます。検証のためです
| キー | 動作 |
|---|---|
| カーソル移動 | |
| 矢印キー(←↓↑→) | それぞれの方向にカーソルを移動 |
| 値の変更 | |
PageUp / e |
カーソル位置の値を増加 |
PageDown / q |
カーソル位置の値を減少 |
+ / . |
値を1増やす |
- / , |
値を1減らす |
Shift + . (>) |
値を10増やす |
Shift + , (<) |
値を10減らす |
Home |
現在のパラメータの最大値に設定 |
End |
最小値(0)に設定 |
r / R |
ランダム値に設定(有効範囲内) |
| マウス | |
マウスホイール上 |
マウスポインタ位置にカーソルを移動して値を増加 |
マウスホイール下 |
マウスポインタ位置にカーソルを移動して値を減少 |
| その他 | |
ESC |
保存してアプリケーション終了 |
コマンドラインオプション
| オプション | 説明 |
|---|---|
--value-by-mouse-move |
レガシーマウス動作を有効化(マウスの左右移動でカーソル位置の値を変更) |
依存関係
ratatui0.28 - ターミナルUIフレームワークcrossterm0.28 - クロスプラットフォームターミナル操作ライブラリ
コンセプト
- 100msで起動、100msで音が鳴る ※数値は雑。1秒よりは大幅に短い程度のイメージ
- キーを押せば音が鳴るし音色も変化する
- 「触っても鳴らないし編集できない、よくわからない」を優先して対策する
- カラフルに可視化
- シンプル
- 最低限の編集だけならとっつきやすい操作(カーソル、マウス)
スコープ外、目指さないこと
- 高機能エディタ
- 初心者から超上級者まで全員が満足する完璧な万能エディタ
- 無制限のインテリジェントなUNDO
- 各種インテリジェントでフルオート、わかりやすくミスなく使えて柔軟で高度な編集機能
- インタラクティブ
- 仮想MIDIキーボードによる高度にインタラクティブな演奏、サーバも共有メモリを使った低レイテンシの高度なリアルタイム処理に変更
- レスポンスのよい高度にインタラクティブな演奏全般
- GUI
- グラフィカルな音色の可視化。専用ターミナルエミュレータによるエンベロープや波形のビジュアライズ、16msecで表示更新する高性能オシロスコープ
- 高機能なライブラリアン
- すべての音色に柔軟な操作でわかりやすく素早くアクセス、プレビュー、選択、編集、高度にインテリジェントな版管理
- 既存楽曲からのフルオートあるいはインタラクティブで高度な音色抽出、その成功率100%
- 全てのYM2151音色フォーマットを自動判別して読み込み、自動判別成功率100%
- 全てのFM音色フォーマットを自動判別と自動変換して読み込み、その成功率100%
- 高度な拡張性
- オートメーションを利用した高度な音色作り
- 8channelすべて、さらには複数YM2151を利用した高度な音色づくり
- YM2151の枠組みを超えすべてのFM音源に対応
- DAWやオーディオプラグインすべてに対応して、それぞれを演奏可能、それぞれのFM音源の音色のインポートとエクスポート
音色保存用のフォーマットを検討する
- これまでの課題
- ym2151-logフォーマット
- 行数の多いJSONデータ。
- 1ファイルに複数音色バリエーションを入れることができない。
- これをこのままGeneral MIDI用にGitHubでメンテするのはあまり現実的でない。
- サーバ送信用として今後も使う。だが音色管理用のフォーマットとしては、もっと適切なものが必要という感触。
対策案
- ym2151-logフォーマット
- 運用
- 配置
tones/general_midi/000_AcousticGrand.json- メリット
- 自己記述性
- ディレクトリ階層とファイル名で、用途と音色がわかりやすい
- 自己記述性
- commit
- ym2151-tone-editor リポジトリに、1日0回~1回の頻度でcommit
- 配置
- ファイルフォーマット
{ "description": "GM:000 Acoustic Grand Piano family", "variations": [ { "description": "GM:000 Bright Piano", "mml": "t120 o5 l4 cdefgab", "registers": "204F204C364037808003812D" }, { "description": "GM:000 Soft Piano", "note_number": 60, "registers": "204F204C364037808001812D" } ] } - JSONファイルフォーマット説明
- 本体はregisters。必須項目。
- mml,note_number,descriptionは任意項目。
- mmlとnote_numberは省略すると何が鳴るかはアプリ任せ、例えば中央ド
- mmlとnote_numberを両方書いた場合にどちらが鳴るかもアプリ任せ、例えばnote_number、mml、の順番で交互に鳴る
- データフォーマット説明
- アドレスとデータ
- アドレス2文字、データ2文字、のペア、の繰り返し。
- メリット
- 構造化
- jsonであり、自然言語のような曖昧さがなく、シンプルなcodeで読み書きが可能
- 柔軟性
- もし特定レジスタのみに絞り、それを特定の記述方法に固定するフォーマットの場合、以下のような問題がありうるが、それぞれを回避できる
- 例、このフォーマットでは、必要な情報が不足
- 例、どこまで記録すれば十分なフォーマットになるか、フォーマット検討コストがかかる
- 例、あとからフォーマット変更したために、パーサや出力のcodeの変更や、マイグレーションが必要になる
- フォーマット変更とは、記述方法の変更や、対象レジスタの増減など
- もし特定レジスタのみに絞り、それを特定の記述方法に固定するフォーマットの場合、以下のような問題がありうるが、それぞれを回避できる
- 自己記述性
- descriptionで、可読性と自己記述性を担保、それはdir名とfilenameも同様
- jsonであることも同様
- descriptionで、可読性と自己記述性を担保、それはdir名とfilenameも同様
- バリエーション
- 実用上、GM000でも多数のバリエーションがありうるので、
- そこはjson内に配列で保持することで対処
- 実用上、GM000でも多数のバリエーションがありうるので、
- 可読性
- 1行で書き、description先頭なら可読性が高い。音色バリエーション名のlistとして扱える想定
- 移植性
- 移植性が高いフォーマット、このレベルなら楽に相互変換codeを書ける想定
- 一意性
- registersをunique IDとして利用することで、ある程度の一意性の恩恵がある想定
- メリット。重複検知ができるので、過剰な音色ライブラリ肥大を多少防止できる可能性がある
- メリット。ある音色を一意に識別したいとき、IDとして利用できる。
- descriptionが変更されていても検索できる。
- いろいろ取り扱いが楽になる可能性がある。
- メリット。registersを使って検索すれば、「YM2151音色で、誰それのリポジトリにあるデータだ」がわかる。データに自己記述性がある。
- このためregistersは区切り文字を使わないフォーマットを保持することが必要。
- 前提として、GitHub管理で登録されていること、登録場所が自己記述的であること、はある。
- 注意、あくまで、ある程度レベル。ほぼ同じ音色でも1bit違えば別IDなので
- registersをunique IDとして利用することで、ある程度の一意性の恩恵がある想定
- 構造化
- 補足
- slot mask
- registersにnote onを含むことで、slot maskを表現できる。アプリはそこからslot maskを抽出できる。ym2151-tone-editorが実装済み。
- slot maskの用途は、編集しやすい2op音色edit体験の提供など。
- 全256bytesのレジスタ情報すべてをjson保存、は推奨しない。アプリが想定外の動作となるリスクがある想定。
- そこの精査や検討は、後回しにする。YAGNI。あとからアプリ側で対処できる想定。
- モジュレータTLオートメーション等の高度な奏法はこの音色データに含めることができない点は留意されたい。
- つまり、このフォーマットで表現しきれないような「高度な奏法を含む音色データ」は存在しうるし、それとの互換性は限定的なものとなる。
- slot mask
- アドレスとデータ
- 課題と対策
- 課題、128個は手間
- 対策、それ用に簡易的なcodeを書いて対処すれば十分対応可能な想定
- 例えば音色名のlist128行を用意し、簡易codeを用意すれば、json filename生成や、descriptionの生成も楽な想定
keybindsを検討する
- ※それぞれ切り分けて個別のissueにする。安全優先。混乱防止。
- ※ym2151-tone-editor.toml のkeybinds欄で設定可能にする想定
- コンセプト
- カーソルキーとPage Up/Downだけで基本操作は完結する
- 補足
- ショートカットキーで素早い編集と、高機能、を補足する
- mouse左クリックでカーソル移動、ホイールで値が増減、もスタンダードなので実装する
- TUIで右クリックはわかりづらいので回避がよい
- なお、終了など一部の機能はESCのみでいい、それはスタンダードである、という考え。
- +と-で値の増減。広く知られて伝わりやすいため、導入のUX改善となる考え。
- CTRL hjklでカーソル移動。CTRL npfbもカーソル移動。
- カーソルキーなしの移動は、ほかのショートカットキーで実現できてはいるが、これらも使えるとUXがよい、という可能性がある、特に導入時。
- Pとspaceで演奏。今の音のまま連打できるのはUXがよいので。
- FでFB増加、SHIFT+FでFB減少とする。カーソルもFBに移動する。
- 他の類似の操作も、カーソルジャンプと値の増減をセットで行う、それが素早い想定。検証する。
- Tで今の行のTL増加、SHIFT+Tで減少。
- Mで今の行のMUL増加、SHIFT+Mで減少。
- 備忘、もしMがほかが優先なら、X。multipleならxは意味が近いというイメージ。
- A,D,S,Rで今の行のAR,D1R,D2R,RR増加、SHIFT+で減少。
- 補足。WASDによるカーソル移動をやめる。この用途だとミスが多く、メリットを感じられなかった。左手を常時ホームポジションから左に1つずらす必要がある点でミスが多かった想定。
- LでD1L増加、SHIFT+Lで減少。
- D1LのL。見出しでの説明がわかりやすい。
- 1,2,3,4でM1,C1,M2,C2の行に直接移動しつつ、カーソルのある列の値をup。
- SHIFTキーを押しながらだとdown。
- 用途は、OPを横断的に値の増減するとき、素早くやれる用。
- 例、OP1やっててOP4upしたいとき、カーソルキー3回とpage upに対して、
- 4なら1回なので、4倍高速になる。
- 例、OP1やっててOP4upしたいとき、カーソルキー3回とpage upに対して、
- 注意、数字は比較的タッチタイピングしづらいので、aliasでhjklも検証する。
- 5,6,7,8でOP1~4のSlotMaskのトグル。
- SHIFTを押しながらだとsoloモードのトグル。
- modulatorであっても、soloモード中は強制ALG7で鳴らすことで、
- エンベロープ等を確認する用。そして強制SlotMaskが当該行だけonとなる。
- このときのALGとSMは、特殊な色あるいは背景色にしてわかりやすく。
- エンベロープ等を確認する用。そして強制SlotMaskが当該行だけonとなる。
- カーソルのある行が常にsoloモードとなる、つまりSMはカーソル移動で動的に変化する。
- トグル解除すると、トグルonになる直前に保持していたALGに戻る。
- SHIFT+5,6,7,8いずれでもトグル解除とする、まずシンプル仕様。
- つまり2つのopのsoloはしない。まずシンプル優先。
- SHIFT+5,6,7,8いずれでもトグル解除とする、まずシンプル仕様。
- modulatorであっても、soloモード中は強制ALG7で鳴らすことで、
- SHIFTを押しながらだとsoloモードのトグル。
- Kでmouseマルチカーソルlockのトグル。loc
Kで表示説明しやすい。- lockしたときは、Fキーなどを押しても、カーソル移動しない。
- lock対象は複数可。それぞれmouseによる数値増減の対象になる。
- 用途の想定は、エンベロープをまとめて増減しながらプレビューする用。
- lockしていないときは、mouseの挙動は、
- 左クリックした場所にカーソル移動して値up、
- 右クリックした場所にカーソル移動して値down、とする
- lockしたときは、Fキーなどを押しても、カーソル移動しない。
,.で、Noteのdownとupとする。中央ドを中心にしたCイオニアンスケールとする。- ただし値の増減としても有力なので、今後keybind変更も想定する。
プレビューにMMLを使う方法について整理する
- ただし値の増減としても有力なので、今後keybind変更も想定する。
- プレビューMML to SMF段
mmlabc-to-smf-rustライブラリに、プレビューMMLをわたし、smfを得る- 備忘、この時点で音色データをわたすのは複雑なので後回しにする。いずれはマストの想定
- log生成段
smf-to-ym2151log-rustライブラリの、smf to log関数について、- 「
smfと音色データ」を引数で渡し、logを得る - 方法 : https://github.com/cat2151/smf-to-ym2151log-rust/pull/46
- 「