From 9929209bcf25c12ab1330e131e1c834a6fc1834a Mon Sep 17 00:00:00 2001 From: Masahiko AMANO Date: Tue, 19 May 2026 10:41:57 +0300 Subject: [PATCH] docs: update chord format spec to v2.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Revise and expand the authoritative .chord format specification: version bump 1.0 → 2.0, clarified period scope, updated tokenization rules, grammar tables, and key normalization details. Co-Authored-By: Claude Sonnet 4.6 --- docs/chord_format_spec.md | 559 ++++++++++++++++++++++---------------- 1 file changed, 319 insertions(+), 240 deletions(-) diff --git a/docs/chord_format_spec.md b/docs/chord_format_spec.md index 29a1a44..ab3fec4 100644 --- a/docs/chord_format_spec.md +++ b/docs/chord_format_spec.md @@ -2,401 +2,480 @@ ## Проект: генератор аккордовых последовательностей -**Версия:** 1.0 -**Дата:** 2026-05-03 +**Версия:** 2.0 +**Дата:** 2026-05-16 --- -## 1. Архитектура формата +## 1. Что описывает этот документ + +Формат хранения и кодирования гармонических периодов для обучения генеративной модели и для практического использования модели как творческого помощника. + +Один файл в этом формате описывает **один гармонический период** (4–16 тактов) — замкнутую гармоническую фразу. + +--- + +## 2. Архитектура формата Формат двухуровневый: -- **Источник** — то, что ты пишешь руками. Близок к лид-шиту, человекочитаем, легко правится. -- **Токены** — то, что видит модель. Факторизованное представление с маленьким словарём. +- **Исходный (`.chord`)** — то, что пишется руками. Близок к лид-шиту, человекочитаем, легко правится в любом текстовом редакторе. +- **Токенизированный** — то, что подаётся в модель. Факторизованное представление с маленьким словарём (~75 токенов). -Между уровнями стоит парсер. Источник → токены — детерминированное преобразование. +Между уровнями стоит детерминированный парсер. --- -## 2. Исходный формат +## 3. Исходный формат `.chord` -### 2.1 Структура файла - -Один файл — одна пьеса. Расширение `.chord`. Кодировка UTF-8. +### 3.1 Пример ``` -# title: Sea Glass +# title: Sea Glass - chorus # key: D_major # time: 4/4 # subdivision: 4 # style: user -# tempo_bucket: medium +# function: chorus -[intro] -| D . . . | A/C# . . . | Bm7 . . . | A . . . | - -[verse] -| D . . . | F#m7 . . . | G . . . | A . . . | -| Bm7 . . . | F#m7 . . . | G . . . | Asus4 . A . | - -[chorus] -| Gmaj7 . . . | A . . . | F#m7 . . . | Bm7 . . . | -| Gmaj7 . . . | A . . . | D . . . | D . . . | +| Gmaj7 . . . | A . . . | F#m7 . . . | Bm7 . . . | +| Gmaj7 . . . | A . . . | D . . . | D . . . | ``` -### 2.2 Шапка (метаданные) +### 3.2 Структура файла -Любая строка, начинающаяся с `#`, — метаданные. Формат: `# key: value`. +Один файл — один период. Расширение `.chord`. Кодировка UTF-8. -| Поле | Обязательно | Допустимые значения | Пример | -| -------------- | ----------- | ------------------------------------------------------------------------------------------- | ----------- | -| `title` | да | свободная строка | `Sea Glass` | -| `key` | да | `_major` или `_minor`, где `` — `C, C#, D, D#, E, F, F#, G, G#, A, A#, B` | `D_major` | -| `time` | да | `4/4`, `3/4`, `6/8`, `2/4`, `12/8` | `4/4` | -| `subdivision` | да | `4` (четвертные) или `8` (восьмые) | `4` | -| `style` | да | `user`, `jpop`, `classical`, `jazz`, `other` | `user` | -| `tempo_bucket` | нет | `slow`, `medium`, `fast`, `very_fast` | `medium` | +Состоит из двух частей: -`subdivision` определяет, сколько позиций в одном такте. В `4/4` при `subdivision: 4` — 4 позиции на такт; при `subdivision: 8` — 8 позиций. +1. **Шапка** — строки, начинающиеся с `#`, в любом порядке. +2. **Тело** — последовательность тактов, каждый обрамлён `|`. -### 2.3 Структурные теги секций +Пустые строки игнорируются. Комментарии (`// ...`) игнорируются парсером. -В квадратных скобках на отдельной строке. Действуют до следующего тега. +### 3.3 Поля шапки -| Тег | Назначение | -| ------------- | ---------- | -| `[intro]` | вступление | -| `[verse]` | куплет | -| `[prechorus]` | предприпев | -| `[chorus]` | припев | -| `[bridge]` | бридж | -| `[interlude]` | проигрыш | -| `[solo]` | соло | -| `[outro]` | концовка | +| Поле | Обязательно | Допустимые значения | Назначение | +| ------------- | ----------- | -------------------------------------------------------------------------------- | -------------------------------------------- | +| `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` | функциональная роль периода в исходной пьесе | -### 2.4 Записи аккордов +**Допустимые ноты для `key`:** `C, C#, D, D#, E, F, F#, G, G#, A, A#, B`. Бемольные написания (`Db`, `Eb`, ...) принимаются и нормализуются к диезной форме. -Внутри секции — последовательность тактов. Каждый такт обрамлён `|`. +**`subdivision`** определяет, сколько позиций в одном такте: -Внутри такта — `subdivision` позиций, разделённых пробелами. На каждой позиции либо аккордовый символ (новый аккорд начинается здесь), либо `.` (удержать предыдущий аккорд), либо `NC` (no chord — пауза/тишина в гармонии). +- При `subdivision: 4` в `4/4` — 4 позиции на такт (одна на четверть). +- При `subdivision: 8` в `4/4` — 8 позиций на такт (одна на восьмую). +- Для `3/4` — соответственно 3 или 6 позиций. +- Для `6/8` — 6 позиций при `subdivision: 8`, рекомендуемое значение. + +### 3.4 Тело файла + +Последовательность тактов. Такты записываются на одной строке через `|` или каждый на своей строке — парсер обрабатывает оба варианта одинаково. + +Внутри такта — ровно `subdivision` позиций (или соответствующее число для нестандартных размеров), разделённых **одним пробелом**. На каждой позиции — один токен. + +### 3.5 Что может стоять на позиции + +| Запись | Значение | +| ----------------- | ------------------------------------------------------------ | +| Аккордовый символ | новый аккорд начинается здесь | +| `.` | удержать предыдущий аккорд | +| `NC` | no chord — пауза в гармонии | +| `?` | unknown — для случаев неуверенности; парсер выпустит `` | + +Первая позиция первого такта не может быть `.` (нечего удерживать). + +### 3.6 Комментарии + +Строки и хвосты строк, начинающиеся с `//`, игнорируются: ``` -| D . . . | A/C# . . . | ← такт 1: D на 4 четверти; такт 2: A/C# на 4 четверти -| Em7 . D . | A . . . | ← такт 3: Em7 на 2 четверти, D на 2 четверти -| NC . . . | D . . . | ← такт 4: пауза; такт 5: D -``` - -Пробелов между токенами должно быть **строго один**, чтобы парсер по позициям различал доли. - -### 2.5 Комментарии - -Строки, начинающиеся с `//`, парсер игнорирует. Можно использовать для пометок. - -``` -// здесь модулируем в параллельный минор -[bridge] -| Bm . . . | F#m . . . | +// здесь характерный приём с проходящим басом +| F . . . | F/E . . . | Dm . . . | Dm/C . . . | ``` --- -## 3. Аккордовая нотация +## 4. Аккордовая нотация -### 3.1 Корневой тон +### 4.1 Структура аккордового символа -Один из 12 классов высоты, через диез: `C, C#, D, D#, E, F, F#, G, G#, A, A#, B`. - -Бемольная запись (`Db`, `Eb`, `Gb`, `Ab`, `Bb`) допускается на входе и парсер сам приведёт к диезной форме. Энгармоническое написание для модели не значимо. - -### 3.2 Базовые качества (18) - -| Символ | Название | Состав от корня | -| ------------------- | --------------------------- | --------------- | -| `maj` или ничего | мажорное трезвучие | 1, 3, 5 | -| `m` или `min` | минорное трезвучие | 1, b3, 5 | -| `dim` или `°` | уменьшённое трезвучие | 1, b3, b5 | -| `aug` или `+` | увеличенное трезвучие | 1, 3, #5 | -| `sus2` | sus2 | 1, 2, 5 | -| `sus4` | sus4 | 1, 4, 5 | -| `maj7` или `M7` | большой мажорный септаккорд | 1, 3, 5, 7 | -| `m7` | минорный септаккорд | 1, b3, 5, b7 | -| `7` | доминантовый септаккорд | 1, 3, 5, b7 | -| `m7b5` или `ø` | полууменьшённый | 1, b3, b5, b7 | -| `dim7` или `°7` | уменьшённый септ | 1, b3, b5, bb7 | -| `mM7` или `m(maj7)` | минорно-мажорный септ | 1, b3, 5, 7 | -| `7sus4` | доминанта на сус4 | 1, 4, 5, b7 | -| `aug7` или `7#5` | увеличенный септ | 1, 3, #5, b7 | -| `6` | мажорный с секстой | 1, 3, 5, 6 | -| `m6` | минорный с секстой | 1, b3, 5, 6 | -| `add9` | мажор с добавленной ноной | 1, 3, 5, 9 | -| `m(add9)` | минор с добавленной ноной | 1, b3, 5, 9 | - -Запись «без качества» (просто `C`) автоматически = `Cmaj`. - -### 3.3 Расширения (опционально) - -Один опциональный слот после качества. Поддерживаются: - -| Символ | Значение | -| --------------- | ------------------------------------------ | -| `9`, `b9`, `#9` | нона (натуральная, пониженная, повышенная) | -| `11`, `#11` | ундецима | -| `13`, `b13` | терцдецима | +``` +(/)? +``` Примеры: -- `Cmaj9` = `Cmaj7` + расширение `9` -- `C7b9` = `C7` + расширение `b9` -- `Fmaj7#11` = `Fmaj7` + расширение `#11` (лидийский) -- `Dm9` = `Dm7` + расширение `9` +- `C` → root=C, quality=maj (по умолчанию), без extension, bass=root +- `Am7` → root=A, quality=min7, без 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 -Условные сокращения, которые парсер расшифровывает: +### 4.2 Корневой тон -- `9` (например, `C9`) = `7` + расширение `9` (доминантовая нона) -- `maj9` = `maj7` + расширение `9` -- `m9` = `m7` + расширение `9` -- `13` = `7` + расширение `13` -- `m11` = `m7` + расширение `11` +Один из 12 классов: `C, C#, D, D#, E, F, F#, G, G#, A, A#, B`. Бемольная запись принимается. -Если хочется указать сразу несколько расширений (например, альтерированный доминант `C7#9b13`) — модель использует только **первое** расширение в записи. Это сознательное упрощение, чтобы не раздувать комбинаторику. На практике для J-Pop и поп-музыки этого хватает; для джазовых случаев можно записать как ближайший эквивалент. +### 4.3 Базовые качества (18) -### 3.4 Бас и слэш-аккорды +| Символ | Альтернативы | Состав от корня | +| --------------- | ------------------------------ | --------------- | +| `maj` или пусто | — | 1, 3, 5 | +| `m`, `min` | `-` | 1, ♭3, 5 | +| `dim` | `°` | 1, ♭3, ♭5 | +| `aug` | `+` | 1, 3, ♯5 | +| `sus2` | — | 1, 2, 5 | +| `sus4` | `sus` | 1, 4, 5 | +| `maj7` | `M7`, `Δ7`, `Δ` | 1, 3, 5, 7 | +| `m7` | `min7`, `-7` | 1, ♭3, 5, ♭7 | +| `7` | — | 1, 3, 5, ♭7 | +| `m7b5` | `ø`, `ø7`, `m7♭5` | 1, ♭3, ♭5, ♭7 | +| `dim7` | `°7` | 1, ♭3, ♭5, ♭♭7 | +| `mM7` | `m(maj7)`, `minMaj7` | 1, ♭3, 5, 7 | +| `7sus4` | `7sus` | 1, 4, 5, ♭7 | +| `aug7` | `7#5`, `+7` | 1, 3, ♯5, ♭7 | +| `6` | `maj6` | 1, 3, 5, 6 | +| `m6` | `min6` | 1, ♭3, 5, 6 | +| `add9` | `2` (в некоторых поп-нотациях) | 1, 3, 5, 9 | +| `m(add9)` | `madd9`, `m(add2)` | 1, ♭3, 5, 9 | -Для инверсий и слэш-аккордов — стандартный формат `/`: +Если качество не указано (например, просто `C`), оно автоматически = `maj`. + +### 4.4 Расширения (опционально) + +Один опциональный слот после качества: + +| Символ | Значение | +| ------ | ---------------- | +| `9` | нона натуральная | +| `b9` | ♭9 | +| `#9` | ♯9 | +| `11` | ундецима | +| `#11` | ♯11 (лидийская) | +| `13` | терцдецима | +| `b13` | ♭13 | + +**Условные сокращения, которые парсер расшифровывает автоматически:** + +| Запись | Расшифровка | +| ---------- | --------------------------- | +| `C9` | quality=7, extension=9 | +| `Cmaj9` | quality=maj7, extension=9 | +| `Cm9` | quality=m7, extension=9 | +| `C13` | quality=7, extension=13 | +| `Cmaj13` | quality=maj7, extension=13 | +| `Cm11` | quality=m7, extension=11 | +| `C7b9` | quality=7, extension=b9 | +| `Cmaj7#11` | quality=maj7, extension=#11 | + +**Ограничение:** ровно один слот расширения на аккорд. Если в исходной пьесе встречается аккорд с несколькими альтерациями (например, `C7♯9♭13`), нужно выбрать одну наиболее характерную и записать её. Это сознательное упрощение для уменьшения комбинаторики словаря. + +### 4.5 Инверсии и слэш-аккорды + +Стандартный формат `/`: ``` -F/A ← F с басом A (первое обращение) -G/B ← G с басом B -F/G ← F с басом G (характерный «on-аккорд» из J-Pop) -Em7/G ← Em7 с басом G +F/A ← F, бас A (первое обращение) +G/B ← G, бас B (первое обращение) +F/G ← F с басом G (характерный on-аккорд из J-Pop) +Em7/G ← Em7, бас G +D/F# ← D, бас F♯ ``` -Бас может быть как любой из 12 нот, так и любой ступенью аккорда. Парсер не проверяет, входит ли бас в состав аккорда — это ответственность транскрибера. +Бас может быть любой из 12 нот. Парсер не проверяет, входит ли бас в состав аккорда — это ответственность транскрибера. Если слэш не указан, считается `bass = root`. -Если слэш-нотация не указана, считается, что бас совпадает с корнем (BASS = root). +**Инверсии обязательны к точной записи.** Они несут значительную часть стилистической информации (особенно для J-Pop материала с характерной on-нотацией). -### 3.5 Специальные значения +### 4.6 Полные примеры разбора -| Запись | Значение | -| ------ | -------------------------------------------------------------------------------- | -| `.` | удержать предыдущий аккорд на этой позиции | -| `NC` | нет аккорда (пауза в гармонии) | -| `?` | unknown — для случаев, когда не уверен в транскрипции; парсер заменит на `` | +| Запись | root | quality | extension | bass | +| --------- | ---- | ------- | --------- | ---- | +| `C` | C | maj | none | root | +| `Am` | A | m | none | root | +| `F#m7` | F# | m7 | none | root | +| `Cmaj9` | C | maj7 | 9 | root | +| `G7sus4` | G | 7sus4 | none | root | +| `F/G` | F | maj | none | G | +| `Bb7b9/D` | A# | 7 | b9 | D | +| `Em7b5` | E | m7b5 | none | root | +| `D#dim7` | D# | dim7 | none | root | --- -## 4. Внутреннее токенизированное представление +## 5. Токенизированное представление -### 4.1 Словарь (≈100 токенов) +### 5.1 Принцип нормализации тональности + +**Перед токенизацией каждый период транспонируется в каноническую тональность:** + +- мажорные периоды → C major, +- минорные периоды → A minor. + +После транспозиции аккорды записываются абсолютными именами, но фактически отражают функциональные отношения относительно тоники. Тональность исходного периода в токенах **не присутствует**. + +На инференсе пользователь задаёт желаемую тональность, модель генерирует в C/Am, и результат транспонируется обратно постпроцессингом. + +### 5.2 Полный словарь **Служебные (4):** ``, ``, ``, `` -**Метаданные (всегда в начале последовательности, после ``):** +**Метаданные периода (выпускаются один раз в начале последовательности, после ``):** -- `KEY__` — 24 токена (12 нот × major/minor) -- `TIME_/` — 5 токенов: `TIME_4/4`, `TIME_3/4`, `TIME_6/8`, `TIME_2/4`, `TIME_12/8` -- `STYLE_` — 5 токенов: `STYLE_user`, `STYLE_jpop`, `STYLE_classical`, `STYLE_jazz`, `STYLE_other` -- `TEMPO_` — 4 токена: `TEMPO_slow`, `TEMPO_medium`, `TEMPO_fast`, `TEMPO_very_fast` -- `SUB_` — 2 токена: `SUB_4`, `SUB_8` +- `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 токенов +- `FUNC_verse`, `FUNC_prechorus`, `FUNC_chorus`, `FUNC_bridge`, `FUNC_intro`, `FUNC_outro`, `FUNC_interlude`, `FUNC_other`, `FUNC_unspecified` — 9 токенов -**Структурные:** +**Аккордовые слоты (новый аккорд = ровно 4 токена в порядке root, quality, extension, bass):** -- `SEC_` — 8 токенов: `SEC_intro`, `SEC_verse`, `SEC_prechorus`, `SEC_chorus`, `SEC_bridge`, `SEC_interlude`, `SEC_solo`, `SEC_outro` -- `BAR` — конец такта +- `ROOT_C`, `ROOT_C#`, ..., `ROOT_B` — 12 токенов +- `QUAL_maj`, `QUAL_m`, `QUAL_dim`, `QUAL_aug`, `QUAL_sus2`, `QUAL_sus4`, `QUAL_maj7`, `QUAL_m7`, `QUAL_7`, `QUAL_m7b5`, `QUAL_dim7`, `QUAL_mM7`, `QUAL_7sus4`, `QUAL_aug7`, `QUAL_6`, `QUAL_m6`, `QUAL_add9`, `QUAL_m_add9` — 18 токенов +- `EXT_none`, `EXT_9`, `EXT_b9`, `EXT_#9`, `EXT_11`, `EXT_#11`, `EXT_13`, `EXT_b13` — 8 токенов +- `BASS_root`, `BASS_C`, `BASS_C#`, ..., `BASS_B` — 13 токенов -**Аккордовые (4 слота на каждый аккорд):** - -- `ROOT_` — 12 токенов -- `QUAL_` — 18 токенов (см. §3.2) -- `EXT_` — 8 токенов: `EXT_none`, `EXT_9`, `EXT_b9`, `EXT_#9`, `EXT_11`, `EXT_#11`, `EXT_13`, `EXT_b13` -- `BASS_` — 13 токенов: `BASS_root` плюс 12 нот - -**Временные/специальные:** +**Временные/структурные:** - `HOLD` — позиция продолжает предыдущий аккорд - `NC` — пауза в гармонии +- `BAR` — конец такта -**Итого: ≈100 токенов.** +**Итого:** 4 + 2 + 5 + 2 + 5 + 9 + 12 + 18 + 8 + 13 + 3 = **81 токен**. -### 4.2 Структура последовательности +### 5.3 Структура обучающей последовательности ``` -KEY_ TIME_ SUB_ STYLE_ [TEMPO_] -SEC_ -ROOT_ QUAL_ EXT_ BASS_ ← новый аккорд = ровно 4 токена -HOLD ← удержание = 1 токен +MODE_ TIME_ SUB_ STYLE_ FUNC_ + +ROOT_ QUAL_ EXT_ BASS_ ← новый аккорд = 4 токена +HOLD ← удержание = 1 токен HOLD HOLD BAR + ROOT_ QUAL_ EXT_ BASS_ HOLD ROOT_ QUAL_ EXT_ BASS_ HOLD BAR -SEC_ + ... + ``` -### 4.3 Правила токенизации (источник → токены) +### 5.4 Алгоритм токенизации (источник → токены) -1. Прочитать шапку → выпустить `` и токены метаданных. -2. Каждая `[section]` строка → `SEC_`. -3. Для каждой позиции внутри такта: - - Если аккорд: разобрать на (root, quality, extension, bass). Выпустить 4 токена в этом порядке. - - Если `.`: выпустить `HOLD`. - - Если `NC`: выпустить `NC`. - - Если `?`: выпустить ``. -4. После последней позиции такта → `BAR`. -5. В конце пьесы → ``. +1. Прочитать шапку. +2. Транспонировать все аккорды: если `key = X_major`, транспонировать так, чтобы X стало C; если `key = X_minor` — так, чтобы X стало A. +3. Выпустить ``. +4. Выпустить метатокены: `MODE_`, `TIME_`, `SUB_`, `STYLE_`, `FUNC_` (если `function` не задан — выпустить `FUNC_unspecified`). +5. Для каждого такта: + - Для каждой позиции в такте: + - Если новый аккорд: разобрать на (root, quality, extension, bass), выпустить 4 токена в этом порядке. + - Если `.`: выпустить `HOLD`. + - Если `NC`: выпустить `NC`. + - Если `?`: выпустить ``. + - После последней позиции — `BAR`. +6. Выпустить ``. -### 4.4 Инвариант длины +### 5.5 Алгоритм детокенизации (токены → MIDI) -При `subdivision: 4` каждый такт даёт **переменное** число токенов (от 5 до 17): один `BAR` + от 4 (один аккорд × 4 поля) до 16 (четыре аккорда × 4 поля), плюс `HOLD`-ы. В среднем для поп-музыки получится 6–10 токенов на такт. +1. Считать метатокены, восстановить параметры периода. +2. Группировать аккордовые токены по 4 (root, quality, extension, bass). +3. Развернуть в последовательность аккордов с длительностями, считая HOLD-ы как продолжение предыдущего. +4. Транспонировать обратно из C/Am в целевую тональность (задаваемую пользователем на инференсе). +5. Сгенерировать MIDI через `pretty_midi`: для каждого аккорда выложить ноты в один трек, бас — отдельной линией в нижней октаве. -Типичная пьеса (~80 тактов) → **600–800 токенов**. Это комфортно укладывается в стандартное контекстное окно 1024–2048. +### 5.6 Оценка длины последовательности + +Период 8 тактов в 4/4 с subdivision=4, в среднем 2 смены аккорда на такт: + +- Метатокены: 1 (BOS) + 5 = 6 токенов +- На такт: 2 аккорда × 4 + 2 HOLD-а + 1 BAR = 11 токенов +- 8 тактов: ~88 токенов +- EOS: 1 +- **Итого: ~95 токенов на типичный период.** + +Длинный период (16 тактов с частой сменой): редко превышает 250 токенов. Контекстное окно 512 токенов более чем достаточно. --- -## 5. Полный пример +## 6. Полный пример -### 5.1 Источник +### 6.1 Исходный `.chord` файл ``` -# title: Example Song -# key: C_major +# title: Example period +# key: G_major # time: 4/4 # subdivision: 4 # style: user -# tempo_bucket: medium +# function: chorus -[verse] -| Cmaj7 . . . | Am7 . . . | Dm7 . G7 . | Cmaj7 . . . | - -[chorus] -| F . . . | F/G . G . | Em7 . Am7 . | Dm7 . G7sus4 G7 | +| Gmaj7 . . . | Bm7 . . . | Em7 . . . | C . . D . | +| Cmaj7 . . . | G/B . . . | Am7 . D . | G . . . | ``` -### 5.2 Токенизация +### 6.2 Токенизация + +Шаг 1: транспонировать из G major в C major (вниз на 7 полутонов или вверх на 5): ``` - KEY_C_major TIME_4/4 SUB_4 STYLE_user TEMPO_medium +| Cmaj7 . . . | Em7 . . . | Am7 . . . | F . . G . | +| Fmaj7 . . . | C/E . . . | Dm7 . G . | C . . . | +``` -SEC_verse +Шаг 2: выпустить токены: + +``` + +MODE_major TIME_4/4 SUB_4 STYLE_user FUNC_chorus ROOT_C QUAL_maj7 EXT_none BASS_root HOLD HOLD HOLD BAR -ROOT_A QUAL_min7 EXT_none BASS_root +ROOT_E QUAL_m7 EXT_none BASS_root HOLD HOLD HOLD BAR -ROOT_D QUAL_min7 EXT_none BASS_root -HOLD -ROOT_G QUAL_7 EXT_none BASS_root -HOLD -BAR - -ROOT_C QUAL_maj7 EXT_none BASS_root +ROOT_A QUAL_m7 EXT_none BASS_root HOLD HOLD HOLD BAR -SEC_chorus - ROOT_F QUAL_maj EXT_none BASS_root -HOLD HOLD HOLD -BAR - -ROOT_F QUAL_maj EXT_none BASS_G HOLD ROOT_G QUAL_maj EXT_none BASS_root HOLD BAR -ROOT_E QUAL_min7 EXT_none BASS_root +ROOT_F QUAL_maj7 EXT_none BASS_root +HOLD HOLD HOLD +BAR + +ROOT_C QUAL_maj EXT_none BASS_E +HOLD HOLD HOLD +BAR + +ROOT_D QUAL_m7 EXT_none BASS_root HOLD -ROOT_A QUAL_min7 EXT_none BASS_root +ROOT_G QUAL_maj EXT_none BASS_root HOLD BAR -ROOT_D QUAL_min7 EXT_none BASS_root -HOLD -ROOT_G QUAL_7sus4 EXT_none BASS_root -ROOT_G QUAL_7 EXT_none BASS_root +ROOT_C QUAL_maj EXT_none BASS_root +HOLD HOLD HOLD BAR ``` -(В реальности — без переносов строк и пустых строк, всё идёт одним потоком; здесь форматирование только для читаемости.) +(Переносы строк здесь для читаемости; в реальности — один поток.) --- -## 6. Краевые случаи и соглашения +## 7. Краевые случаи -### 6.1 Анакруза (затакт) +### 7.1 Анакруза (затакт) -Записывается как первый «обычный» такт, но с `NC` на пустых позициях: +Записывается как первый такт с `NC` на пустых позициях: ``` -| NC . . D | G . . . | +| NC . . D | G . . . | ... ``` -### 6.2 Смена тональности +### 7.2 Тонально нестабильные фрагменты -Если внутри пьесы происходит модуляция, можно ввести inline-тег `[modulate: F_major]`. На уровне токенов это выпустит `KEY_F_major` посреди последовательности. **Для первой версии** этим лучше не пользоваться — модель проще учить на тонально стабильных пьесах. Если в твоих работах часто бывают модуляции, расскажи отдельно — обсудим, как разрезать пьесу на тонально-однородные сегменты. +Если внутри периода невозможно однозначно определить тональность (например, секвенция через несколько тоник) — записать его в наиболее подходящей тональности по контексту исходной пьесы. Внутренние отклонения и тонизации записываются обычными функциональными аккордами; это не модуляция. -### 6.3 Смена тактового размера +Истинная модуляция (смена тональности в середине периода) **в текущей версии формата не поддерживается**. Если в исходной пьесе период модулирует — разрезать его на два периода: до и после модуляции. -Аналогично — inline `[time: 3/4]`. Тоже лучше избегать в первой версии. +### 7.3 Смена тактового размера внутри периода -### 6.4 Полиаккорды +Не поддерживается. Если есть — разрезать на два периода. -Запись `D/C` (треугольник вверху, квадрат внизу) **не поддерживается** как полиаккорд, только как inverse/слэш. В подавляющем большинстве случаев в поп-музыке слэш-нотации достаточно. Истинные полиаккорды редки и для проекта не критичны. +### 7.4 Полиаккорды -### 6.5 Аккорды вне 12-ступенной системы +Не поддерживаются. Записывать как слэш-аккорд или ближайший наиболее характерный single chord. -Не поддерживаются. Если в материале есть микротональные элементы — округлять до ближайшего темперированного аккорда или отмечать как `?`. +### 7.5 Микротональность -### 6.6 Pickup notes / fills +Не поддерживается. Округлять до ближайшего темперированного аккорда. -Гармонические заполнения и проходящие аккорды записываются обычным образом, на сетке. Если они короче subdivision (например, проходящий восьмой аккорд при subdivision: 4) — либо переключить subdivision на 8 для этой пьесы, либо округлить. +### 7.6 Аккорды короче subdivision -### 6.7 Имена файлов - -Рекомендованный формат: `YYYY_NN_short-title.chord`, где `YYYY` — год создания пьесы, `NN` — её номер в этом году. Это упростит хронологическую сортировку датасета и поможет, если потом захочется анализировать эволюцию стиля во времени. - -### 6.8 Что НЕ кодируется - -Сознательно вне формата: - -- voicing (расположение голосов внутри аккорда сверх баса); -- ритмический паттерн внутри удержания (пунктир, синкопы внутри одного аккорда); -- динамика, артикуляция; -- тембр, аранжировка; -- мелодия (это отдельная задача). - -Это правильный уровень абстракции для гармонической задачи. Всё остальное — на ручную работу в DAW при использовании сгенерированной прогрессии. +Если в пьесе систематически встречаются аккорды длительностью короче выбранного subdivision (например, восьмая нота при `subdivision: 4`) — переключить весь период на `subdivision: 8`. Не округлять и не выбрасывать аккорды. --- -## 7. Чек-лист транскрипции +## 8. Соглашения по именам файлов -При перекладывании пьесы из DAW в `.chord`-файл: +Рекомендованный формат: -1. Заполнить шапку: title, key, time, subdivision, style, tempo_bucket. -2. Прослушать пьесу целиком, разметить секции. -3. Для каждой секции — определить шаблонную единицу (4 такта? 8?), записать гармонию по позициям. -4. Прогнать парсер (когда он будет написан) и проверить, что нет `` токенов и предупреждений о неизвестных качествах. -5. Сравнить «на слух»: воспроизвести аккорды в DAW по транскрипции и убедиться, что слышимая гармония совпадает с оригиналом. +``` +YYYY_NNN__.chord +``` -Этот шаг 5 особенно важен — даже с абсолютным слухом легко пропустить инверсию или septима↔nona в плотной фактуре. +Где: + +- `YYYY` — год создания исходной пьесы +- `NNN` — порядковый номер периода в датасете (000–999) +- `` — короткое имя в kebab-case +- `` — функциональная роль (опционально, для удобства поиска) + +Примеры: + +``` +2024_001_sea-glass_chorus.chord +2024_002_sea-glass_verse.chord +2025_037_winter-light_bridge.chord +``` + +Это упростит хронологическую сортировку датасета и поиск по функции. --- -## 8. История изменений +## 9. Что НЕ кодируется (сознательные пропуски) -- **v1.0** — первоначальная спецификация. +- **Voicing** (расположение голосов внутри аккорда выше баса). Бас передаётся, остальное — на ручную работу в DAW. +- **Ритмический паттерн** внутри удержания аккорда (восьмые, синкопы, паттерны типа альбертиевых басов). +- **Динамика, артикуляция, тембр, аранжировка.** +- **Мелодия.** Это отдельная задача за пределами текущего проекта. +- **Полная форма пьесы.** Юнит — период, не пьеса целиком. +- **Метроритмическая микроразметка** (свинг, рубато, ramp'ы темпа). + +--- + +## 10. Чек-лист транскрипции + +При перекладывании периода из DAW в `.chord` файл: + +1. **Прослушать пьесу целиком**, определить границы периодов. Замкнутая фраза с возвратом к тонике или ясной полукаденцией — кандидат на период. +2. **Заполнить шапку:** title, key, time, subdivision, style, function. +3. **Проверить subdivision.** Если в выбранном периоде аккорды стабильно меняются не чаще четверти — `subdivision: 4`. Если есть систематические восьмые смены — `subdivision: 8`. +4. **Транскрибировать гармонию по позициям**, аккуратно фиксируя инверсии. +5. **Прогнать парсер**, проверить отсутствие `` и предупреждений. +6. **Прогнать sanity-check утилиту** (`.chord` → MIDI), воспроизвести в DAW параллельно с оригиналом, убедиться в совпадении. +7. **Сохранить файл** под именем по схеме из §8. + +--- + +## 11. История изменений + +- **v2.0** (текущая) + - Единицей датасета стал **гармонический период**, не пьеса целиком. + - Введена **нормализация тональности** в C major / A minor. Поле `key` сохраняется в шапке для парсера, но в словаре модели нет — есть только `MODE_major` / `MODE_minor`. + - Введён тег `function` (необязательный) как метаданные периода. + - Удалены секционные теги (больше не нужны при периодной разбивке). + - Удалён тег `tempo_bucket` (мало пользы при текущем объёме данных). + - Словарь сокращён с ~100 до 81 токена. + +- **v1.0** — первоначальная спецификация, единицей была целая пьеса, тональность входила в словарь, использовались секционные теги внутри последовательности.