3cd9c29d9f
Add 5/4, 7/4, 7/8, 9/8 to _VALID_TIMES and VOCAB (TIME_* tokens). Vocab size grows from 81 to 85 tokens. _parse_metre in the McGill converter assigns subdivision=8 to 7/8 and 9/8. Spec bumped to v2.2. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
501 lines
28 KiB
Markdown
501 lines
28 KiB
Markdown
# Спецификация формата данных hamori
|
||
|
||
**Версия:** 2.2
|
||
**Дата:** 2026-05-20
|
||
|
||
---
|
||
|
||
## 1. Что описывает этот документ
|
||
|
||
Формат хранения и кодирования гармонических периодов для обучения генеративной модели и для практического использования модели как творческого помощника.
|
||
|
||
Один файл в этом формате описывает **один гармонический период** (4–16 тактов) — замкнутую гармоническую фразу.
|
||
|
||
---
|
||
|
||
## 2. Архитектура формата
|
||
|
||
Формат двухуровневый:
|
||
|
||
- **Исходный (`.chord`)** — то, что пишется руками. Близок к лид-шиту, человекочитаем, легко правится в любом текстовом редакторе.
|
||
- **Токенизированный** — то, что подаётся в модель. Факторизованное представление с фиксированным словарём (85 токенов).
|
||
|
||
Между уровнями стоит детерминированный парсер.
|
||
|
||
---
|
||
|
||
## 3. Исходный формат `.chord`
|
||
|
||
### 3.1 Пример
|
||
|
||
```
|
||
# title: Sea Glass - chorus
|
||
# key: D_major
|
||
# time: 4/4
|
||
# subdivision: 4
|
||
# style: H1K0
|
||
# function: chorus
|
||
|
||
| Gmaj7 . . . | A . . . | F#m7 . . . | Bm7 . . . |
|
||
| Gmaj7 . . . | A . . . | D . . . | D . . . |
|
||
```
|
||
|
||
### 3.2 Структура файла
|
||
|
||
Один файл — один период. Расширение `.chord`. Кодировка UTF-8.
|
||
|
||
Состоит из двух частей:
|
||
|
||
1. **Шапка** — строки, начинающиеся с `#`, в любом порядке.
|
||
2. **Тело** — последовательность тактов, каждый обрамлён `|`.
|
||
|
||
Пустые строки игнорируются. Комментарии (`// ...`) игнорируются парсером.
|
||
|
||
### 3.3 Поля шапки
|
||
|
||
| Поле | Обязательно | Допустимые значения | Назначение |
|
||
| ------------- | ----------- | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||
| `title` | да | свободная строка | идентификация периода |
|
||
| `key` | да | `<note>_major` или `<note>_minor` | для нормализации в C/Am перед обучением |
|
||
| `time` | да | `4/4`, `3/4`, `6/8`, `2/4`, `12/8`, `5/4`, `7/4`, `7/8`, `9/8` | тактовый размер |
|
||
| `subdivision` | да | `4` или `8` | сколько позиций в одном такте |
|
||
| `style` | да | любой идентификатор `[A-Za-z][A-Za-z0-9_]*` (например: `H1K0`, `jpop`, `other`) | стилевой тег периода; при токенизации тег должен совпасть с токеном `STYLE_<tag>` в словаре, иначе используется `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`, ...) принимаются и нормализуются к диезной форме.
|
||
|
||
**`subdivision`** определяет, сколько позиций в одном такте:
|
||
|
||
- При `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 — для случаев неуверенности; парсер выпустит `<UNK>` |
|
||
|
||
Первая позиция первого такта не может быть `.` (нечего удерживать).
|
||
|
||
### 3.6 Комментарии
|
||
|
||
Строки и хвосты строк, начинающиеся с `//`, игнорируются:
|
||
|
||
```
|
||
// здесь характерный приём с проходящим басом
|
||
| F . . . | F/E . . . | Dm . . . | Dm/C . . . |
|
||
```
|
||
|
||
---
|
||
|
||
## 4. Аккордовая нотация
|
||
|
||
### 4.1 Структура аккордового символа
|
||
|
||
```
|
||
<root><quality?><extension?>(/<bass>)?
|
||
```
|
||
|
||
Примеры:
|
||
|
||
- `C` → root=C, quality=maj (по умолчанию), без 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=m7, extension=9, bass=F
|
||
|
||
### 4.2 Корневой тон
|
||
|
||
Один из 12 классов: `C, C#, D, D#, E, F, F#, G, G#, A, A#, B`. Бемольная запись принимается.
|
||
|
||
### 4.3 Базовые качества (18)
|
||
|
||
| Символ | Альтернативы | Состав от корня |
|
||
| --------------- | ------------------------------ | --------------- |
|
||
| `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 Инверсии и слэш-аккорды
|
||
|
||
Стандартный формат `<chord>/<bass>`:
|
||
|
||
```
|
||
F/A ← F, бас A (первое обращение)
|
||
G/B ← G, бас B (первое обращение)
|
||
F/G ← F с басом G (характерный on-аккорд из J-Pop)
|
||
Em7/G ← Em7, бас G
|
||
D/F# ← D, бас F♯
|
||
```
|
||
|
||
Бас может быть любой из 12 нот. Парсер не проверяет, входит ли бас в состав аккорда — это ответственность транскрибера. Если слэш не указан, считается `bass = root`.
|
||
|
||
**Инверсии обязательны к точной записи.** Они несут значительную часть стилистической информации (особенно для J-Pop материала с характерной on-нотацией).
|
||
|
||
### 4.6 Полные примеры разбора
|
||
|
||
| Запись | 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 |
|
||
|
||
---
|
||
|
||
## 5. Токенизированное представление
|
||
|
||
### 5.1 Принцип нормализации тональности
|
||
|
||
**Перед токенизацией каждый период транспонируется в каноническую тональность:**
|
||
|
||
- мажорные периоды → C major,
|
||
- минорные периоды → A minor.
|
||
|
||
После транспозиции аккорды записываются абсолютными именами, но фактически отражают функциональные отношения относительно тоники. Тональность исходного периода в токенах **не присутствует**.
|
||
|
||
На инференсе пользователь задаёт желаемую тональность, модель генерирует в C/Am, и результат транспонируется обратно постпроцессингом.
|
||
|
||
### 5.2 Полный словарь
|
||
|
||
**Служебные (4):**
|
||
`<BOS>`, `<EOS>`, `<PAD>`, `<UNK>`
|
||
|
||
**Метаданные периода (выпускаются один раз в начале последовательности, после `<BOS>`):**
|
||
|
||
- `MODE_major`, `MODE_minor` — 2 токена (наследие тональности; нужны, потому что мажор и минор остаются разделёнными)
|
||
- `TIME_4/4`, `TIME_3/4`, `TIME_6/8`, `TIME_2/4`, `TIME_12/8`, `TIME_5/4`, `TIME_7/4`, `TIME_7/8`, `TIME_9/8` — 9 токенов
|
||
- `SUB_4`, `SUB_8` — 2 токена
|
||
- `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):**
|
||
|
||
- `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 токенов
|
||
|
||
**Временные/структурные:**
|
||
|
||
- `HOLD` — позиция продолжает предыдущий аккорд
|
||
- `NC` — пауза в гармонии
|
||
- `BAR` — конец такта
|
||
|
||
**Итого:** 4 + 2 + 9 + 2 + 5 + 9 + 12 + 18 + 8 + 13 + 3 = **85 токенов**.
|
||
|
||
### 5.3 Структура обучающей последовательности
|
||
|
||
```
|
||
<BOS>
|
||
MODE_<x> TIME_<x> SUB_<x> STYLE_<x> FUNC_<x>
|
||
|
||
ROOT_<x> QUAL_<x> EXT_<x> BASS_<x> ← новый аккорд = 4 токена
|
||
HOLD ← удержание = 1 токен
|
||
HOLD
|
||
HOLD
|
||
BAR
|
||
|
||
ROOT_<x> QUAL_<x> EXT_<x> BASS_<x>
|
||
HOLD
|
||
ROOT_<x> QUAL_<x> EXT_<x> BASS_<x>
|
||
HOLD
|
||
BAR
|
||
|
||
...
|
||
|
||
<EOS>
|
||
```
|
||
|
||
### 5.4 Алгоритм токенизации (источник → токены)
|
||
|
||
1. Прочитать шапку.
|
||
2. Транспонировать все аккорды: если `key = X_major`, транспонировать так, чтобы X стало C; если `key = X_minor` — так, чтобы X стало A.
|
||
3. Выпустить `<BOS>`.
|
||
4. Выпустить метатокены: `MODE_<major|minor>`, `TIME_<x>`, `SUB_<x>`, `STYLE_<x>`, `FUNC_<x>` (если `function` не задан — выпустить `FUNC_unspecified`; если `STYLE_<style>` отсутствует в словаре — выпустить `STYLE_other` с предупреждением в лог).
|
||
5. Для каждого такта:
|
||
- Для каждой позиции в такте:
|
||
- Если новый аккорд: разобрать на (root, quality, extension, bass), выпустить 4 токена в этом порядке.
|
||
- Если `.`: выпустить `HOLD`.
|
||
- Если `NC`: выпустить `NC`.
|
||
- Если `?`: выпустить `<UNK>`.
|
||
- После последней позиции — `BAR`.
|
||
6. Выпустить `<EOS>`.
|
||
|
||
### 5.5 Алгоритм детокенизации (токены → MIDI)
|
||
|
||
1. Считать метатокены, восстановить параметры периода.
|
||
2. Группировать аккордовые токены по 4 (root, quality, extension, bass).
|
||
3. Развернуть в последовательность аккордов с длительностями, считая HOLD-ы как продолжение предыдущего.
|
||
4. Транспонировать обратно из C/Am в целевую тональность (задаваемую пользователем на инференсе).
|
||
5. Сгенерировать MIDI через `pretty_midi`: для каждого аккорда выложить ноты в один трек, бас — отдельной линией в нижней октаве.
|
||
|
||
### 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.7 Добавление нового стилевого тега
|
||
|
||
Поле `style` в `.chord` файле принимает любой идентификатор — дополнительный код менять не нужно. Однако, чтобы модель кондиционировалась на новый стиль отдельным токеном (а не сваливала его в `STYLE_other`), нужно зарегистрировать токен в словаре:
|
||
|
||
1. Открыть `src/tokenizer.py`, найти блок `# Style (5)` в списке `VOCAB`.
|
||
2. Добавить `"STYLE_<tag>"` в этот блок. Пример: `"STYLE_ALICE"`.
|
||
3. Обновить счётчик в §5.2 этой спецификации и в итоговой строке («**N токенов**»).
|
||
4. **Переобучить модель с нуля** — изменение размера словаря меняет размер матрицы эмбеддингов и выходного слоя; дообучить существующий чекпоинт не получится.
|
||
5. Обновить все `.chord` файлы нужного корпуса, выставив новый тег в поле `style`.
|
||
|
||
Если токен не зарегистрирован, парсер принимает файл без ошибок, но токенизатор выдаёт `STYLE_other` и пишет предупреждение в лог. Это удобно для экспериментов до переобучения.
|
||
|
||
---
|
||
|
||
## 6. Полный пример
|
||
|
||
### 6.1 Исходный `.chord` файл
|
||
|
||
```
|
||
# title: Example period
|
||
# key: G_major
|
||
# time: 4/4
|
||
# subdivision: 4
|
||
# style: H1K0
|
||
# function: chorus
|
||
|
||
| Gmaj7 . . . | Bm7 . . . | Em7 . . . | C . D . |
|
||
| Cmaj7 . . . | G/B . . . | Am7 . D . | G . . . |
|
||
```
|
||
|
||
### 6.2 Токенизация
|
||
|
||
Шаг 1: транспонировать из G major в C major (вниз на 7 полутонов или вверх на 5):
|
||
|
||
```
|
||
| Cmaj7 . . . | Em7 . . . | Am7 . . . | F . G . |
|
||
| Fmaj7 . . . | C/E . . . | Dm7 . G . | C . . . |
|
||
```
|
||
|
||
Шаг 2: выпустить токены:
|
||
|
||
```
|
||
<BOS>
|
||
MODE_major TIME_4/4 SUB_4 STYLE_H1K0 FUNC_chorus
|
||
|
||
ROOT_C QUAL_maj7 EXT_none BASS_root
|
||
HOLD HOLD HOLD
|
||
BAR
|
||
|
||
ROOT_E QUAL_m7 EXT_none BASS_root
|
||
HOLD HOLD HOLD
|
||
BAR
|
||
|
||
ROOT_A QUAL_m7 EXT_none BASS_root
|
||
HOLD HOLD HOLD
|
||
BAR
|
||
|
||
ROOT_F QUAL_maj EXT_none BASS_root
|
||
HOLD
|
||
ROOT_G QUAL_maj EXT_none BASS_root
|
||
HOLD
|
||
BAR
|
||
|
||
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_G QUAL_maj EXT_none BASS_root
|
||
HOLD
|
||
BAR
|
||
|
||
ROOT_C QUAL_maj EXT_none BASS_root
|
||
HOLD HOLD HOLD
|
||
BAR
|
||
|
||
<EOS>
|
||
```
|
||
|
||
(Переносы строк здесь для читаемости; в реальности — один поток.)
|
||
|
||
---
|
||
|
||
## 7. Краевые случаи
|
||
|
||
### 7.1 Анакруза (затакт)
|
||
|
||
Записывается как первый такт с `NC` на пустых позициях:
|
||
|
||
```
|
||
| NC . . D | G . . . | ...
|
||
```
|
||
|
||
### 7.2 Тонально нестабильные фрагменты
|
||
|
||
Если внутри периода невозможно однозначно определить тональность (например, секвенция через несколько тоник) — записать его в наиболее подходящей тональности по контексту исходной пьесы. Внутренние отклонения и тонизации записываются обычными функциональными аккордами; это не модуляция.
|
||
|
||
Истинная модуляция (смена тональности в середине периода) **в текущей версии формата не поддерживается**. Если в исходной пьесе период модулирует — разрезать его на два периода: до и после модуляции.
|
||
|
||
### 7.3 Смена тактового размера внутри периода
|
||
|
||
Не поддерживается. Если есть — разрезать на два периода.
|
||
|
||
### 7.4 Полиаккорды
|
||
|
||
Не поддерживаются. Записывать как слэш-аккорд или ближайший наиболее характерный single chord.
|
||
|
||
### 7.5 Микротональность
|
||
|
||
Не поддерживается. Округлять до ближайшего темперированного аккорда.
|
||
|
||
### 7.6 Аккорды короче subdivision
|
||
|
||
Если в пьесе систематически встречаются аккорды длительностью короче выбранного subdivision (например, восьмая нота при `subdivision: 4`) — переключить весь период на `subdivision: 8`. Не округлять и не выбрасывать аккорды.
|
||
|
||
---
|
||
|
||
## 8. Соглашения по именам файлов
|
||
|
||
Рекомендованный формат:
|
||
|
||
```
|
||
YYYY_NNN_<short-title>_<function>.chord
|
||
```
|
||
|
||
Где:
|
||
|
||
- `YYYY` — год создания исходной пьесы
|
||
- `NNN` — порядковый номер периода в датасете (000–999)
|
||
- `<short-title>` — короткое имя в kebab-case
|
||
- `<function>` — функциональная роль (опционально, для удобства поиска)
|
||
|
||
Примеры:
|
||
|
||
```
|
||
2024_001_sea-glass_chorus.chord
|
||
2024_002_sea-glass_verse.chord
|
||
2025_037_winter-light_bridge.chord
|
||
```
|
||
|
||
Это упростит хронологическую сортировку датасета и поиск по функции.
|
||
|
||
---
|
||
|
||
## 9. Что НЕ кодируется (сознательные пропуски)
|
||
|
||
- **Voicing** (расположение голосов внутри аккорда выше баса). Бас передаётся, остальное — на ручную работу в DAW.
|
||
- **Ритмический паттерн** внутри удержания аккорда (восьмые, синкопы, паттерны типа альбертиевых басов).
|
||
- **Динамика, артикуляция, тембр, аранжировка.**
|
||
- **Мелодия.** Это отдельная задача за пределами текущего проекта.
|
||
- **Полная форма пьесы.** Юнит — период, не пьеса целиком.
|
||
- **Метроритмическая микроразметка** (свинг, рубато, ramp'ы темпа).
|
||
|
||
---
|
||
|
||
## 10. Чек-лист транскрипции
|
||
|
||
При перекладывании периода из DAW в `.chord` файл:
|
||
|
||
1. **Прослушать пьесу целиком**, определить границы периодов. Замкнутая фраза с возвратом к тонике или ясной полукаденцией — кандидат на период.
|
||
2. **Заполнить шапку:** title, key, time, subdivision, style, function.
|
||
3. **Проверить subdivision.** Если в выбранном периоде аккорды стабильно меняются не чаще четверти — `subdivision: 4`. Если есть систематические восьмые смены — `subdivision: 8`.
|
||
4. **Транскрибировать гармонию по позициям**, аккуратно фиксируя инверсии.
|
||
5. **Прогнать парсер**, проверить отсутствие `<UNK>` и предупреждений.
|
||
6. **Прогнать sanity-check утилиту** (`.chord` → MIDI), воспроизвести в DAW параллельно с оригиналом, убедиться в совпадении.
|
||
7. **Сохранить файл** под именем по схеме из §8.
|
||
|
||
---
|
||
|
||
## 11. История изменений
|
||
|
||
- **v2.2** (текущая)
|
||
- Добавлены тактовые размеры `5/4`, `7/4`, `7/8`, `9/8` — в допустимые значения поля `time` и в словарь (`TIME_*`).
|
||
- Размер словаря: 81 → 85 токенов.
|
||
|
||
- **v2.1**
|
||
- Поле `style` теперь принимает любой идентификатор `[A-Za-z][A-Za-z0-9_]*`, а не фиксированный список.
|
||
- `STYLE_user` заменён на `STYLE_H1K0` (авторский тег) в словаре модели.
|
||
- Неизвестный стиль при токенизации маппируется на `STYLE_other` с предупреждением в лог.
|
||
|
||
- **v2.0**
|
||
- Единицей датасета стал **гармонический период**, не пьеса целиком.
|
||
- Введена **нормализация тональности** в C major / A minor. Поле `key` сохраняется в шапке для парсера, но в словаре модели нет — есть только `MODE_major` / `MODE_minor`.
|
||
- Введён тег `function` (необязательный) как метаданные периода.
|
||
- Удалены секционные теги (больше не нужны при периодной разбивке).
|
||
- Удалён тег `tempo_bucket` (мало пользы при текущем объёме данных).
|
||
- Словарь сокращён с ~100 до 81 токена.
|
||
|
||
- **v1.0** — первоначальная спецификация, единицей была целая пьеса, тональность входила в словарь, использовались секционные теги внутри последовательности.
|