- BrainTools - https://www.braintools.ru -

Как плеер угадывает тональность трека: 12 чисел и одна корреляция

Я делаю музыкальный плеер Nami. Он показывает у каждого трека тональность: «ми минор», «ре мажор». После поста про плеер в комментариях спросили, как это вообще считается. Вопрос звучал примерно так: у Прокофьева в мажорной тональности мажора на слух [1] почти нет, так как программа решает?

Короткий ответ: программа не слушает гармонию, как музыкант. Она считает, сколько в записи звучит каждой из 12 нот, и ищет мажорную или минорную гамму, на которую этот набор похож сильнее всего. Ниже я разберу, как это устроено, покажу картинки на реальных треках и расскажу, где метод ошибается.

Шаг 1. Хромаграмма: сколько звучит каждой ноты

Плеер берёт первые 90 секунд трека, сводит их в моно и понижает частоту до 22 050 Гц. Дальше запись режется на окна по 4096 отсчётов (около 0,19 с) с перекрытием в половину окна. Каждое окно проходит через быстрое преобразование Фурье, и получается спектр: сколько энергии на каждой частоте.

Частоту легко перевести в ноту. Ля первой октавы звучит на 440 Гц, каждый полутон умножает частоту на ¹²√2. Номер ноты по стандарту MIDI:

midi = 69 + 12 · log2(f / 440)

Октава при этом не важна: до в любой октаве считается одной нотой. Остаток от деления на 12 даёт класс ноты от 0 (до) до 11 (си). Амплитуды всех частот одного класса складываются, и получается 12 чисел. Это хромаграмма. Частоты ниже 80 Гц и выше 5000 Гц я отбрасываю: внизу гудит бас и бочка, вверху шипят тарелки и обертоны.

for k in 1..FFT_SIZE / 2 {
    let freq = k as f64 * rate as f64 / FFT_SIZE as f64;
    if !(80.0..=5000.0).contains(&freq) {
        continue;
    }
    let mag = (re[k] * re[k] + im[k] * im[k]).sqrt();
    let midi = 69.0 + 12.0 * (freq / 440.0).log2();
    let pc = (((midi.round() as i64 - 60) % 12 + 12) % 12) as usize;
    chroma[pc] += mag;
}

Шаг 2. Профили: как «должна» звучать тональность

Хромаграмму нужно с чем-то сравнить. Для этого есть профили Крумхансл и Кесслер. В 1982 году психологи Кэрол Крумхансл и Эдвард Кесслер ставили слушателям с музыкальным образованием каденцию (короткую последовательность аккордов) в нужной тональности, потом играли одну ноту и просили оценить, насколько она «подходит». Так получились 12 оценок для мажора и 12 для минора.

Профили Крумхансл-Кесслер для до мажора и до минора

Профили Крумхансл-Кесслер для до мажора и до минора

Выше всего оценена тоника, потом квинта и терция. Ноты не из гаммы оценены ниже всего. В мажоре и миноре разница в основном в терции: ми в до мажоре и ми-бемоль в до миноре.

Профиль построен для до. Для другой тоники его сдвигают по кругу: профиль ре мажора – это профиль до мажора, сдвинутый на два полутона. 12 тоник на 2 лада дают 24 профиля.

Шаг 3. Корреляция: какая гамма похожа сильнее

Осталось сравнить хромаграмму с каждым из 24 профилей. Я беру обычный коэффициент корреляции Пирсона: он не зависит от громкости записи и показывает только похожесть формы. Тональность с наибольшей корреляцией и есть ответ. Этот способ называют алгоритмом Крумхансл-Шмуклера, Крумхансл описала его в книге 1990 года.

Вот как это выглядит на треке, где тональность выражена ясно:

Хромаграмма трека и профиль ми минора

Хромаграмма трека и профиль ми минора

Громче всего звучит ми, тоника. Среди первых и соль, минорная терция. Ля, четвёртая ступень, звучит громче, чем ждёт профиль, поэтому корреляция 0,845, а не 1, и второе место у ля минора.

Так выглядят все 24 оценки для этого трека и для другого, где ответ неочевиден:

Как плеер угадывает тональность трека: 12 чисел и одна корреляция - 3

В первом треке ми минор выигрывает с запасом: 0,845 против 0,703 у второго места. Во втором до минор и соль минор отличаются на сотую. Плеер всё равно напишет «до минор», хотя честнее было бы сказать «где-то между до и соль минором».

