From 4fd8ece170ac02edd1ea9b5552fbd230f0187738 Mon Sep 17 00:00:00 2001 From: Masahiko AMANO Date: Wed, 20 May 2026 00:29:52 +0300 Subject: [PATCH] refactor: replace fixed STYLE_user with open-ended style tag system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - STYLE_user renamed to STYLE_H1K0 in VOCAB (author's personal tag) - Style field now accepts any [A-Za-z][A-Za-z0-9_]* identifier in .chord files - Unknown styles fall back to STYLE_other at tokenization time with a log warning - Test fixtures updated to style: other; drop closed _VALID_STYLES frozenset - Spec bumped to v2.1: documents open style field, fallback behaviour, and §5.7 guide on registering a new style token Co-Authored-By: Claude Sonnet 4.6 --- docs/chord_format_spec.md | 59 +++++++++++++++-------- src/tokenizer.py | 19 +++++--- tests/fixtures/invalid_bar_count.chord | 2 +- tests/fixtures/invalid_chord_symbol.chord | 2 +- tests/fixtures/midi_export_test.chord | 2 +- tests/fixtures/valid_b_minor.chord | 2 +- tests/fixtures/valid_c_major.chord | 2 +- tests/fixtures/valid_fsharp_major.chord | 2 +- tests/fixtures/valid_gsharp_minor.chord | 2 +- tests/test_chord_file_parser.py | 2 +- tests/test_dataset.py | 2 +- tests/test_tokenizer.py | 2 +- 12 files changed, 60 insertions(+), 38 deletions(-) diff --git a/docs/chord_format_spec.md b/docs/chord_format_spec.md index 41d43ab..98e3ff1 100644 --- a/docs/chord_format_spec.md +++ b/docs/chord_format_spec.md @@ -1,7 +1,7 @@ # Спецификация формата данных hamori -**Версия:** 2.0 -**Дата:** 2026-05-16 +**Версия:** 2.1 +**Дата:** 2026-05-20 --- @@ -18,7 +18,7 @@ Формат двухуровневый: - **Исходный (`.chord`)** — то, что пишется руками. Близок к лид-шиту, человекочитаем, легко правится в любом текстовом редакторе. -- **Токенизированный** — то, что подаётся в модель. Факторизованное представление с маленьким словарём (~75 токенов). +- **Токенизированный** — то, что подаётся в модель. Факторизованное представление с фиксированным словарём (81 токен). Между уровнями стоит детерминированный парсер. @@ -33,7 +33,7 @@ # key: D_major # time: 4/4 # subdivision: 4 -# style: user +# style: H1K0 # function: chorus | Gmaj7 . . . | A . . . | F#m7 . . . | Bm7 . . . | @@ -53,14 +53,14 @@ ### 3.3 Поля шапки -| Поле | Обязательно | Допустимые значения | Назначение | -| ------------- | ----------- | -------------------------------------------------------------------------------- | -------------------------------------------- | -| `title` | да | свободная строка | идентификация периода | -| `key` | да | `_major` или `_minor` | для нормализации в C/Am перед обучением | -| `time` | да | `4/4`, `3/4`, `6/8`, `2/4`, `12/8` | тактовый размер | -| `subdivision` | да | `4` или `8` | сколько позиций в одном такте | -| `style` | да | `user`, `jpop`, `classical`, `jazz`, `other` | стилевой тег периода | -| `function` | нет | `verse`, `prechorus`, `chorus`, `bridge`, `intro`, `outro`, `interlude`, `other` | функциональная роль периода в исходной пьесе | +| Поле | Обязательно | Допустимые значения | Назначение | +| ------------- | ----------- | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | +| `title` | да | свободная строка | идентификация периода | +| `key` | да | `_major` или `_minor` | для нормализации в C/Am перед обучением | +| `time` | да | `4/4`, `3/4`, `6/8`, `2/4`, `12/8` | тактовый размер | +| `subdivision` | да | `4` или `8` | сколько позиций в одном такте | +| `style` | да | любой идентификатор `[A-Za-z][A-Za-z0-9_]*` (например: `H1K0`, `jpop`, `other`) | стилевой тег периода; при токенизации тег должен совпасть с токеном `STYLE_` в словаре, иначе используется `STYLE_other` | +| `function` | нет | `verse`, `prechorus`, `chorus`, `bridge`, `intro`, `outro`, `interlude`, `other` | функциональная роль периода в исходной пьесе | **Допустимые ноты для `key`:** `C, C#, D, D#, E, F, F#, G, G#, A, A#, B`. Бемольные написания (`Db`, `Eb`, ...) принимаются и нормализуются к диезной форме. @@ -110,10 +110,10 @@ Примеры: - `C` → root=C, quality=maj (по умолчанию), без extension, bass=root -- `Am7` → root=A, quality=min7, без extension, bass=root +- `Am7` → root=A, quality=m7, без extension, bass=root - `Fmaj9` → root=F, quality=maj7, extension=9, bass=root - `G7/B` → root=G, quality=7, без extension, bass=B -- `Dm9/F` → root=D, quality=min7, extension=9, bass=F +- `Dm9/F` → root=D, quality=m7, extension=9, bass=F ### 4.2 Корневой тон @@ -228,7 +228,7 @@ D/F# ← D, бас F♯ - `MODE_major`, `MODE_minor` — 2 токена (наследие тональности; нужны, потому что мажор и минор остаются разделёнными) - `TIME_4/4`, `TIME_3/4`, `TIME_6/8`, `TIME_2/4`, `TIME_12/8` — 5 токенов - `SUB_4`, `SUB_8` — 2 токена -- `STYLE_user`, `STYLE_jpop`, `STYLE_classical`, `STYLE_jazz`, `STYLE_other` — 5 токенов +- `STYLE_H1K0`, `STYLE_jpop`, `STYLE_classical`, `STYLE_jazz`, `STYLE_other` — 5 токенов стиля (текущий словарь); неизвестный тег → `STYLE_other` - `FUNC_verse`, `FUNC_prechorus`, `FUNC_chorus`, `FUNC_bridge`, `FUNC_intro`, `FUNC_outro`, `FUNC_interlude`, `FUNC_other`, `FUNC_unspecified` — 9 токенов **Аккордовые слоты (новый аккорд = ровно 4 токена в порядке root, quality, extension, bass):** @@ -274,7 +274,7 @@ BAR 1. Прочитать шапку. 2. Транспонировать все аккорды: если `key = X_major`, транспонировать так, чтобы X стало C; если `key = X_minor` — так, чтобы X стало A. 3. Выпустить ``. -4. Выпустить метатокены: `MODE_`, `TIME_`, `SUB_`, `STYLE_`, `FUNC_` (если `function` не задан — выпустить `FUNC_unspecified`). +4. Выпустить метатокены: `MODE_`, `TIME_`, `SUB_`, `STYLE_`, `FUNC_` (если `function` не задан — выпустить `FUNC_unspecified`; если `STYLE_