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 <noreply@anthropic.com>
24 KiB
Спецификация формата данных
Проект: генератор аккордовых последовательностей
Версия: 2.0 Дата: 2026-05-16
1. Что описывает этот документ
Формат хранения и кодирования гармонических периодов для обучения генеративной модели и для практического использования модели как творческого помощника.
Один файл в этом формате описывает один гармонический период (4–16 тактов) — замкнутую гармоническую фразу.
2. Архитектура формата
Формат двухуровневый:
- Исходный (
.chord) — то, что пишется руками. Близок к лид-шиту, человекочитаем, легко правится в любом текстовом редакторе. - Токенизированный — то, что подаётся в модель. Факторизованное представление с маленьким словарём (~75 токенов).
Между уровнями стоит детерминированный парсер.
3. Исходный формат .chord
3.1 Пример
# title: Sea Glass - chorus
# key: D_major
# time: 4/4
# subdivision: 4
# style: user
# function: chorus
| Gmaj7 . . . | A . . . | F#m7 . . . | Bm7 . . . |
| Gmaj7 . . . | A . . . | D . . . | D . . . |
3.2 Структура файла
Один файл — один период. Расширение .chord. Кодировка UTF-8.
Состоит из двух частей:
- Шапка — строки, начинающиеся с
#, в любом порядке. - Тело — последовательность тактов, каждый обрамлён
|.
Пустые строки игнорируются. Комментарии (// ...) игнорируются парсером.
3.3 Поля шапки
| Поле | Обязательно | Допустимые значения | Назначение |
|---|---|---|---|
title |
да | свободная строка | идентификация периода |
key |
да | <note>_major или <note>_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 |
функциональная роль периода в исходной пьесе |
Допустимые ноты для 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=rootAm7→ root=A, quality=min7, без extension, bass=rootFmaj9→ root=F, quality=maj7, extension=9, bass=rootG7/B→ root=G, quality=7, без extension, bass=BDm9/F→ root=D, quality=min7, 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— 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):
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 + 5 + 2 + 5 + 9 + 12 + 18 + 8 + 13 + 3 = 81 токен.
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 Алгоритм токенизации (источник → токены)
- Прочитать шапку.
- Транспонировать все аккорды: если
key = X_major, транспонировать так, чтобы X стало C; еслиkey = X_minor— так, чтобы X стало A. - Выпустить
<BOS>. - Выпустить метатокены:
MODE_<major|minor>,TIME_<x>,SUB_<x>,STYLE_<x>,FUNC_<x>(еслиfunctionне задан — выпуститьFUNC_unspecified). - Для каждого такта:
- Для каждой позиции в такте:
- Если новый аккорд: разобрать на (root, quality, extension, bass), выпустить 4 токена в этом порядке.
- Если
.: выпуститьHOLD. - Если
NC: выпуститьNC. - Если
?: выпустить<UNK>.
- После последней позиции —
BAR.
- Для каждой позиции в такте:
- Выпустить
<EOS>.
5.5 Алгоритм детокенизации (токены → MIDI)
- Считать метатокены, восстановить параметры периода.
- Группировать аккордовые токены по 4 (root, quality, extension, bass).
- Развернуть в последовательность аккордов с длительностями, считая HOLD-ы как продолжение предыдущего.
- Транспонировать обратно из C/Am в целевую тональность (задаваемую пользователем на инференсе).
- Сгенерировать 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 токенов более чем достаточно.
6. Полный пример
6.1 Исходный .chord файл
# title: Example period
# key: G_major
# time: 4/4
# subdivision: 4
# style: user
# 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_user 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 файл:
- Прослушать пьесу целиком, определить границы периодов. Замкнутая фраза с возвратом к тонике или ясной полукаденцией — кандидат на период.
- Заполнить шапку: title, key, time, subdivision, style, function.
- Проверить subdivision. Если в выбранном периоде аккорды стабильно меняются не чаще четверти —
subdivision: 4. Если есть систематические восьмые смены —subdivision: 8. - Транскрибировать гармонию по позициям, аккуратно фиксируя инверсии.
- Прогнать парсер, проверить отсутствие
<UNK>и предупреждений. - Прогнать sanity-check утилиту (
.chord→ MIDI), воспроизвести в DAW параллельно с оригиналом, убедиться в совпадении. - Сохранить файл под именем по схеме из §8.
11. История изменений
-
v2.0 (текущая)
- Единицей датасета стал гармонический период, не пьеса целиком.
- Введена нормализация тональности в C major / A minor. Поле
keyсохраняется в шапке для парсера, но в словаре модели нет — есть толькоMODE_major/MODE_minor. - Введён тег
function(необязательный) как метаданные периода. - Удалены секционные теги (больше не нужны при периодной разбивке).
- Удалён тег
tempo_bucket(мало пользы при текущем объёме данных). - Словарь сокращён с ~100 до 81 токена.
-
v1.0 — первоначальная спецификация, единицей была целая пьеса, тональность входила в словарь, использовались секционные теги внутри последовательности.