View on GitHub

cat-smf-editor

cat-smf-editor

cat-smf-editor

SMF(Standard MIDI File)を手軽に編集できることを目指している軽量アプリ。UAPMDを利用しています。Rustで書かれています。

現在、編集はほとんどできないです。 その状況で公開するのはラバーダッキングのためです。

これまでの課題と、このアプリが解決すること

AIが編集するセクション

読みづらいのであとでなおすつもり。折りたたんでおきます

機能の詳細、ほか ## 機能(AIによる詳細な追記) - 演奏 - `Ctrl+, → b`またはコマンドパレットの「ずんだもん演奏連動」で連動を切り替えます。連動演奏時にAPIでserverが応答しなければ`mascot-render-server.exe`を自動起動し、editor終了時に自動起動したserverも終了します。起動済みのserverはそのまま利用し、editor終了時も終了しません。exeはeditorと同じディレクトリ、開発ビルド時の兄弟repoの`mascot-render-server/target/release`、`PATH`の順に探します。パレットでは `voicevox`・`ずんだもん` でも検索できます。ON/OFFは`status.json`に保存し、再起動時に復元します(初回はOFF)。演奏中は四分音符ごとに伸縮を先頭から再生し、次の拍で途中の動きを打ち切ります。serverの`mascot-render-server.toml`内の`musical_squash_bounce`で長さ・上下移動量・周期数・減衰・横の広がり量・縦のつぶれ量を独立して調整でき、保存するとホットリロードします。既定は500ms・上下移動3px・周期数1・減衰2・横0.1・縦0.05です。再生対象のずんだもん歌声trackの音符区間だけ口を開閉します。他キャラ・対象外track・休符では口パクしません。テンポ変更・途中再生・A-B repeatに追従し、停止・OFF・終了・通信断で解除します。口画像は初回に遅れて準備される場合がありますが、映像を待って演奏を止めません。口の開閉はserverの既定周期による2枚切替で、モーラ同期ではありません。SMPTE divisionでは伸縮の拍同期を行いません。serverの起動・接続を待たずに演奏を続け、起動・通信エラーを`error.log`へ記録します。 - window titleはアプリ名、SMFファイル名、曲名(先頭track名)、`4tracks`形式のtrack数の順に表示します。未保存の変更がある間はファイル名の直後に`(更新)`を付け、Auto save待機中は`曲.mid(更新)(1分後にauto save)`と表示します。保存後や変更を元に戻したときに消します。左上はPlaying/Stoppedを同じ幅で表示し、再生中は曲先頭からの現在時間、停止中はカーソル位置の時間と小節・beat・tickを同じ場所に表示します。現在時間・合計時間は、曲全体が1時間未満なら`00:00.000`(分:秒.ミリ秒)、1時間以上なら`00:00:00.000`(時:分:秒.ミリ秒)で表示します。合計時間は既存の再生用テンポマップを使い、ミリ秒精度で表示します。再生位置は`32|1| 1`形式で、小節番号は曲全体の最終小節の桁数に合わせて半角スペースで右揃えし、beatだけを既存の拍色にし、tickを半角スペースによる3桁の右揃えにします。Follow・Mixer・Stopの常設表示は省き、`F`・`M`・`Shift+Space`で操作します。`F1`/`?`でhelpを開閉します。 - `Ctrl+Shift+P`でコマンドパレットを開きます。画面上部に1行の検索欄、その下に画面の残りの高さを使う一覧を表示し、絞り込み件数で小窓へ縮めません。現在の入力画面で実行できる操作と、画面を開けば実行できる内部操作を、所属画面・短い機能名・キーで一覧にします。機能名・キー表記・`help`/`quit`/`exit`/`play`など基本的な英語の検索語の部分一致で絞り込み、大文字小文字は区別しません。英字のみのローマ字入力はMigemoでも検索し、`hiraku`で「開く」、`hozon`で「保存」を絞り込めます。辞書はアプリに同梱しています。`quit`/`exit`は終了操作で、既存の保存確認を通ります。上下キーで選び、`Enter`で1回実行、`Esc`で元の画面へ戻ります。閉じたmixerの減音・増音は現在trackを選んでから実行し、既にmixerにいる場合はそこで選んだ対象を使います。未確定入力や確認画面を自動で突破せず、入力途中の取消ではbuffer・選択範囲・focusを保持します。表示中も演奏は続きます。Spectrumウィンドウでも使えます。外部の音色browser・OSダイアログ内の操作は対象外です。空白区切りの語はANDで絞り込み、`add effect`で「エフェクト追加」を検索できます。候補は、Enter確定時と同じ入力文字の選択履歴、全体の選択履歴、その他の順で、それぞれ最後に選んだものを上に表示します。履歴は`%LOCALAPPDATA%\cat-smf-editor\command-palette-history.json`へ保存し、次回起動でも復元します。検索欄は開くたび空になります。 - `w`で2列overlayを開きます。`wl`で右、`wh`で左の列を操作対象にし、`wj`で操作対象の列を次のtrack、`wk`で前のtrackに置き換えます(端では反対側の端へ戻ります)。`ww`以外は、1列のときは先に2列にしてから効果を出します。2列にすると左に現在track、右に次のtrackを表示します。最後のtrackでは右を先頭trackにし、trackが1つなら左右とも同じtrackです。`ww`で操作対象のtrackを1列に戻します。2列かどうか、左右のtrack、操作対象の列は`status.json`へ保存し、次回起動で復元します。左右の表示時刻は常時同期し、カーソル(再生中は再生位置)を各列の縦中央に揃えます(曲の先頭・末尾付近を除く)。操作対象の列は橙色の枠で示します。`g`でgo overlay、続けて`t`(`gt`)でtrack一覧を開きます。`gt1`はtrack 1、`gt2`はtrack 2、`gt4`はtrack 4へ、goを開く前のカーソル時刻を引き継いで移動します。track 10〜33は`n`・`p`を除く`a`〜`z`、track 34〜59は`Shift+a`〜`Shift+z`で、一覧の各行にキーを表示します。60番目以降のtrackは一覧をクリックして移動できます。`gtn`は次のtrack、`gtp`は前のtrackへ移動し、端では反対側の端へ戻ります。`Ctrl+右`は次のtrack、`Ctrl+左`は前のtrackへ、現在のカーソル時刻を引き継いで同様に移動します(例: 4 trackなら`Ctrl+右`で1→2→3→4→1、`Ctrl+左`で4→3→2→1→4)。piano roll/tempo mapでも`Ctrl+左右`で同様に移動し、format 1のconductor track(先頭trackかつnoteがないtrack)ではtempo map、それ以外ではpiano rollを表示します。2列では`Ctrl+左右`・`gt`・track一覧のどれも操作対象の列のtrackだけを置き換え、反対側の列は変えません。反対側と同じtrackになっても左右とも表示します。`gh`は現在trackの先頭行、`ge`は末尾行へ移動します。`Esc`でキャンセルします。 - `V`でNotes表示とRaw表示を切り替えます。Raw表示は各イベントの番号・delta・tick・MBT・bytes(読めるmetaはtext)の右に、Notes表示と同じ内容(ノートは音名・長さ・velocity、それ以外はイベントの説明)を半文字間隔で詰めて並べ、右端にminimapを出します。音名(Note Offの説明内も含む)は鍵盤と同じ12色、meta eventの説明は種類を通常色・中身を紫で表示します。このアプリの専用meta(sequencer-specific)は、byte列でなく`Instrument layers: Organ + Flute (+1 oct, -3.0 dB) · Effects Hall`のように内容を読める形で表示します。Notes/Rawのminimapでは、tempo curveがある場合、conductorのtempo eventの横線をpiano rollのminimapと同じ緑の細いカーブに置き換えます(横軸はBPMで右ほど速く、縦軸は時間)。ノートとほかのmeta eventはその手前に表示します。Notes/Rawのevent list本体とminimapの左ドラッグは、選んだ時間範囲の全trackをA-B repeatします。上下どちら向きにも選択でき、離したときに反映します。event listをつかんでスクロールする操作は廃止しました。minimapの左クリックは従来どおり小節先頭への移動です。2列にしていても、Raw表示中は操作対象の列だけを表示します。 - 1列のNotes表示では、右半分に現在trackの簡易な五線譜(ト音記号・ヘ音記号の大譜表)を表示します。小節の幅はピアノロールと同じで、小節内の音符は次の音符までの時間に応じて間隔を詰め直します(長い休符は縮み、細かい音符は広がります)。音符は長さに最も近い全・2分・4分・8分・16分・32分音符の形で、Note Onの位置に描き、1拍の中で続く8分音符以下は連桁でつなぎます(休符・付点・タイは描きません)。臨時記号は調号と同じ小節内の先行音から必要なものだけを付け、小節線を引きます。他trackの音符は背景にグレーで重ね、音符の無いtrackでは他trackの音符を音高の色で表示します。音符は、dark表示では音高の色をわずかに混ぜた明るいグレー、light表示では黒で描き、演奏中に鳴っている音符はピアノロールと同じ12色で描きます。左端の音部記号・調号(表示範囲左端の調)と、上の曲名・BPM(演奏位置またはカーソル位置)はscrollしません。現在trackとconductorのText meta(0x01)は五線の上にtick位置で表示します。VOICEVOXの歌声trackの歌詞は、各モーラの中心を対応する符頭の中心に揃え、上下の五線の中間に表示します。ピアノロールでは各noteの先頭に白い矩形を背景にした黒字のモーラを重ね、ドラッグ中もnoteに追従します。テンポカーブ上段のnote表示にも、同じ白背景・黒字のモーラを表示します。上部にピアノロールと同じzoomバー・minimap・A-B repeatバーがあり、五線譜の左クリックはピアノロールと同じく、演奏中はその位置から演奏し直し、停止中はその拍へカーソルを移してそこから演奏します。演奏中はfollowがONなら演奏位置を中央に追従し、停止中はカーソルが動くか演奏が止まったときにカーソル位置を中央へ移します。右上のボタンで白い紙に黒インクのlight表示とdark表示(既定)を切り替えます(保存しません)。ピアノロール/テンポカーブを開いている間は描きません。 - 五線譜の下に、カーソル位置(再生中は演奏位置)の1小節だけを全track同じ形式の簡易MMLで表示します。表示中の小節にかかるnoteだけをtrackごとに、同一tick・同一durationの音を和音にまとめてから声部へ分解し、等幅fontで1行ずつ表示します。他の小節の和音から生じた行は引き継ぎません。音のあるtrackを上に集め、track同士は最高音の高い順、各track内の声部も高い順に並べます。同じtrackの行はひとまとめにし、`track2`などの見出しは先頭行だけにtrack固有のMonokai色で表示します。無音のtrackは見出しだけの1行にまとめて下へ置きます。拍ごとの欄(4/4では4欄)をevent list・ピアノロールと同じ拍色の縦線で区切り、各beatの先頭からMMLを表示します。各行の単音の最頻音価(同数なら短い音価)は、`l`でまとめた方が短いか同じ長さになる場合だけ、`l`と一致する音価の省略で表示します(例: `l24 c4de`)。`l4 `のように`l`指定の後ろには半角spaceを置きます。同一tick・同一duration内のoctave重複は表示上だけ省きます。重複を除いて3音以上、かつ元のdurationが8分音符以上の場合だけ和音としてまとめ、2音以下または8分音符未満なら単音の声部へ分けます。和音は低音から並べて` 'ce<g2' `のように前後に半角spaceを置き、引用符内の末尾に音価を必ず付けます。和音内だけ`<`(octave up)・`>`(octave down)を使います。単音は`d2`のように直接表示し、休符だけの行はtrack番号を残して内容を空欄にします。8分音符未満の細かい休符は省き、読める長さの休符は`l4 crd`のように表示します。音価への丸めで伸ばした音の後の休符は、表示音価の終端から配置します。長い休符はその残り時間以下の音価に丸めます。書式は兄弟repo `mmlabc-to-smf-rust`の音名`cdefgab`・音価・休符`r`・臨時記号`+`/`-`・付点`.`と上記の和音表記の範囲に限定します。読みやすさ優先で細かなtick差を通常の音価へ丸め、絶対octave指定・和音外のoctave上下・tick数指定・タイは表示しません。現在trackにnoteがあれば、そのtrackだけを色表示し、他trackのMMLと見出しはグレーにします。noteの有無は表示中の小節だけでなくtrack全体で判定し、noteのないtrackでは全trackを色表示します。色表示する音名は五線譜dark表示と同じ配色で、非発音時は音高の12色を混ぜた薄いグレー、発音中は彩度の高い12色です。五線譜の高さは描画音域・縦zoom倍率と既存の操作バーに必要な高さから算出し、縦zoomバーもその領域に追従します。MMLには残りの高さを使い、固定比率による高さ制限は設けません。MMLは五線譜のスクロールとは独立して下に固定し、画面に収まらない行や長い行はMML内でスクロールできます。track変更時は現在trackの行を表示範囲へ移し、小節変更時は並べ直した先頭へ戻します。行を左クリックすると、演奏とA-B repeatを止め、その行のtrackだけを表示中の1小節分演奏します(現在trackは変えません)。再現可能なMMLの生成や編集・出力は行いません。 - コマンドパレットの`VOICEVOX: 現在のtrackの歌声を選ぶ`で、接続先ENGINEのハミング対応キャラと全スタイルを選べます。通常画面とピアノロール/テンポカーブから開き、ずんだもんを先頭に表示します。検索欄はMigemoに対応し、ローマ字・日本語の空白区切りAND検索、上下矢印、`Enter`で選択し、`Esc`で取り消します。保存済みの試聴WAVがある声には一覧の行に`WAV`を表示し、カーソルを合わせると即座に試聴します。WAVがない声は選択画面を開いている間にbackgroundで1件ずつ合成し、「カーソルの声 → 同じキャラの別スタイル → スクロール領域内に見えている声 → 残りすべて」の順で予約します。対象は未生成の声だけで、重複予約と実行中の声の再予約を除きます。カーソル・絞り込み・表示範囲が変わるたびに待機予約を並べ替え、実行中の1件が終わったら新しい順番で続けます。F5操作はありません。試聴フレーズは「どんぐりころころ」(BPM120・八分音符の`ggeefedc`)です。WAVを`%LOCALAPPDATA%\cat-smf-editor\cache\voicevox\`へ保存し、次回以降や再起動後も再利用します。選択中の声の合成が終わると自動で試聴します。別の声へ移動すると前の試聴を止め、移動済みの声が完成しても再生しません。選択画面を閉じると試聴を止め、待機予約を取り消します。実行中の1件は保存まで終えます。IME変換のEnterでは確定しません。現在の歌声は一覧の色で示し、`歌声を解除`で通常の音源へ戻せます。歌声はtrack名と独立したSMFの専用metaへ保存し、再読込・再起動で復元します。変更・解除はUndoとAuto saveの対象です。通常再生、カーソル・鍵盤・MML入力の試聴に選択した声を使い、歌声ごとに音声cacheを分けます。ENGINEに保存した声がない場合は指定を保持してエラーにし、同じ選択画面から選び直せます。ENGINEは`Ctrl+, → v`でrun.exeを指定し、起動中ならそのENGINEを利用します。 - `j/k`で行を移動すると、移動先のノート1つだけを試聴し、カーソル行を縦中央に保ちます。クリックでは同時刻の和音を試聴します。`h/l`(`Ctrl+上`/`Ctrl+下`も同じ)で小節を移動すると、現在trackの移動先の小節だけを再生します。`Space`で繰り返す再生方法は変わりません。 - 再生開始から音声が実際に出始めるまで(plugin準備中)は、開始行に半透明で点滅する`Preparing playback…`を重ね、緑の再生位置線は出しません。 - 鍵盤の色は調号の主音からの五度圏距離0〜6の7段階で、Monokaiの白・青・紫・緑・黄・橙・ピンクです。調号がなければ灰色です。鍵盤は行の左端・セルの背面へ暗く表示し、押されていない黒鍵は黒で塗ります。鍵盤上の音名とtooltipは出しません。 - MIDIファイルはコマンドライン引数で指定するか、アプリへdropして直接開きます。引数がなければ前回開いたMIDを復元します。通常起動では演奏をGUI生成より先に始め、編集位置・分割画面・履歴・Spectrumは演奏開始後に復元します。音色やeffectは保存された設定を使います。起動順と計測方法は[ADR 0011](/cat-smf-editor/docs/adr/0011-minimal-startup-to-first-audio.html)を参照してください。起動時にファイルが開かれなかった場合は、`Ctrl+O`と同じファイル選択を一度だけ自動で開きます。キャンセル後は空の画面になり、ファイルを開いていない間は左上のStoppedとTracksを表示しません。project管理、原本との紐付き、フォルダー探索はありません。 - `Ctrl+N`で`untitled.mid`をメモリ上に新規作成します。SMF format 1、480 ticks/四分音符、120 BPM、4/4で、作者名・title・track名は設定しません。track 1にnote number 60・velocity 100・四分音符のnoteを置き、そのtrackを開いて自動演奏します。初期テンポと拍子は[現在のCubaseの既定値](https://www.steinberg.help/r/cubase-pro/15.0/en/cubase_nuendo/topics/editing_tempo_and_signature/editing_tempo_and_signature_c.html?contentId=sBTN1Gq7uKzN8r6htftCRA)を参考にしています。既存の編集があれば通常の保存確認を行います。初回保存は保存先を選ぶOS標準ダイアログを開き、保存成功後に履歴と次回起動の復元対象へ登録します。保存前はディスクに作らず、再起動での復元対象にも登録しません。 - track list最終行の下の`+`(tooltip: `Add track`)、または`Ctrl+Shift+N`で末尾にtrackを追加します。noteのある既存trackが2つ以上の場合だけ、各trackの先頭tickにある非note eventの共通部分を、新しいtrackのtick 0へ同じ順序・共通する重複数で継承します。Note On/OffとEnd of Trackは継承しません。初期eventsの後にnote number 60・velocity 100・四分音符のnoteを置き、追加trackを開いてそのtrackだけを先頭から自動演奏します。format 0への追加ではformat 1にします。追加はUndoの対象です。 - `Ctrl+O`でOS標準のファイル選択を開きます。現在のファイルのフォルダを初期表示し、SMF(`.mid`/`.midi`/`.smf`)を選べます。ファイル名入力・`Enter`で開き、`Esc`でキャンセルします。開くと演奏を停止し、キャンセル時も編集内容とカーソルは保持します。選択後はAuto save ONなら保存し、OFFなら通常の未保存確認を行い、読み込み成功後に`pa`相当の全track演奏を自動で始めます。 - `Ctrl+P`で最近開いたファイルを新しい順の1列一覧に表示します。先頭が`1`で初期カーソルも先頭です。`1-9a-zA-Z`で直接開き(小文字`j/k`の行は`Alt+j/Alt+k`)、`Enter`で選択を開きます。`j/k`・上下矢印は1行、PageUp/PageDownは10行移動し、移動先の曲の先頭1小節(全trackで最初にnoteがあるtickから1小節)を全trackでプレビュー演奏します。`Esc`で試聴を止めて編集へ戻り、未保存編集とカーソルは保持します。切替を確定したときはAuto save ONなら保存し、OFFなら通常の保存確認を行い、読み込み成功後に`pa`相当の全track演奏を自動で始めます。プレビュー音は一覧を開いている間だけ作り、閉じると作成を止めます。編集・演奏中には作りません。カーソルを合わせた曲を優先し、続けて履歴の新しい順に1件ずつ、ディスク上のSMFの先頭1小節をwavに書き出します。読込と書き出しはbackgroundで行いますが、音源の生成はUI threadで行うため、入力が750ms止まってから始め、その間は一覧の操作が一時止まります。まだwavの無い曲にカーソルを合わせた場合は、書き出し後に演奏します。wavは`%LOCALAPPDATA%\cat-smf-editor\cache\recent-preview\`にSMFのSHA-256をファイル名として保存し、内容が同じSMFでは作り直しません。自動削除はしません。一覧に「準備中…/準備済み/準備失敗」を表示し、失敗したファイルは更新されるまで再試行しません。音源をメモリに保持しないため、確定後の演奏開始では音源の生成を待ちます。各行はキー、最後に開いてからの経過時間、filename、曲名(先頭track名)、演奏時間、track数、fullpathです。経過時間は`1m/1h/1d/1w/1mon/1y`形式で、単位ごとにMonokaiのピンク・橙・黄・緑・青・紫にします。一覧は内容に合わせて自動サイズにし、画面に収まらない場合だけスクロールします。履歴は`%LOCALAPPDATA%\cat-smf-editor\recent-files.json`に保存し、次回起動でも復元します。プレビューは履歴順や日時を更新しません。導入前に開いたファイルの履歴は含みません。 - `Ctrl+O`・`Ctrl+P`で選んだ曲やdropした曲を開く間は、画面左上に曲名・spinner・track別の準備状況を重ねます。`Queued`・`Restoring sound…`・`Loading instrument…`・`Ready`などを英語で表示し、処理中のtrackを橙色、準備済みを緑色にします。master effectの音源準備は別の行に表示します。背景の画面を描画しながらtrackごとに準備を進め、曲の編集や別ファイルのopenは準備完了まで受け付けません。プラグイン1インスタンスの初期化中はspinnerも一時停止する場合があります。読込・音色復元の失敗時は元の曲と編集内容を保持し、エラーを表示します。`Ctrl+O`・`Ctrl+P`では音声の開始まで表示を維持し、dropでは従来どおり自動演奏しません。 - `Ctrl+Z`または編集menuの`eu`で、音符・track追加/初期化/削除・event範囲削除・MML/コード挿入・トリル・テンポカーブ・目安BPM、音色・instrument layer・track/master effect・track音量の編集を最大100回戻せます。フェーダーを含むドラッグは1回の変更として扱います。ピアノロール/テンポカーブ・layer画面・ミキサー内でも`Ctrl+Z`を使えます。文字入力中や確認画面、音色/effect browserでは曲のundoを実行しません。undoでは演奏を停止し、戻したSMFから音色・effect・音量の再生用cacheを再構築します。再構築に失敗した場合は曲・再生・履歴を保持します。音色変更で履歴は消えません。redoと履歴の永続化はなく、ファイルの読込成功時と新規SMF作成時に履歴をリセットします。 - Auto saveはファイルごとに既定OFFで、`Ctrl+, → s`または設定overlayの「このファイルのAuto save」で切り替えます。ONにするときは現在の編集内容も含めた保存を確認し、`y`でバックアップ付き保存に成功してからONを確定します。`n`/`Esc`は有効化を取り消し、OFFのまま編集内容を保持します。有効化の保存失敗時もOFFのまま、確認画面から再試行・取消できます。設定変更はSMFの編集として扱います。OFFは直ちに自動保存を止め、OFFの永続化には`Ctrl+S`で手動保存が必要です。設定は先頭trackのtick 0の専用metaへ保存し、OFFではそのmetaを除去します。移動・改名後や次回起動も同じSMFから復元します。ONのファイルでは最初の未保存変更から60秒後に確認なしでバックアップ付き保存し、追加編集で期限を延ばしません。文字入力・ドラッグ・保存確認・ファイル選択やbrowserの操作中は終了まで延期します。ONでは`Ctrl+S`・アプリ終了・ファイル切替時に60秒を待たず確認なしで保存し、終了・切替は保存成功後に進めます。保存失敗時は編集内容を保持してエラーを表示し、定期保存の自動再試行を止めます。終了・切替時の保存失敗は、その操作を止めて`y`で再試行・`n`で破棄して終了/切替・`Esc`で編集へ戻ることができます。`Ctrl+S`の保存失敗は再試行か編集へ戻る操作を選べます。保存に成功すると定期保存を再開します。OFFでは`Ctrl+S`のたびに「y: 上書き保存する」「n / esc: 保存せず編集を続ける」を確認し、編集内容は保存するまでメモリ内に保持します。OFFで未保存編集がある場合は、終了・ファイル切替時に`y`で保存して進む・`n`で破棄して進む・`Esc`で編集を続けることを確認します。保存に失敗した場合は編集内容と確認画面を保持します。 - 内容変更を上書きする直前に、元の内容を`%LOCALAPPDATA%\cat-smf-editor\backup\`へバックアップします。`foo.mid`ならローカル時刻で`foo_yyyyMMddHHmmss.mid`、同名があれば`.2.mid`、`.3.mid`と連番にします。変更がなく保存不要な場合は作りません。バックアップ失敗時や読み込み後に外部変更された場合は上書きを止めます。世代数制限や自動削除は行わず、整理・復元はuserが行います。音源stateの保存先は従来どおりです。 保存確認ダイアログにはローカル日付で1日1回、バックアップのTIPSと保存先のフルパスを表示します。リンクのクリックまたは`O`でOS標準のopen動作により保存先を開きます。表示日は再起動後も保持します。 - `Ctrl+,`または右上の`☰`でタイトル`help`の設定overlayを開き、`Esc`で閉じます。表示・音色変更対象・このファイルのAuto save・ずんだもん演奏連動の設定を行います。 - ノート行の選択で試聴し、`p` から範囲を選んで再生します。overlayは開始位置を横軸、終了位置を縦軸とするグループで、右ほど開始が早く、下ほど終了が遅くなります。全track対象だけボタンに色を付け、`pa`(全trackを先頭から末尾まで)は右下に置きます。起動時は前回のファイルを開いたあと自動で`pa`相当の再生を始めます。ほかのボタンは現在trackが対象ですが、現在trackにNote Onが一つもない場合は、開始・終了の範囲を保って全trackを対象にします(`pe`もカーソルと同じtickの全trackのノートが対象)。この場合は全ボタンに色を付けます。該当する操作のない枠は空欄です。`pc` は全trackを現在小節から末尾まで、`ps` は現在小節から対象trackの末尾まで、`Space` は最後に使った方法で再生(A-Bリピートの操作では記憶した方法を変更しません)、`pi`は現在の拍だけを再生します。`Shift+Space` は演奏停止です。`pd`(演奏overlay内の `d`/Stopボタン)でも停止し、演奏overlayを閉じます。停止は準備中の再生とA-Bリピートも解除し、event listの表示を編集カーソルの位置へ戻します。`Esc` はoverlayを閉じる操作で、演奏を止めません。`F` はfollow、`M` はmixerです。再生と各trackの音量・muteはeditor自身が扱います。 - `i`でMML/コード進行の入力overlayを開きます。`o5 l8 cde`や`C F G`を入力すると、cat-plugin-playerと同じくカーソル位置の音符・和音を現在trackの音色で試聴します。chord進行を入力すると、挿入位置で有効な調号の主音名を先頭へ補います(E majorで`I`なら`Key:E I`、C# minorなら`Key:C# Aeolian I`)。明示した`Key:`は保持し、調号がない場合とMML入力には補いません。左右キーで試聴対象を移動し、`Enter`直後に`Preparing playback, please wait...`とspinnerのoverlayを表示し、演奏開始まで維持します。確定すると現在tickを基準にnote eventsを挿入し、末尾の休符を含むMMLの終了位置まで全trackで1回演奏します。同時にMMLの長さだけカーソルを進めます(例: 4/4で`c1`なら次の小節頭)。`Esc`で入力中の変更を破棄し、曲とカーソルを編集前へ戻します。Undoは確定時だけ1回分を記録します。入力中は開いた時点の挿入先trackとtickを固定します。A-B repeat演奏中に開くと、その範囲と全trackの演奏を維持し、入力変更を現在の演奏tickから反映します(反映時に音声を再開するため短い途切れが生じる場合があります)。この場合はカーソル単位の試聴と確定後の1回演奏を行わず、Enterで確定後も、Escで曲とカーソルを戻した後もrepeatを続けます。入力中もShift+Spaceで停止でき、停止後は入力変更・確定・キャンセルで演奏を再開しません。それ以外の演奏は開いたときに停止します。生成SMFの分解能を曲へ換算し、note on/offだけを追加します。入力のtempo・音色・CC指定は曲へ取り込みません。`;`による複数channelも検証用に現trackの同一channelへ集めます。コマンドパレットの`MML / コード進行: 1小節を上書き`は同じoverlayを、カーソルのある小節の先頭を挿入先として開き、その小節を全trackでA-B repeat演奏します。入力は小節の先頭から現在trackの既存noteを休符の範囲も含めて上書きします(前から鳴り続けるnoteは入力の先頭で終わらせます)。`VOICEVOX: 1小節の歌詞を差し替え`は、既存noteの歌詞だけを1音1モーラで差し替えます。1小節の歌詞入力は、IMEの変換を確定するEnterでは確定しません。歌詞の確定で入力が終わるときは、その小節のA-B repeatを続けたままカーソルが次の小節の先頭へ移ります。VOICEVOXの歌声trackの`VOICEVOX: 1小節のMMLと歌詞を同時に差し替え`は1つの入力欄で、`o5 l2 c d どん`または`どん o5 l2 c d`の順序を自動判別します。MML側は音名・音価・休符・octave・和音などのMML表記を使い、歌詞との境界にはspaceを置けます。両方ともMMLとして読めるなど判別できない入力は確定しません。入力中はその小節をA-B repeatし、noteと歌詞をまとめてプレビューします。1小節を超えるMMLは反映しません。Enterでまとめて確定し、repeatを保ったままカーソルを次小節へ移します。IME変換のEnterは確定に使わず、Escで両方を戻します。Undoはまとめて1回です。channelの決定と制限は[ADR 0010](/cat-smf-editor/docs/adr/0010-mml-chord-note-insertion.html)を参照してください。入力本文は実行中だけ保持し、挿入したnoteは通常のSMF保存・Auto save・Undoの対象です。 - Notes表示でノート行のMBT欄をクリックすると入力欄になり、`M:B:T`を入れて`Enter`でそのノートの開始だけを移します。`Esc`か欄の外のクリックで取り消します。Note Offと他のイベントのtickは変えず、変わるのは移したノートの長さと前後のdeltaだけです。移した先のtickに既存のイベントがあれば、その後ろに置きます。自分のNote Off以降への移動と、同じchannel・音高の別ノートとの前後が入れ替わる移動(別ノートの長さが変わる)は、エラーを出して変更しません。 - Notes表示でノート行のDuration欄をクリックすると入力欄になり、tick数を入れて`Enter`でそのノートのNote Offだけを移して長さを変えます。Note Onと他のイベントのtickは変えません。移した先のtickに既存のイベントがあれば、その後ろに置き、End of Trackより後ろへ伸ばすとEnd of Trackも同じtickへ動かします。0 tickと、同じchannel・音高の別ノートとNote Offの前後が入れ替わる長さ(別ノートの長さが変わる)は、エラーを出して変更しません。 - event list(Notes/Raw)の`s`で範囲選択を開始し、`hjkl`・矢印・PageUp/PageDown・Home/Endなど通常の移動キーで伸縮します。現在行を含み、開始行より上へ移動した場合は開始行を除きます。もう一度`s`で範囲menuを開き、`a`でA-B repeat、`d`でDelete eventsを実行します。track全体の選択時は`i`のInit track(他の全trackの先頭tickに共通する非note eventだけをtick 0へ継承し、それ以外は消去。eventのstatus・meta type・data全体のバイナリ一致で比較し、共通する重複数を保持)と`t`のDelete trackも表示します。最後の1 trackは削除できません。Notesの削除は選択ノートのNote Offも含み、Rawは選択eventだけを削除します。End of Trackは再補完し、残るeventのtickは動かしません。編集はUndoの対象です。menuの`Esc`で範囲選択に戻り、選択中の`Esc`で解除します。選択範囲は保存しません。 - `e`で編集overlayを開き、`em`でカーソル位置のノートのMBT欄、`ed`でDuration欄を、クリックしたときと同じ入力欄にします。カーソルがノート行に無いときは何もしません。 - `r`でピアノロールoverlay(SMF format 1のconductor trackでは次項のテンポカーブoverlay)を開き、`r`/`Esc`で閉じます。既定ではアプリ内いっぱいに最大化します。`Ctrl+, → r`または設定overlayの`Piano roll always maximized`で切り替え、tempo curveの`Ctrl+, → m`とは独立して`status.json`へ保存・復元します。OFFでは移動・サイズ変更できます。開いたまま`p`で再生menu、`Space`で前回の再生、`Shift+Space`/`pd`で停止できます。再生menuの`Esc`はmenuだけを閉じ、`r`/`Esc`でピアノロールを閉じても演奏は続きます。演奏位置を橙色の縦線で示し、`F`で横方向中央への追従を切り替えます(曲の先頭・末尾付近を除く)。followは通常画面・tempo curveと共有します。`F1`/`?`でピアノロール専用ヘルプを開き、`F1`/`?`/`Esc`でヘルプだけを閉じます。現在trackのノートはNote OnからNote Offまでを矩形で描き、色はtempo curveと同じ12色です(各ノート位置の調号が基準、調号なしはC major基準)。ノートのあるtrackでは、他trackのノートを現trackの音高表示範囲内だけ背景にグレーで重ねます。音高範囲は広げず、グレーのノートは編集対象にしません。minimapにも同じ背景ノートを表示します。縦は半音1行(trackの最低音〜最高音の上下に2半音の余白)、横は初期倍率で四分音符96pxで描きます。各枠の左に音高行と揃えた鍵盤を固定表示し、左クリックで押している間、左ドラッグで鍵を移りながら、曲内での使用有無によらずすべての鍵を現在の音色で試奏します(velocity 80)。鳴らしている鍵は既存の12色で示します。鍵盤の外、ボタンを離したとき、画面を閉じたとき、フォーカスを失ったときは消音します。試奏中も曲の再生位置とA-Bリピートを保ち、曲のノートやカーソル位置は変えません。`w`で2 trackを選んでいる場合は、上下半分ずつに各trackを表示します。Note OnからNote Offまであるノートの最低・最高note numberの中央が高いtrackを上にし、同じ範囲中央なら`w`の左右順、ノートのないtrackは下に置きます。各trackの音高範囲をそれぞれの枠に収め、音高zoom・縦scrollは両枠で同じ倍率・移動率を共有します。時間軸・横scroll・minimap・A-B repeatも共通で、ノート編集は操作した枠のtrackへ反映します。同じtrackを2枠に選んでも両方を表示します。背景には拍ごとの縦線(拍の4色、小節頭は太線)と、ト音記号(E4 G4 B4 D5 F5)・ヘ音記号(G2 B2 D3 F3 A3)の五線のうち表示範囲に入る線を白で描きます。開いたときは初期倍率でカーソル位置の小節を左端にします(再生中でfollowがONなら演奏位置への追従を優先します)。音符表示の左クリックは、停止中ならその拍の先頭へカーソルを移し、p menuで最後に選んだ終了範囲(拍末・小節末・track末)まで全trackを試聴します(`pi`が拍末、`pm`が小節末、`pb`・`pp`などがtrack末、note end系は拍末として扱います)。演奏中ならクリックしたtickから再開し、再生対象と終了範囲の系統を保ちます。`w`の2枠ではクリックしたtrackを操作対象にし、選択済みの2 trackは保ちます。空白から始めた左ドラッグは、選んだ時間範囲が表示幅の90%になるよう拡大します。ノート上からの左ドラッグはノート編集です。右クリック/右ドラッグは、押し始めた位置に近い表示時間範囲の端を調整し、反対側の端を保って範囲を90%へ拡大します。範囲操作はドラッグ中に色で示し、離したときに反映してfollowを解除します。上の`zoom`は時間軸、左の`zoom`は音高軸を、左クリックでクリック位置を中心に3/2倍に拡大、右クリックで2/3倍に縮小します。zoomバーの左ドラッグは、選択範囲が表示範囲の90%になるよう拡大します。右・下のスクロールバーで音高・時間の表示範囲を移動し、両端の矢印で0.5画面分移動します。zoomバー上のホイールはその軸のzoom、スクロールバー上ではその軸のscrollになり、バー以外のホイールは、直前の操作によらず時間軸scrollになります。倍率とスクロールは画面を閉じるまで保持します。上部のminimapには表示対象trackのノート、実際のtempo event(水色)、テンポカーブ(緑)、目安テンポ(順位が初期値と一致する線はピンク、不一致は橙色の破線)と現在の時間範囲を表示します。演奏中はminimapにも橙色の現在位置線を表示し、followがOFFでも更新します。時間軸は他trackの末尾やテンポ情報の範囲も含み、zoom・scrollから独立して全体を示します。SMF format 1ではconductor、それ以外は現在trackのtempo eventを使います。ピアノロール側の表示では目安テンポを新規作成しません。左クリックでその時刻を中央へ移し、演奏中ならそのtickから再開します。左ドラッグは倍率を保って表示枠を移動します。表示枠内ではつかんだ位置を保ち、枠外ではポインタを表示枠の中央にして移動します。ドラッグでは演奏位置とA-B repeatを変えません。minimap操作は通常画面と共有するfollowを解除します。A-B repeatの範囲内への演奏位置変更はBまで再生して次の周回へ進み、範囲外への変更はrepeatを解除します。A-B repeatバーの左ドラッグで指定した時間範囲を全trackで繰り返し再生し、右クリック/右ドラッグで近い端を動かします。右ドラッグ中の再演奏は250ms間隔とし、範囲表示は即時更新、離した位置は必ず反映します。バーの左クリックでリピートを解除して現在の再生位置から通常再生を続けます。範囲はtempo curve画面と共有し、SMFや設定には保存しません。別の再生方法を選ぶとリピートも解除します。minimapとrepeatバーは縦scrollしても上部に残ります。Note Offの無いノートは描きません。ノートの左端・中央・右端(幅を三等分)にポインタを乗せると、その部分が紫・黄・ピンクと黒い枠で0.5秒周期で点滅します。そこからドラッグすると、左端はNote Onのtick、中央はノート全体の位置(長さは保つ)、右端は長さを変え、離したときに1回だけ反映します(グリッドへのスナップはありません)。同じ音高の別ノートをまたぐなど反映できない変更は取り消され、エラーを赤字で出します。 - SMF format 1のconductor track(先頭trackかつnoteがないtrack)では、`r`でピアノロールの代わりにテンポカーブoverlayを開きます。既定ではアプリ内いっぱいに常時最大化します。`Ctrl+, → m`または設定overlayの`Tempo curve always maximized`でON/OFFを切り替え、`status.json`へ保存して次回起動で復元します。OFFでは移動・サイズ変更できます。テンポカーブ表示中も`Ctrl+,`で設定overlayを開けます。`r`/`Esc`で閉じます。開いたまま`p`で演奏overlayを開いて範囲を選び、`Space`で最後の方法を繰り返せます。`Shift+Space`/`pd`で演奏だけを停止し、テンポカーブは開いたままにします。`r`/`Esc`でテンポカーブを閉じても演奏は続きます。演奏位置は橙色の縦線で表示します。`f`で演奏位置への追従を切り替え、ONの間は演奏位置を横方向の中央に保ちます(曲の先頭・末尾付近を除く)。追従設定は通常画面と共有します。上部には常に`A-B repeat`と表示します。その行を左ドラッグすると、その範囲の全trackを繰り返し再生します(スナップなし)。右クリック・右ドラッグで近い方の端をその位置へ動かします。右ドラッグ中の再演奏は250ms間隔とし、範囲表示は即時更新、離した位置は必ず反映します。左クリックするとリピートを解除し、その位置から通常再生を続けます。別の再生方法を選ぶとリピートも解除します。範囲はSMFや設定には保存しません。演奏overlayの`Esc`は演奏overlayだけを閉じ、`c`は再生範囲の選択として扱います。ピアノロールの上には曲全体のノートに、実際のtempo event(水色)・テンポカーブ(緑)・リファレンスtempo(本体と同じピンク/橙色の破線)を重ね、現在の表示範囲も示すminimapを表示します。演奏中はminimapにも橙色の現在位置線を表示し、followがOFFでも更新します。minimapの左クリックでその時刻を中央に移し、演奏中ならそのtickから再開します。左ドラッグは倍率を保って表示枠を移動します。表示枠内ではつかんだ位置を保ち、枠外ではポインタを表示枠の中央にして移動します。ドラッグでは演奏位置とA-B repeatを変えません。minimapでクリック・ドラッグすると再生位置への追従を解除します。演奏位置をA-B repeat内へ移すと範囲を保ち、範囲外へ移すとrepeatを解除します。上半分は全trackのノートを鍵盤と同じ12色(調号なしはC major基準)とグレーの五線で描くピアノロール、下半分はテンポカーブです。先頭trackにnoteがある場合は、通常のピアノロールを開きます。上半分の音符表示を左クリックすると、停止中は拍の先頭から、p menuで最後に選んだ拍末・小節末・track末まで全trackを試聴します。演奏中はクリックしたtickから、その終了範囲の系統を保って再開します。続けて`pp`(Current MBT to end)でその位置から末尾まで再生できます。左ドラッグで選んだ時間範囲が表示幅の90%になるよう拡大します。上半分の右クリック・右ドラッグは表示中の時間範囲の近い端をその位置へ動かし、反対側の端を保って同様に90%へ拡大します。右ドラッグ中は調整範囲を色で示し、離したときに反映します。下半分にポインタがある間、全trackのNote On/Note Offのうちポインタの時刻を左右から挟む最も近い位置に縦線を表示します。Note Onは拍の色を明るさ55%にした破線、Note Offはグレーの実線です。同じ時刻に両方ある場合はNote Onを優先し、片側にイベントがない場合は存在する側だけを表示します。横軸と横スクロールを共有し、音高の縦配置とBPM軸の範囲・拡大縮小は独立しています。下半分の縦軸は目安テンポも含む曲のmin BPM〜max BPM(一定テンポの場合だけ前後1 BPM)、横軸はピアノロールと同じtickです。スクロールバーは右と下だけに置き、右はBPMの表示範囲、下は時間範囲を移動します。横・縦スクロールバーの両端の矢印ボタンは、それぞれの軸の表示範囲0.5画面分を移動します(端では移動できる範囲まで)。上の`zoom`はクリックした時刻を中心に時間軸を、左の`zoom`はクリックしたBPMを中心にBPM軸を、左クリックで3/2倍に拡大、右クリックで2/3倍に縮小します。zoomゾーンを左ドラッグすると、選んだ時間範囲(上)またはBPM範囲(左)が表示範囲の90%になるよう、範囲の中央を中心に拡大します。ドラッグ中は選択範囲を色で示し、離したときに反映します。zoomバー上のホイールはその軸のzoom、スクロールバー上のホイールはその軸のscrollとして動きます。バー以外のホイールは、直前の操作によらず時間軸scrollになります。`F1`/`?`でキーの色と余白で操作を区切った簡潔なヘルプを表示し、`F1`/`?`/`Esc`でヘルプだけを閉じます。緑の線がカーブ、水色の階段線と点がconductorのtempo eventで、カーブが無い曲でも既存のtempo eventを水色で表示します。初回表示では既存tempo eventの各位置から表示用の目安テンポを仮生成し、次の目安位置までの水平な破線とBPM値で表示します(先頭にtempoがなければtick 0に既定の120 BPMも作ります)。目安線は左ドラッグの上下でBPMだけを調整し、離したときに保存します。実際のカーブ・演奏テンポと目安位置は変わりません。線とカーブの点が重なる場所では点のドラッグを優先します。初期BPMの速い順の順位も記録し、同じBPMは同順位、順位は1・2・3のように欠番なしとします。現在の目安同士の順位が初期順位と同じ線はピンク、違う線は橙色で、ドラッグ中も色を更新し、順位を戻せば元の色に戻ります。開閉・スクロール・ズームだけではMIDIもUndo履歴も変えず、別のMIDIへ切り替える際の保存確認も出ません。カーブ・目安BPMの変更、またはtrillの変更を確定すると、必要な初期化もその編集とまとめてUndo 1回分にします。各目安と初期順位はconductorのText meta(例: `Reference Tempo: 120 BPM; rank=2`)へ保存し、再表示・再読込では作り直しません。カーブを全削除しても目安は残します。黄の円がテンポポイント、紫の正方形がコントロールポイント(区間ごとに1個の2次ベジェの制御点)です。両種類の点をそのまま左ドラッグでき、近接時はポインタに最も近い点を選びます(完全に重なる場合はテンポポイント)。点の無い場所の左クリックでテンポポイントを追加し、左ドラッグでは追加したポイントをそのまま移動します。円の右クリックで削除します。テンポポイントを隣のポイントにぶつけ、移動できない方向へ500ms押し込み続けると、ボタンを離す前にドラッグ中のポイントを削除します。内側へ戻したり、押し込む方向を変えたりすると500msを数え直します。追加・削除で変わった区間のコントロールポイントは区間の中点(直線)に置き直します。点をドラッグすると上下でBPM、左右でtickを変え、ドラッグ中は書かれるtempo eventを水色でプレビューし、通常の移動は離したときに1回だけ反映します(スナップはありません)。テンポポイントは隣のテンポポイントを越えず、コントロールポイントはその区間の外へ出ません。カーブがある間は、全trackのNote On・Note Offがあるtickとtick 0に、カーブのBPMのtempo eventを書き(直前と同じ値は省きます)、conductorの既存のtempo eventはすべて置き換えます。ピアノロールなど他の編集でノートが動いても、tempo eventを作り直して追従します。カーブはconductorの専用metaへ保存し、再読込で復元します。最後の1点を消すとカーブのmetaだけを除去し、その時点のtempo eventは残します。理由と保存形式は[ADR 0005](/cat-smf-editor/docs/adr/0005-tempo-curve-in-conductor-track.html)に記録しています。 - テンポカーブを開いたとき、未登録の曲では全trackからtrillを自動検知して仮表示します。カーブ・目安BPM・trillの実編集時に、ノートのあるtrackへ英語のText meta `Trill Start: {...}`/`Trill End: {...}`を記録します。半音または全音の交互反復が6音以上、64分音符以下の等しいtick間隔で、各Note Offが次の発音位置と一致するものが対象です。開始metaに識別子・channel・2音のnote numberと、検知時の実際のtempo eventで最初の発音間隔を秒へ変換した浮動小数点値を記録します。登録済みなら再表示・テンポ変更後も速度を取り直しません。テンポカーブの曲中にある`Trill Start`/`Trill End`の表示text、またはevent list(Notes/Raw)のtrill metaをクリックすると、そのtrillの編集画面を開きます。`First pitch`の`Upper`/`Lower`で開始音を選び、`First note`で最初の1音の長さ、`Interval`で2音目以降の発音間隔を、秒で個別に入力・ドラッグ変更します。入力・ドラッグのたびにmetaとノート配置を更新し、演奏・A-B repeatも現在の演奏tickから新しい配置で続けます。`Apply`で確定して閉じ、初期化を含めてUndo 1回分にします。値を変えずに`Apply`しても編集扱いになりません。`Cancel`/`Esc`/外側クリックでは初期化・変更・Undo履歴を残さず編集前へ戻します。最初の長さは同じ開始metaの`first_note_seconds`へ保存し、省略時は通常の間隔を使います。実編集と値の変更時に、開始・終了tickを保って、その秒間隔になるようノート数と位置を作り直します。カーブの変更にも追従し、最後の音は終了tickで切ります。ノート位置は整数tickに丸めるため、実際の間隔にはtick精度の誤差があります。管理中のtrillノートの単独移動・長さ変更は拒否し、伴奏の通常編集は維持します。元の開始音と音高ごとの最初のvelocity・release velocityもmetaへ保存し、最初の音を長くして1音だけになった後も復元できます。不正な間隔や同音の重なりはエラーにして変更を取り消します。詳細は[trillの管理と再配置](/cat-smf-editor/docs/trill.html)を参照してください。 - ピアノロールとtempo curveの各描画領域に、全trackのText meta(0x01、例: `Fermata`)をtick位置に表示します。常に読める本文で表示し、近接するラベルは縦にずらします。`Ctrl+, → a`(`All tracks meta text`)で全track分を一括表示/非表示にします(既定ON)。trillの本文は`Trill Start`/`Trill End`に短縮して表示し、クリックで編集します。ポインタを重ねると元の本文を表示します。表示/非表示の設定は`status.json`へ保存し、次回起動で復元します。 - `.`で直前の`em`・`ed`を、入力欄が出るところまでくり返します。入力欄の値は覚えず、その場所の値が入ります。 - mixerはtrackを横に並べ、各列にtrack名・音色名・縦フェーダー・dB値を表示します。音量は−36〜+6 dB、3 dB刻みで、0 dBが元の音量です。`m`で開いた直後はmaster effect欄を選択し、続けて`x`(`mx`)・`Enter`・`Space`でmaster effectのoverlayを開きます。`h/l`/左右キーでmaster/trackを選び、track選択中の`j/k`/上下キーで減音/増音し、マウスでも操作できます。`x`は選択対象のeffect overlay、`f`はSpectrum / Lissajous、`m`/`Esc`はmixerを閉じます。trackが多い場合は横スクロールできます。音量の変更は再生をやり直さず即座に反映され、SMF専用metaに保存して再読込で復元します。MIDI CC7は変更しません。 - mixerの`Master auto gain`で全track合成後の音量補正を切り替えます。起動時はonで、再生中も切り替えられます。RMS目標は−12 dBFS、補正範囲は−12〜+6 dBで、offは補正なしの音量です。音色・effectを変えても切り替え状態を保ちます。SMFや設定ファイルには保存しません。 - `Shift+t`で現在trackのinstrument layer overlayを開きます。track見出しの音色名クリックは、通常のtrackではinstrument layer overlay、歌声trackではそのtrackのキャラ・スタイル選択を開きます。見出しの音色ボタンは、歌声trackではキャラ名とスタイル名(例: `ずんだもん / ノーマル`)を表示し、WAVがない場合も代用音源のInit Sawは表示しません。通常のtrackでは全layerの音色名を区切り線でつなぎ、複数layerではlayerごとに色を変えます。trackのeffect名はどちらも従来どおり表示します。一覧は行数に合わせて画面内まで自動で広がり、スクロールバーは表示しません。画面を超える行数ではホイールと選択layerへの自動スクロールを使えます。1行1layerでpatchボタン、整数の`Octave`、`dB`を編集し、`j/k`/上下キーでlayer、`h/l`/左右キーでPatch・Octave・dBを選びます。選択項目は色で示し、`Enter`でpatch browserまたは数値入力を開きます。選択layerを`o/i`でoctave +1/−1、`]/[`で音量 +6/−6 dB、`m/s`でmute/solo切替できます(数値入力中・help表示中は無効)。Octave・dB欄の上でマウスホイールを回すと、その欄を選択して`o/i`・`]/[`と同じ量だけ増減します(数値入力中は無効)。行内の`M/S`でも切り替えられ、有効なボタンを色で示します。soloが0なら全layer、1つ以上ならsoloのlayerだけを鳴らし、追加soloも可能です。muteは常に複数を許可し、soloと重なった場合も消音します。mute/soloは同じtrack内だけに作用し、SMF保存・再読込とundoの対象です。数値欄はクリックでも入力でき、`Enter`で確定、入力中の`Esc`か欄外クリックで取り消します。`a`/`+`は選択layerを複製して末尾へ追加し(空一覧なら既定音色を追加)、`Delete`/行の`−`はlayerを削除します。browserから戻っても対象layerの選択を保ちます。`F1`/`?`で専用helpを開き、`Esc`でhelpだけを閉じます。入力中でないときの`Esc`/見出しの`×`で一覧を閉じます。最後のlayerも削除でき、そのtrackは無音になります。同じpatchを重ねられ、各layerのインスタンスと保持ノートは独立しています。範囲外の移調pitchは鳴らしません。layer gainを合算した後にtrack共通effectを1回適用します。実pluginでの発音・独立した停止、実画面での追加・交換・削除・数値編集と再起動復元を機械検証済みです。パイプオルガンでの音色の良否と操作感は人間による確認待ちです。 - trackごとのlayerとeffectを復元し、別trackの同pitchも独立した音源で鳴らします。未設定のtrackは従来の既定音色相当のSurge XTを使います。SMFのGM Program Changeを、GM音源としての自動切替やCCの音色選択への解釈は行いません。 - 音色 - `t`/Program Change行からcat-plugin-playerのpatch browser、effect overlayの`a`/`x`からeffect browserを開きます。最初の1回でplayerを起動して常駐させ、以降はbrowserを前面に出すだけです。patch/effectそれぞれの初回表示までは、画面中央に`now loading...` overlayを表示します。playerのmain画面は表示しません。browserで選んだ音色・effectはplayerでは鳴らさず、editorの音源へ反映します。演奏中はその再生位置から新しい設定で鳴らし直し、停止中は演奏を開始しません。`t`/Program Change行のpatch選択は対象trackの先頭layer、layer overlayのpatchボタンはその行だけを置き換えます。effectはoverlayの`x`では選択中のeffect(無ければ追加)を置き換え、`a`では末尾へ追加します。同じeffect pluginを別のeffect欄へ入れる選択は反映しません。patch browserの左上Role・左下Preset、effect browserの左上Category・左下Kindは、patchは曲・track・layerごと、track effectは曲・trackごと、master effectは曲ごとに独立して`status.json`へ保存し、開き直したときと次回起動で復元します。effectの欄どうしでは同じtrackの選択を共有します。一括patch選択では先頭の演奏trackの選択を使います。検索文字列と、その中に含まれるSolo/Mute・除外条件も同じ対象ごとに保存・復元します。音色を選ばず閉じた場合も絞り込みを記憶します。patch一覧の選択も曲・track・layerごとにpatch名と音源・元patchの識別情報で記憶し、並び順が変わっても同じpatchを選択して見える位置へ戻します。選択の復元では音色を再適用しません。削除済み・絞り込み対象外のpatchは未選択にします。削除されたRole/Preset・Category/KindはALLへ戻します。 - editorはtrackごとに使ったplugin chainをcacheし、同じ構成へ戻ると再利用します。別の音色ならstateを読み直します。patch/effect browserを開いている間は1分ごとに保持時間を更新し、閉じてから5分使わなければ非使用中のcacheを解放します。使用中の音源は残します。保持中はメモリが増え、初回と解放後は生成時間がかかります。曲切替時は前の曲の音源を破棄します。master設定変更、音声エラーなどの音源リセットでは必要な音源を準備し直します。詳細は[インスタンスcache](/cat-smf-editor/docs/plugin-instance-cache.html)を参照してください。 - `t`の対象は`Ctrl+, → t`の2択で決め、現在の選択を色で示します。`Ctrl+, → ta`(既定)はノートのあるtrackが複数あり、すべてのprogram名が同じ場合に確認なしで一括、それ以外は現在trackを対象にします。`Ctrl+, → tc`は常に現在trackだけです。選択は`%LOCALAPPDATA%\cat-smf-editor\status.json`へ保存し、次回起動で復元します。一括ではノートのある全trackの先頭layerのpatchだけを変更し、追加layer、各layerのoctave・dB、各trackのeffect・bypass・音量を保持します。空のlayer一覧には先頭layerを追加します。一括以外ではNote Onがないtrackの音色選択をエラーoverlayで止め、演奏trackを選ぶよう案内します。 - `Esc`、文字入力に使われない`q`、browserの×、effect browserを閉じるEnterはbrowserを隠すだけで、playerは終了しません。検索欄の`q`は文字入力です。editorを終了するとplayerも終了します。playerが途中で終了した場合はエラーを表示し、次の`t`/`x`で起動し直します。 - 選択はbrowserを開いたときの対象(現在track、一括ならノートのある全track、masterならconductor)へ反映します。browserを開いた後に別ファイルを開いた場合や、別のbrowserを開いた後、対象layerを削除した後、曲を読み直した後に届いた古いpatch選択は取り込みません。 - layerのpatch参照・octave・dB・mute・solo、順序付きtrack/master effectの参照とbypassをSMFの専用metaへ保存します。plugin format/IDと元patch位置・program/preset valueで復元し、state本体はSMFに入れません。旧state保存形式の移行は行わず、既知の旧metaや壊れた参照はエラーにします。外部sampleの複製やOS/plugin版をまたぐstate互換は保証しません。 - 使用したstateは曲やpatchを切り替えても保持し、終了時に`%LOCALAPPDATA%\cat-smf-editor\cache\patch-states-v1\`へ保存します。次回SMF復元では有効なcacheを先に使い、欠けたpatchだけをplayerの非表示生成経路で復元します。全cacheが有効ならplayer探索・起動・カタログ走査・生成は不要で、`--player`の有無にも依存しません。pluginと元patchの更新・破損はcache missとし、octave・dB・track番号はcache keyに含めません。layer間の音源インスタンスは共有しません。詳細と後段の汎用graph移行方針は[ADR 0006](/cat-smf-editor/docs/adr/0006-instrument-layers-and-patch-state-cache.html)を参照してください。 - Surge XTは演奏用instanceのpatch・FX preset・wavetable一覧走査を減らし、初期patchを保持して音色・wavetableを保存stateから復元します。browserとstate生成用playerには元の環境を渡します。`CMRT_SURGE_MINIMAL_DATA_HOME=0`で無効化できます。検証した音色・FXと適用範囲、計測結果は[ADR 0012](/cat-smf-editor/docs/adr/0012-surge-minimal-data-home.html)を参照してください。 - エラー調査 - 起動・読込・保存・音声・playerなどのエラーを`%LOCALAPPDATA%\cat-smf-editor\error.log`へ時刻付きで追記します。同じエラーが表示され続ける間は毎フレームの重複出力を抑えます。 - エフェクトルーティング - master effectはSMF format 1に対応し、conductor(先頭track)の専用metaへ保存・復元します。各trackのeffect・音量を適用して合成した後、master effect、Master auto gainの順に処理します。master effect browserで選んだeffectはmasterだけへ反映します。format 0/2のmaster対応は追加していません。理由と保存形式は[ADR 0004](/cat-smf-editor/docs/adr/0004-master-effects-in-conductor-track.html)に記録しています。 - track effect・master effectは専用overlayで編集します。overlayは信号の流れを縦に描きます(trackはinstrument layer → effect → mixer、masterはtrack群 → effect → Master auto gain → 出力)。effectの追加・差し替え(browser)、ドラッグまたはShift+j/kでの並べ替え、effectごとのbypass、削除ができます。bypassはeffectごとにSMFへ保存し、再生を止めずに切り替わります。入口はメイン画面とmixerの`x`、trackヘッダーとmixerのeffect名です。構成はeditor内の試聴・範囲再生・全track再生で使います。理由は[ADR 0007](/cat-smf-editor/docs/adr/0007-effect-chain-on-uapmd-graph.html)に記録しています。 # ローカルでのビルドと実行 editor、`cat-plugin-player`、`uapmd`、`clap-mml-render-tui`、`clap-mml-play-server`、`mascot-render-server`を同じ親ディレクトリに置きます。editorはplayerの共通host・初回導入・MML入力のソース、TUIの`chord`/`midi-filter`、play-serverの`core-lib`、mascot-render-serverのclient/protocolを参照します。MMLとchordの変換器はCargo.tomlのGit依存から取得します。playerをビルドする場合はplayer側READMEの依存checkoutも用意してください。 ```powershell cargo build --release --locked & ./target/release/cat-smf-editor.exe 'X:\music\song.mid' ``` playerを明示指定する場合は `& ./target/release/cat-smf-editor.exe --player 'X:\projects\cat-plugin-player\target\release\cat-plugin-player.exe'` と起動します。環境変数の設定は不要です。 cache missの復元要求とbrowser選択で使うplayerの探索順は`--player `、editorのexeと同じディレクトリ、兄弟repoの`cat-plugin-player/target/release/cat-plugin-player.exe`、`PATH`です。兄弟repoの探索はeditorのexeが`target/debug`または`target/release`にあるときに行い、作業ディレクトリには依存しません。指定したパスが不正なら別の場所へ黙って切り替えません。起動時に演奏の復元ができず、playerも未発見なら、[配布ZIP](https://github.com/cat2151/cat-plugin-player/releases/download/v0.1.0/cat-plugin-player-0.1.0-windows-x64.zip)を自動取得し、editorのexeと同じディレクトリへ配置します。取得したplayerの連携機能を配置前に確認し、未対応の古い配布版は配置せず更新が必要な旨を表示します。既存のplayerは上書きしません。playerのライセンス同意画面は出さず、著作権表示はWindowsのDesktop(OneDriveなどへの移動先も含む)内に`cat-smf-editor-licenses`フォルダを作り、その中へ`cat-plugin-player-LICENSE.txt`として保存します。同名で内容の異なるファイルがある場合は、内容を識別するsuffixを付けた別名で保全します。取得・書込に失敗した場合は再試行または手動ダウンロードを選べます。 起動時に演奏の復元ができず、音源も検出できなければ、cat-plugin-playerと共通の画面からSurge XTの利用規約を確認し、同意後にwingetでインストールできます。effectだけの場合も対象です。既存の音源があれば案内しません。保存された音色を復元して演奏できる場合は、playerの探索や音源一覧の走査を待ちません。復元できない場合も、playerの音源cacheに実在する音源が記録されていれば走査を省略します。導入後は再スキャンし、通常のMIDI復元・ファイル選択へ進みます。`あとで`/`Esc`で見送れます。案内を閉じても開始済みのインストールは続きます。Tab/Shift+Tabで項目移動、Enter/Spaceでボタンを選べます。失敗の詳細は画面と`error.log`へ出し、wingetがない場合は手動取得先を案内します。player選択のエラー画面の`Setup`からやり直すこともできます。ZIPの配置先には書込権限、Surge XTの導入にはWindowsの権限確認が必要な場合があります。構成は[ADR 0009](/cat-smf-editor/docs/adr/0009-first-run-dependencies.html)を参照してください。 各アプリは自分のbuildに対応するhost DLLをexeへ同梱します。editorのDLL展開先は`%LOCALAPPDATA%\cat-smf-editor\cache\native\`です。`cache/`配下は再生成可能なデータだけで、削除後は必要なものを再生成します。前回のMIDのpathを持つ`startup.json`と、操作位置・表示設定・browser選択を持つ`status.json`を分け、起動時の発音前は`startup.json`だけを読みます。`status.json`にも操作位置の対象曲を照合するpathを保持します。両方と`settings.toml`、履歴、ログ、MIDI保存時の`backup/`はcacheの外へ保持します。editorはインストール済みplayerのDLLを借りません。共通化と保存契約は[ADR 0003](/cat-smf-editor/docs/adr/0003-shared-host-player-selection.html)、配布の構成は[release workflow](/cat-smf-editor/docs/release-workflow.html)を参照してください。 ※↑AIはこのh1セクションのみに書いてください </details> # コンセプト、目指すもの - おもちゃ - エディタよりはおもちゃを目指します - このアプリの位置づけは [おもちゃ] >> 教育用 >> 商業用 くらいのイメージです - editできるのはごくわずかな要素だけです - 名前にeditorが入っていますが気にしない - 鳴ること - 「作者の環境で鳴ること」はできるだけ維持することを目指します - すぐ鳴ること - アプリ起動から音が鳴るまで1trackなら体感0.2秒。演奏までを最速にしています - GUI表示準備などの処理も、音の後にしています - GUI表示より先に音が鳴るのは、いわばスプラッシュスクリーンのサウンド版かもしれません - 自分が使うワークフローだけを実装する - 開発リソースがほぼゼロのため、トリアージです - この種のエディタの開発には膨大な開発コストが必須です - 例えば、アンドゥやタイムマシンや非破壊編集など、安全な編集とスタンダードなUXを両立するため、データモデル設計に運用設計に洗い出しに検証用実装とドッグフーディングなどをディレクションして機能を取捨選択(はスタンダードを目指すとできないので全部入りにするしかない)、などだけでも開発コストが膨大です - もし、よくありそうな「軽量でスタンダードなエディタ」をお探しなら、ほかをあたってください - 教育用から実験用へ - 商業用よりは、教育用の方向を向いています - が、このアプリは上記の制約のため、 - 教育用よりも、おもちゃ or 実験用 の方向を向いています - 実験、探索、自分用 - 頻繁に破壊的変更をします - 昨日saveしたファイルが今日loadできないのは日常茶飯時となります - なので利用はおもちゃレベルにとどめてください # 思ったことを雑に書くコーナー - SMFエディタは、いろいろな用途があり、考慮ポイントが多すぎ、「実用になるレベルを目指すと」開発コストが膨大すぎる - おもちゃ。一部だけ、がっつり編集したい。音色とエフェクト、テンポカーブ、アルペジオ、ピアノロールで各noteを微調整。素早く編集と検証のサイクルをまわすことを優先し、loadやsaveは手動操作なしの全自動 → 当アプリのターゲットとするワークフローが、そのごく一部 - サクサクとブラウズ演奏したい、サクサク中身を可視化したい。軽量のブラウザやビューア - ちょっと変更したい。変更部分以外は完全に元のままであることを担保、そのためのdiff可視化。軽量のエディタ - 作編曲の練習用おもちゃ - カジュアルな可視化、カジュアルな編集。混乱防止のため非破壊編集もあるとよいが開発コストは膨大になる - いや、SMFエディタじゃなく、スタンダードなモダンな他のアプリで作曲したほうがいいと思います - 本格的な作編曲 - 上に同じ - さらに、高度なアンドゥ、タイムマシン、非破壊編集などを極めて高水準に実現が必須 - 今後追記予定 # スコープ外、目指さないもの - DAW - SMFだけでなくDAW projectほか有名DAWのprojectを直接読み書きし、編集可能、もちろんAudioも - プラグイン - あらゆるエディタ機能を自由にプラグインで拡張 - script - あらゆるエディタ機能を自由にscriptで拡張 - スタンダード - 標準的なSMFエディタやDAWの見た目や挙動を200%網羅。すべてのエディタとDAWに対して完全上位互換 - 機能 - あらゆる機能を搭載。あらゆる用途で利用可 - 互換性 - データの完全互換 - あらゆるSMFをload可能、あらゆるDAWのprojectをimport可能 - exportはあらゆる音楽データ、あらゆるDAWのprojectに対応 - 設定の完全互換。あらゆる過去の設定をloadして動作する - 堅牢さ - 何をしても絶対にバグらない。アプリが落ちない - 利便性 - 便利さ、使いやすさを極限まで追求 - 性能 - あらゆる環境でCPU負荷なく高速に動作。音は絶対に途切れない - 要望 - ユーザーのあらゆる要望に即応 # ライセンス - MIT