Весь алгоритм — около 110 строк на Rust без внешних библиотек, вместе с самописным БПФ. На сервере он считает тональность и темп при сканировании библиотеки. Тот же алгоритм на Kotlin работает на телефоне для локальных файлов.

Где метод ошибается

Параллельные и родственные тональности. У до мажора и ля минора одни и те же семь нот. Различаются они только тем, какие ноты звучат чаще. Если в песне много аккорда ля минор, а заканчивается она в до мажоре, хромаграмма этого не различит: она не знает, какой аккорд был последним.

Соседи по квинтовому кругу. У до мажора и соль мажора шесть общих нот из семи. Отсюда ничья на картинке выше: до минор и соль минор тоже очень близкие соседи.

Модуляции. Хромаграмма по 90 секундам усредняет всё, что в них прозвучало. Если трек сменил тональность, получится смесь. Вот хромаграмма одной песни по 10-секундным кускам:

Хромаграмма по времени и тональность каждого куска

Хромаграмма по времени и тональность каждого куска

Почти каждый кусок даёт свой ответ. Общая корреляция по первым 90 секундам у этого трека всего 0,31 для ля минора и 0,29 для ре мажора. Для такой песни одна тональность — условность, и программа это честно показывает низкими числами. Жаль, что пока только в числах: на экране видна одна строчка.

Лады и хроматика. Профили описывают только классические мажор и минор. Дорийский лад, блюз, музыка, где автор нарочно уходит от тоники, или Прокофьев с его хроматикой подгоняются под ближайшую из 24 тональностей. Это ровно тот случай из комментария. Тональность в названии симфонии — решение композитора о центре всей вещи. Алгоритм же видит только, каких нот в записи больше.

Что звучит, кроме нот. Барабаны, перегруженные гитары и шум добавляют энергию на всех частотах. Обертоны тоже путают: у ноты до третья гармоника звучит как соль. Поэтому я режу диапазон до 80–5000 Гц, но это полумера.

Строй. Если запись настроена не на 440 Гц, а, например, на 432, часть энергии попадает в соседний полутон. Метод это не компенсирует.

А нейросети?

С 2005 года алгоритмы определения тональности ежегодно сравнивают на конкурсе MIREX. Там оценка не просто «угадал или нет»: точное попадание даёт 1 балл, ошибка [2] на квинту 0,5, родственная тональность 0,3, параллельная 0,2. Сами правила говорят, что ошибки в соседние тональности ожидаемы.

Современные системы учат свёрточную нейросеть на спектрограммах, например работа Корженёвского и Видмера 2017 года (arXiv:1706.02921 [3]). Сеть сама учится, какие признаки важны, и меньше путается с ударными и обертонами. Но учат её на разметке людей, а люди размечают глобальную тональность одной меткой. Поэтому вопрос «какая тональность у вещи, которая всё время модулирует» нейросеть не решает: она лучше угадывает ту же метку, которую поставил бы человек.

Я оставил в Nami классический метод: он работает без моделей, быстро и одинаково на сервере и на телефоне. Для подбора треков в микс этого хватает: соседние по кругу квинт тональности хорошо сочетаются, даже если метод ошибся на квинту.

Что из этого следует

  • Тональность от программы — ответ на вопрос «на какую мажорную или минорную гамму больше всего похож набор нот», а не музыкальный анализ.

  • Число корреляции полезнее названия. 0,85 — уверенный ответ. 0,3 — у трека нет одной ясной тональности.

  • Самые частые ошибки — квинта и родственная тональность. Их ждут даже правила конкурса MIREX.

Попробовать

Nami бесплатный, без рекламы и аккаунтов. Про проект целиком я рассказывал в первой статье [8].

Автор: AstolfoOwO

Источник [9]


Сайт-источник BrainTools: https://www.braintools.ru

Путь до страницы источника: https://www.braintools.ru/article/36440

URLs in this post:

[1] слух: http://www.braintools.ru/article/6251

[2] ошибка: http://www.braintools.ru/article/4192

[3] arXiv:1706.02921: https://arxiv.org/abs/1706.02921

[4] nami-music.ru: http://nami-music.ru

[5] скачать APK: https://nami-music.ru/download/

[6] скачать для компьютера: https://nami-music.ru/desktop/

[7] инструкция по установке: https://nami-music.ru/server/

[8] первой статье: https://habr.com/ru/articles/1088018/

[9] Источник: https://habr.com/ru/articles/1089832/?utm_campaign=1089832&utm_source=habrahabr&utm_medium=rss

www.BrainTools.ru

Rambler's Top100