diff --git a/examples/test/10key-dp.bms b/examples/test/10key-dp.bms new file mode 100644 index 00000000..04459aa8 --- /dev/null +++ b/examples/test/10key-dp.bms @@ -0,0 +1,61 @@ +*---------------------- METADATA FIELD + +#TITLE 10 KEY DP Lane Mode +#SUBTITLE IIDX 5-key double play - channels 11..16 and 21..26 +#ARTIST be-music +#GENRE TEST +#BPM 120 +#PLAYLEVEL 2 +#TOTAL 250 +#DIFFICULTY 2 + +*---------------------- EXTENDED HEADER FIELD +* The 2P-side, no-6/7 corner of the IIDX lane-mode table: five keys plus scratch +* on both sides, which must resolve to 10 KEY DP. +* +* This chart is also the counter-example for the PMS-STD content rule. That rule +* claims any chart touching `22..25` for 9 KEY, but only when the traditional +* IIDX 2P channels (`21` and `26..29`) are absent. A real 5-key DP chart authors +* `21` and `26` alongside `22..25`, so it has to stay 10 KEY DP. +* +* See 5key-sp.bms for the rest of the lane-mode fixture family. + +#PLAYER 2 +#LNTYPE 1 + +*---------------------- RESOURCES FIELD + +#WAV01 sample.wav +#WAV02 branch.wav + +*---------------------- MEASURE LENGTH FIELD + +*---------------------- OBJECT DATA FIELD + +* Measure 0 - one eighth note per lane, sweeping 1P left to right then 2P. +#00011:0100000000000000 +#00012:0001000000000000 +#00013:0000010000000000 +#00014:0000000100000000 +#00015:0000000001000000 +#00021:0000000000010000 +#00022:0000000000000100 +#00023:0000000000000001 + +* Measure 1 - scratch on both sides, keys alternating between the two players. +#00016:02000200 +#00026:00020002 +#00111:01000100 +#00115:01000100 +#00121:00010001 +#00125:00010001 + +* Measure 2 - the 2P keyboard columns 22..25 on their own. Without 21 / 26 in +* the chart this measure alone would look like PMS-STD, so it exists to keep the +* 10 KEY DP classification honest. +#00222:01010101 +#00223:01010101 +#00224:01010101 +#00225:01010101 + +*---------------------- CONTROL FLOW FIELD diff --git a/examples/test/5key-sp.bms b/examples/test/5key-sp.bms new file mode 100644 index 00000000..1bae7e35 --- /dev/null +++ b/examples/test/5key-sp.bms @@ -0,0 +1,59 @@ +*---------------------- METADATA FIELD + +#TITLE 5 KEY SP Lane Mode +#SUBTITLE IIDX 5-key single play - channels 11..16, no 18 / 19 +#ARTIST be-music +#GENRE TEST +#BPM 120 +#PLAYLEVEL 1 +#TOTAL 200 +#DIFFICULTY 1 + +*---------------------- EXTENDED HEADER FIELD +* Lane-mode detection falls through to the IIDX family when no POPN or keyboard +* marker matches, and then splits on two signals only: whether the chart uses +* the 2P side, and whether it uses the 6th / 7th columns (`18` / `19` / `28` / +* `29`). This chart is the 1P-side, no-6/7 corner of that table: five keys plus +* scratch, which must resolve to 5 KEY SP. +* +* Keeping it as `.bms` matters - the extension carries no lane information for +* this family, so the classification has to come from the channels alone. +* +* Companion fixtures for the rest of the family: +* 10key-dp.bms - 5 keys on both sides -> 10 KEY DP +* ln-mode-1-long-note.bms - 1P side with 18 / 19 -> 7 KEY SP +* lane-order-test.bms - both sides with 18 / 19 / 28 / 29 -> 14 KEY DP +* 9key-all-keys-quarter.pms - PMS-STD -> 9 KEY +* 24key-keyboard-sp.bme - extended 1A..1O columns -> 24 KEY SP +* 48key-keyboard-dp.bme - extended columns on both sides -> 48 KEY DP + +#PLAYER 1 +#LNTYPE 1 + +*---------------------- RESOURCES FIELD + +#WAV01 sample.wav +#WAV02 branch.wav + +*---------------------- MEASURE LENGTH FIELD + +*---------------------- OBJECT DATA FIELD + +* Measure 0 - one eighth note per lane, left to right, then scratch. +#00011:0100000000000000 +#00012:0001000000000000 +#00013:0000010000000000 +#00014:0000000100000000 +#00015:0000000001000000 +#00016:0000000000020000 + +* Measure 1 - all five keys as a chord on every quarter note, scratch on the +* backbeat. +#00111:01010101 +#00112:01010101 +#00113:01010101 +#00114:01010101 +#00115:01010101 +#00116:00020002 + +*---------------------- CONTROL FLOW FIELD diff --git a/examples/test/7key-longnote.bml b/examples/test/7key-longnote.bml new file mode 100644 index 00000000..a6377869 --- /dev/null +++ b/examples/test/7key-longnote.bml @@ -0,0 +1,62 @@ +*---------------------- METADATA FIELD + +#TITLE 7 KEY Long Note (BML) +#SUBTITLE The .bml extension - 7 keys plus scratch with #LNOBJ long notes +#ARTIST be-music +#GENRE TEST +#BPM 140 +#PLAYLEVEL 5 +#TOTAL 300 +#DIFFICULTY 3 + +*---------------------- EXTENDED HEADER FIELD +* `.bml` is the fourth chart extension the toolchain accepts, alongside `.bms`, +* `.bme` and `.pms`. It carries no parsing rule of its own - by convention it +* marks a 7-key chart that uses long notes - so it only shows up in the +* extension allow-lists (the player-tui chart picker, the player-web drop +* handler, the CLI usage line) and in lane-mode detection's "not .pms" path. +* +* Without a real `.bml` file in this directory those allow-list entries were +* only ever tested against synthetic paths, so this chart exists to be opened: +* it has to parse like any other BMS chart and classify as 7 KEY SP. + +#PLAYER 1 +#LNTYPE 1 +#LNMODE 1 +#LNOBJ ZZ + +*---------------------- RESOURCES FIELD + +#WAV01 sample.wav +#WAV02 branch.wav +#WAV03 right.wav +#WAVZZ sample.wav + +*---------------------- MEASURE LENGTH FIELD + +*---------------------- OBJECT DATA FIELD + +* Measure 0 - count-in on the seven keys, scratch on the backbeat. +#00011:01010101 +#00013:00020002 +#00015:02000200 +#00016:00030003 + +* Measure 1 - a 2-beat long note per key group, which is what the extension is +* conventionally used to advertise. +#00111:0100ZZ00 +#00113:0100ZZ00 +#00115:0100ZZ00 + +* Measure 2 - the 6th and 7th columns (18 / 19), which are what separate 7 KEY +* from 5 KEY in lane-mode detection. +#00218:010000ZZ +#00219:010000ZZ + +* Measure 3 - scratch plus a chord, no long notes. +#00311:01010101 +#00318:00020002 +#00319:02000200 +#00316:00030003 + +*---------------------- CONTROL FLOW FIELD diff --git a/examples/test/README.ja.md b/examples/test/README.ja.md new file mode 100644 index 00000000..ee45cf89 --- /dev/null +++ b/examples/test/README.ja.md @@ -0,0 +1,121 @@ +# テスト譜面フィクスチャ + +[English version](./README.md) + +be-music のテストスイートが共有する譜面・音声フィクスチャ置き場です。各譜面は「ひとつのまとまった機能群」を対象にし、 +かつ必ずどこかのテストから読まれます。どのテストからも読まれないフィクスチャは誰にも気づかれないまま古くなり、 +実際にこのディレクトリで見つかった不具合はすべてそれが原因でした。 + +コーパス全体の番人は [`packages/parser/src/fixtures.test.ts`](../../packages/parser/src/fixtures.test.ts) です。 +このディレクトリを走査してすべての譜面をディスクから読み、制御フロー解決後にプレイ可能なイベントが残ることを要求します。 +譜面を追加すれば自動的に対象に入り、壊せばこのテストが落ちます。 + +## 規約 + +- 譜面名は対象機能に合わせた kebab-case にする。 +- 拡張子は意図して選ぶ。`.bms` / `.bme` / `.bml` / `.pms` はレーンモード判定に効くため、拡張子自体がフィクスチャの + 検証対象の一部になる。 +- 既存譜面と同じ `*---------------------- ... FIELD` のセクション見出しで始め、`*` コメントブロックに + 「何のための譜面か」「変えると何が壊れるか」を書く。 +- `#WAV` などで参照する音声は、このディレクトリに実在するファイルだけにする。そうすれば全譜面が手動プレイでも鳴る。 + +## 機能別の譜面 + +### ヘッダ・命令カバレッジ + +| ファイル | 対象 | +| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | +| `four-measure-command-combo-test.bms` | パーサが振り分ける拡張ヘッダとオブジェクトチャネルを網羅。コマンド群ごとに 4 小節ブロック。検証しているのは振り分けとラウンドトリップ保持で、ペイロードの妥当性ではない。 | +| `extended-directives.bms` | 同じ命令群を `@be-music/chart` の値パーサが受け付けるペイロードで記述。`#EXWAV` の `pvf`、`#EXBMP` の ARGB タプル、`#ARGB` の 16 進と 10 進、`#BGA` 部分矩形、`#SWBGA` アニメーション、`#WAVCMD` の pitch/volume/loop、チャネル `A0` からの `#EXRANK`、チャネル `A6` からの `#CHANGEOPTION`、`#STP`。 | +| `base62-ids.bms` | `#BASE 62` — 大文字・小文字・混在の ID を別スロットとして扱う。インデックス付きヘッダ、チャネルストリーム、`#LNOBJ`、`#RANDOM` / `#IF` ブロック内のすべてで検証。 | +| `sjis-encoding-test.bms` | Shift_JIS の自動判定。パース結果の IR は `sjis-encoding-test.json` に固定してある。 | +| `benchmark-command-mix-100.bms` | 混在コマンド 100 小節でのパーサスループット。`pnpm bench` は独自のインライン譜面を使うため、こちらには繋がっていない。 | + +### タイミング・描画ギミック + +| ファイル | 対象 | +| -------------------------- | -------------------------------------------------------------------------------------------------------------------------- | +| `scroll-speed-gimmick.bms` | ギミック 1 種につき 1 小節。`#xxx02` 小節長、`#xxx03` 16 進 BPM、`#xxx08` `#BPMxx` 参照、`#xxx09` STOP、`#xxxSC` `#SCROLLxx`(`0` と負値を含む)、`#xxxSP` `#SPEEDxx`、最後に全部を同一小節に。 | +| `measure-length.bms` | 通常小節に挟まれた 1 小節だけの短縮。 | +| `bus-volume-channels.bms` | チャネル `97`(BGM バス)と `98`(キー音バス)の動的音量。両バスが同一拍で動くケースも含む。 | +| `nonpositive-bpm.bms` | チャネル `08` が 0 のスロット・負のスロット・未定義スロットを指すケース。タイムラインが捨てざるを得ないテンポ点と、それでも譜面が成立し続けることを検証。 | + +### ロングノート + +| ファイル | 対象 | +| -------------------------------- | -------------------------------------------------------------------------------- | +| `ln-mode-1-long-note.bms` | `#LNMODE 1`(LN)を `#LNOBJ` の始点/終点ペアで。7 KEY SP のレーンフィクスチャ兼用。 | +| `ln-mode-2-charge-note.bms` | `#LNMODE 2`(CN)— 譜面データは同一、モードのみ差分。 | +| `ln-mode-3-hell-charge-note.bms` | `#LNMODE 3`(HCN)— 譜面データは同一、モードのみ差分。 | +| `lntype2-long-note.bms` | `#LNTYPE 2` の連続記法。1 小節内の 1 連、空きスロットで分かれた 2 連、小節境界をまたぐ 1 連。 | +| `ln-9key-popn.bms` | `#PLAYER 3` で POPN 9 レーン全部にロングノート。 | + +### レーンモード + +`resolveChartPlayVariant` の分岐ごとに 1 譜面。 + +| ファイル | レーンモード | +| --------------------------- | ----------------------------------- | +| `5key-sp.bms` | 5 KEY SP | +| `ln-mode-1-long-note.bms` | 7 KEY SP | +| `9key-all-keys-quarter.pms` | 9 KEY(PMS-STD) | +| `ln-9key-popn.bms` | 9 KEY(`#PLAYER 3` + チャネル `17`) | +| `10key-dp.bms` | 10 KEY DP | +| `lane-order-test.bms` | 14 KEY DP — レーン順序の譜面も兼ねる。両サイドの全クラシックカラムを使用。 | +| `24key-keyboard-sp.bme` | 24 KEY SP — 拡張 `1A..1O` カラム | +| `48key-keyboard-dp.bme` | 48 KEY DP — 両サイドの拡張カラム | +| `7key-longnote.bml` | 7 KEY SP — `.bml` 拡張子。独自のパース規則は持たないが、譜面ファイルの許可リストにはすべて載っている。 | + +### レーンとハザード + +| ファイル | 対象 | +| --------------------- | --------------------------------------------------------------------------------------------------------------- | +| `invisible-notes.bms` | 不可視キー音チャネル `3x` / `4x` — 鳴るが描画も判定もされない。かつ 2P 側の `4x` があっても 1 人プレイ譜面が DP 扱いになってはいけない。 | + +### 制御フロー + +| ファイル | 対象 | +| ------------------------------ | ---------------------------------------------------------------------------------------------------------- | +| `control-flow-random-demo.bms` | `#RANDOM` / `#IF` / `#ELSE`(メタデータ上書きあり)と `#SWITCH` / `#CASE` / `#DEF` を 2 ブロック。全オブジェクトが分岐内にあるため、制御フローを解決するまで譜面は空。 | + +### bmson + +| ファイル | 対象 | +| ----------------------------------- | --------------------------------------------------------------------------------------------- | +| `bmson-strict-features.bmson` | `info` ブロック一式、`bga` のヘッダとイベント、`lines`、`notes[].l` / `.c`。 | +| `bmson-lines-resolution-test.bmson` | 不均等な `lines` と、解像度に依存する `stop_events.duration` の換算。 | +| `bmson-key-channels-mines.bmson` | beatoraja 拡張。`mode_hint` のレーンマップ経由で `Dx` / `Ex` に載る `key_channels` 地雷、`info.ln_type`、`notes[].t`。 | + +### フォーマット間ラウンドトリップ + +次の 5 ファイルは組でしか意味を持たず、 +[`packages/editor/src/index.test.ts`](../../packages/editor/src/index.test.ts) が実パイプラインと突き合わせています。 + +| ファイル | 役割 | +| ------------------------ | ------------------------------------------ | +| `sample.bms` | 元譜面。 | +| `sample.json` | `importChart` の出力。 | +| `sample.roundtrip.bmson` | 同じ譜面を bmson へエクスポートしたもの。 | +| `sample.edit.json` | タイトル変更 1 回とノート追加 1 回を適用後。 | +| `sample.edited.bms` | その編集結果を `exportChart` で書き戻したもの。 | + +手書きで直さず、必ずエディタ API 経由で再生成してください。それが整合性を保つ唯一の方法です。 + +### オーディオ再生 + +| ファイル | 対象 | +| ------------------------------------- | ------------------------------------------------------------------------------- | +| `retrigger-same-key-cut.bms` | BMS のモノフォニック再生。同一レーンの 2 発目が 1 発目を切る。 | +| `retrigger-different-key-overlap.bms` | 別レーンなら、両スロットが同一ファイルを指していても切らない。 | +| `ogg-test.bms` | `#WAV` が wav 以外のコーデックを指す譜面。ローダが Vorbis デコーダまで到達する必要がある。 | + +## 音声アセット + +| ファイル | 用途 | +| ------------------------------------------ | --------------------------------------------------------------------- | +| `sample.wav` | ほとんどの譜面の既定キー音。audio-renderer の基準サンプルでもある。 | +| `branch.wav`, `right.wav`, `wrong.wav` | 副次的なキー音。主に制御フローの分岐を耳で聞き分けるため。 | +| `retrigger_a.wav`, `retrigger_b.wav` | リトリガー譜面が重なりを作るために必要な 2.2 秒サンプル。 | +| `ogg-test.ogg` | `ogg-test.bms` が宣言する Vorbis サンプル。 | +| `ogg-test.wav` | `ogg-test.ogg` の非圧縮元データ。素材として残しているだけで、テストは読んでいない。 | +| `render-codec-test.mp3` / `.ogg` / `.opus` | audio-renderer のコーデック別デコードケースと、`.wav` 不在時のフォールバックケース。 | diff --git a/examples/test/README.md b/examples/test/README.md new file mode 100644 index 00000000..640e054d --- /dev/null +++ b/examples/test/README.md @@ -0,0 +1,121 @@ +# Test Chart Fixtures + +[日本語版はこちら](./README.ja.md) + +Shared chart and audio fixtures for the be-music test suite. Every chart here targets one coherent feature cluster, and +every chart is read by at least one test — a fixture no test reads goes stale without anyone noticing, which is how the +problems fixed in this directory got in. + +The corpus-level guard lives in [`packages/parser/src/fixtures.test.ts`](../../packages/parser/src/fixtures.test.ts). It +scans this directory, parses every chart off disk, and requires each one to yield playable events after control-flow +resolution. Add a chart here and it is picked up automatically; break one and that test fails. + +## Conventions + +- Name a chart after the feature it exercises, in kebab-case. +- Pick the extension deliberately. `.bms` / `.bme` / `.bml` / `.pms` feed lane-mode detection, so the extension is part + of what a fixture asserts. +- Open with the `*---------------------- ... FIELD` section banners the existing charts use, and explain in a `*` + comment block what the chart is for and which behaviour would break if it changed. +- Reference only audio files that already exist in this directory, so every chart is actually playable by hand. + +## Charts by feature + +### Header and directive coverage + +| File | Covers | +| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `four-measure-command-combo-test.bms` | Every extension header and object channel the parser routes, one 4-measure block per command group. Proves routing and roundtrip preservation, not payload validity. | +| `extended-directives.bms` | The same directive family with payloads the `@be-music/chart` value parsers accept: `#EXWAV` `pvf`, `#EXBMP` ARGB tuple, `#ARGB` hex and decimal, `#BGA` sub-region, `#SWBGA` animation, `#WAVCMD` pitch/volume/loop, `#EXRANK` on channel `A0`, `#CHANGEOPTION` on channel `A6`, `#STP`. | +| `base62-ids.bms` | `#BASE 62` — upper, lower and mixed case object IDs as distinct slots, in indexed headers, channel streams, `#LNOBJ`, and inside a `#RANDOM` / `#IF` block. | +| `sjis-encoding-test.bms` | Shift_JIS auto-detection. Its parsed IR is pinned in `sjis-encoding-test.json`. | +| `benchmark-command-mix-100.bms` | Parser throughput over 100 measures with a mixed command load. Not wired to `pnpm bench`, which uses its own inline chart. | + +### Timing and drawing gimmicks + +| File | Covers | +| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `scroll-speed-gimmick.bms` | One measure per gimmick: `#xxx02` measure length, `#xxx03` hex BPM, `#xxx08` `#BPMxx` reference, `#xxx09` STOP, `#xxxSC` `#SCROLLxx` (including `0` and negative), `#xxxSP` `#SPEEDxx`, then all of them in one measure. | +| `measure-length.bms` | A single shortened measure surrounded by normal ones. | +| `bus-volume-channels.bms` | Channels `97` (BGM bus) and `98` (key bus) dynamic volume, including both buses moving on the same beat. | +| `nonpositive-bpm.bms` | Channel `08` pointed at a zero slot, a negative slot, and an undefined slot — the tempo points the timeline has to drop while still leaving a playable chart. | + +### Long notes + +| File | Covers | +| --------------------------------- | ------------------------------------------------------------------------------- | +| `ln-mode-1-long-note.bms` | `#LNMODE 1` (LN) with `#LNOBJ` head/tail pairs. Also the 7 KEY SP lane fixture. | +| `ln-mode-2-charge-note.bms` | `#LNMODE 2` (CN) — same chart data, different mode. | +| `ln-mode-3-hell-charge-note.bms` | `#LNMODE 3` (HCN) — same chart data, different mode. | +| `lntype2-long-note.bms` | `#LNTYPE 2` continuous runs: one run in a measure, two runs split by a gap, and a run crossing a measure boundary. | +| `ln-9key-popn.bms` | Long notes on all nine POPN lanes with `#PLAYER 3`. | + +### Lane modes + +One fixture per branch of `resolveChartPlayVariant`. + +| File | Lane mode | +| ----------------------------- | ----------- | +| `5key-sp.bms` | 5 KEY SP | +| `ln-mode-1-long-note.bms` | 7 KEY SP | +| `9key-all-keys-quarter.pms` | 9 KEY (PMS-STD) | +| `ln-9key-popn.bms` | 9 KEY (`#PLAYER 3` + channel `17`) | +| `10key-dp.bms` | 10 KEY DP | +| `lane-order-test.bms` | 14 KEY DP — also the lane-ordering chart, every classic column on both sides | +| `24key-keyboard-sp.bme` | 24 KEY SP — extended `1A..1O` columns | +| `48key-keyboard-dp.bme` | 48 KEY DP — extended columns on both sides | +| `7key-longnote.bml` | 7 KEY SP — the `.bml` extension, which carries no parsing rule of its own but is on every chart-file allow-list | + +### Lanes and hazards + +| File | Covers | +| ----------------------- | ------------------------------------------------------------------------------------------------------------- | +| `invisible-notes.bms` | Invisible keysound channels `3x` / `4x` — they sound but are neither drawn nor judged, and the 2P-side `4x` channels must not turn a single-player chart into a DP chart. | + +### Control flow + +| File | Covers | +| -------------------------------- | ------------------------------------------------------------------------------------------------------- | +| `control-flow-random-demo.bms` | `#RANDOM` / `#IF` / `#ELSE` with a metadata override, plus two `#SWITCH` / `#CASE` / `#DEF` blocks. Every object lives inside a branch, so the chart is empty until control flow is resolved. | + +### bmson + +| File | Covers | +| ----------------------------------- | ------------------------------------------------------------------------------------------------- | +| `bmson-strict-features.bmson` | The full `info` block, `bga` headers and events, `lines`, and `notes[].l` / `.c`. | +| `bmson-lines-resolution-test.bmson` | Non-uniform `lines` and the resolution-dependent conversion of `stop_events.duration`. | +| `bmson-key-channels-mines.bmson` | beatoraja extensions: `key_channels` mines routed through the `mode_hint` lane map onto `Dx` / `Ex`, `info.ln_type`, and `notes[].t`. | + +### Format round trips + +These five files only mean anything as a set, and +[`packages/editor/src/index.test.ts`](../../packages/editor/src/index.test.ts) checks them against the live pipeline: + +| File | Role | +| ------------------------ | ------------------------------------------------------- | +| `sample.bms` | The source chart. | +| `sample.json` | What `importChart` produces from it. | +| `sample.roundtrip.bmson` | The same chart exported to bmson. | +| `sample.edit.json` | The chart after one retitle and one added note. | +| `sample.edited.bms` | What `exportChart` writes back out from that edit. | + +Regenerate them through the editor API rather than by hand — that is what keeps them honest. + +### Audio playback + +| File | Covers | +| --------------------------------------- | --------------------------------------------------------------------------------------------- | +| `retrigger-same-key-cut.bms` | BMS monophonic playback: a second trigger on the same lane cuts the first voice. | +| `retrigger-different-key-overlap.bms` | A different lane does not cut, even when both slots point at the same file. | +| `ogg-test.bms` | A chart whose `#WAV` names a non-wav codec, so the loader has to reach the Vorbis decoder. | + +## Audio assets + +| File | Used by | +| ---------------------------------------------------------- | -------------------------------------------------------------------------------- | +| `sample.wav` | The default keysound for most charts, and the audio-renderer's reference sample. | +| `branch.wav`, `right.wav`, `wrong.wav` | Secondary keysounds, mostly for telling control-flow branches apart by ear. | +| `retrigger_a.wav`, `retrigger_b.wav` | The 2.2 s samples the retrigger charts need in order to overlap at all. | +| `ogg-test.ogg` | The Vorbis sample `ogg-test.bms` declares. | +| `ogg-test.wav` | The uncompressed source for `ogg-test.ogg`. Kept as source material; no test reads it. | +| `render-codec-test.mp3` / `.ogg` / `.opus` | The audio-renderer's per-codec decode cases, and its missing-`.wav` fallback case. | diff --git a/examples/test/base62-ids.bms b/examples/test/base62-ids.bms new file mode 100644 index 00000000..6cbfd882 --- /dev/null +++ b/examples/test/base62-ids.bms @@ -0,0 +1,67 @@ +*---------------------- METADATA FIELD + +#BASE 62 + +#TITLE Base 62 Object IDs +#SUBTITLE #BASE 62 keeps upper and lower case as separate slots +#ARTIST be-music +#GENRE TEST +#BPM 120 +#PLAYLEVEL 1 +#TOTAL 200 +#DIFFICULTY 1 + +*---------------------- EXTENDED HEADER FIELD +* `#BASE 62` is the beatoraja extension that widens the two-character object ID +* space from base 36 to base 62 by making lower case letters distinct slots. +* Under the default base 36 every pair below would collapse onto one key, so +* this chart is the file-level regression guard for the case-preserving path: +* +* #WAV0a / #WAV0A - distinct sample slots +* #00111:0a0A0z - distinct channel-stream tokens +* #LNOBJ zz - LN end marker matched case-sensitively +* +* `#BASE` must appear before the first object line to take effect, so it is +* declared at the very top of the file. + +#PLAYER 1 +#LNTYPE 1 +#LNMODE 1 +#LNOBJ zz + +*---------------------- RESOURCES FIELD + +#WAV0a sample.wav +#WAV0A branch.wav +#WAV0z right.wav +#WAV0Z wrong.wav +#WAVZz sample.wav +#WAVzz sample.wav + +*---------------------- MEASURE LENGTH FIELD + +*---------------------- OBJECT DATA FIELD + +* Measure 0 - four case-distinct slots in one channel stream. +#00011:0a0A0z0Z + +* Measure 1 - the same four slots on a playable lane. +#00111:0a0A0z0Z + +* Measure 2 - a long note whose end marker is the lower case `zz`. Under base 36 +* this would fold to `ZZ` and stop matching the #LNOBJ declaration. +#00211:0a00zz00 + +* Measure 4 - lower case, upper case and mixed case IDs in one channel stream. +#00411:0a0AZz + +*---------------------- CONTROL FLOW FIELD + +* An indexed header declared inside a control-flow branch still has to register +* under its lower case key. +#RANDOM 1 +#IF 1 +#WAV0b wrong.wav +#00311:0b0b +#ENDIF +#ENDRANDOM diff --git a/examples/test/benchmark-command-mix-100.bms b/examples/test/benchmark-command-mix-100.bms index 22ab10b6..45ae60ea 100644 --- a/examples/test/benchmark-command-mix-100.bms +++ b/examples/test/benchmark-command-mix-100.bms @@ -61,7 +61,6 @@ *---------------------- CONTROL FLOW FIELD #SETRANDOM 2 -#RANDOM 2 #IF 1 #01011:0505 #01016:05 @@ -71,7 +70,6 @@ #ENDIF #ENDRANDOM #SETSWITCH 3 -#SWITCH 3 #CASE 1 #02011:01010101 #SKIP @@ -83,7 +81,6 @@ #SKIP #ENDSW #SETRANDOM 3 -#RANDOM 3 #IF 1 #03004:01 #ELSEIF 2 diff --git a/examples/test/bmson-key-channels-mines.bmson b/examples/test/bmson-key-channels-mines.bmson new file mode 100644 index 00000000..144eb968 --- /dev/null +++ b/examples/test/bmson-key-channels-mines.bmson @@ -0,0 +1,50 @@ +{ + "version": "1.0.0", + "info": { + "title": "BMSON Key Channels Mines", + "subtitle": "beatoraja key_channels / ln_type / notes[].t extensions", + "artist": "be-music", + "genre": "TEST", + "level": 4, + "init_bpm": 150, + "resolution": 240, + "mode_hint": "beat-7k", + "ln_type": 2, + "judge_rank": 100, + "total": 260 + }, + "lines": [{ "y": 0 }, { "y": 960 }, { "y": 1920 }], + "bpm_events": [], + "stop_events": [], + "sound_channels": [ + { + "name": "sample.wav", + "notes": [ + { "x": 1, "y": 0, "l": 0, "c": false }, + { "x": 2, "y": 240, "l": 0, "c": false }, + { "x": 1, "y": 480, "l": 480, "c": false, "t": 3 }, + { "x": 6, "y": 960, "l": 240, "c": false, "t": 1 }, + { "x": 7, "y": 1200, "l": 0, "c": false }, + { "x": 8, "y": 1440, "l": 0, "c": false } + ] + }, + { + "name": "branch.wav", + "notes": [ + { "y": 0, "l": 0, "c": false }, + { "y": 960, "l": 0, "c": false }, + { "y": 1920, "l": 0, "c": false } + ] + } + ], + "key_channels": [ + { + "name": "wrong.wav", + "notes": [ + { "x": 1, "y": 1680, "damage": 0 }, + { "x": 6, "y": 1800, "damage": 50 }, + { "x": 8, "y": 1920, "damage": 100 } + ] + } + ] +} diff --git a/examples/test/bus-volume-channels.bms b/examples/test/bus-volume-channels.bms new file mode 100644 index 00000000..88bf2294 --- /dev/null +++ b/examples/test/bus-volume-channels.bms @@ -0,0 +1,63 @@ +*---------------------- METADATA FIELD + +#TITLE Dynamic Bus Volume Channels +#SUBTITLE Channel 97 (BGM bus) and channel 98 (key bus) +#ARTIST be-music +#GENRE TEST +#BPM 120 +#PLAYLEVEL 1 +#TOTAL 200 +#DIFFICULTY 1 + +*---------------------- EXTENDED HEADER FIELD +* Channels `97` and `98` are the two dynamic volume buses: +* +* #xxx97 - BGM-side (autoplay / channel 01) bus volume +* #xxx98 - playable-side (key sound) bus volume +* +* The token is a base-36 pair read as a 0..FF ratio of the original volume, so +* `FF` is unity, `80` is roughly half, and `01` is the quietest audible step. +* `00` is "no event" rather than silence, so it is never authored as a value. +* +* Both channels must stay out of the sample-trigger path - authoring a volume +* change must not itself make a sound - which is what makes a real chart worth +* having here rather than only the classifier unit tests. + +#PLAYER 1 +#LNTYPE 1 +#VOLWAV 100 + +*---------------------- RESOURCES FIELD + +#WAV01 sample.wav +#WAV02 branch.wav + +*---------------------- MEASURE LENGTH FIELD + +*---------------------- OBJECT DATA FIELD + +* Measure 0 - reference bar. BGM on channel 01, key sounds on channel 11, both +* at the volume the chart declares. +#00001:02020202 +#00011:01010101 + +* Measure 1 - duck the BGM bus to half and then to the quietest step while the +* key bus stays untouched. +#00197:8001 +#00101:02020202 +#00111:01010101 + +* Measure 2 - restore the BGM bus and duck the key bus instead. +#00297:FF00 +#00298:8040 +#00201:02020202 +#00211:01010101 + +* Measure 3 - both buses move on the same beat, which is where an ordering bug +* between the two gain stages shows up. +#00397:40FF +#00398:FF40 +#00301:02020202 +#00311:01010101 + +*---------------------- CONTROL FLOW FIELD diff --git a/examples/test/extended-directives.bms b/examples/test/extended-directives.bms new file mode 100644 index 00000000..8d02deac --- /dev/null +++ b/examples/test/extended-directives.bms @@ -0,0 +1,108 @@ +*---------------------- METADATA FIELD + +#TITLE Extended Directive Payloads +#SUBTITLE Structurally valid #EXWAV / #EXBMP / #ARGB / #BGA / #SWBGA / #WAVCMD / #EXRANK payloads +#ARTIST be-music +#GENRE TEST +#BPM 120 +#PLAYLEVEL 1 +#TOTAL 200 +#DIFFICULTY 1 + +*---------------------- EXTENDED HEADER FIELD +* `four-measure-command-combo-test.bms` proves the parser ROUTES every extended +* header into the right `bms` field, but its payloads are placeholders +* (`#EXWAV01 ex_sample.wav`, `#BGA01 01`, `#SWBGA01 02`, `#WAVCMD legacy`) that +* every `@be-music/chart` value parser rejects. This chart carries the same +* directive family with payloads that actually parse, so the value parsers are +* exercised against a real file instead of inline strings only. +* +* Payload layouts (hitkey BMS Memo): +* #EXWAVxx flags drawn from `pvf`, params positional +* #EXBMPxx a,r,g,b,filename ARGB tuple plus the image filename +* #ARGBxx AARRGGBB | a,r,g,b both accepted spellings +* #BGAxx YY x1 y1 x2 y2 dx dy sub-region crop of #BMPYY +* #SWBGAxx fr:tot:lp[:ARGB] N1 N2 ... switching (animated) BGA, fr in 1/100 s +* #WAVCMD pp xx vv pp = 00 pitch / 01 volume / 02 loop +* #EXRANKxx judge-window scale, cued on channel A0 +* #CHANGEOPTIONxx