Перейти к содержимому

Тюнер

Играйте на инструменте — тюнер покажет, какая нота звучит и насколько она отличается от точной высоты.

Тюнер

Микрофон выключен

Звук никуда не отправляется. Всё считается прямо в браузере: у проекта нет сервера, отправлять данные некуда. Микрофон выключается по кнопке и при уходе со страницы.

Как пользоваться

Нажмите «Включить микрофон» и разрешите доступ — браузер спросит один раз. Дальше играйте: на экране появится название ноты и отклонение.

Отклонение показано в центах. Цент — сотая доля полутона:

ОтклонениеЧто это значит
до 5 центовслух такого не различает — считайте, что чисто
5–15 центовзаметно внимательному уху
больше 15 центовслышно как фальшь

Цвет показаний меняется по этим же границам, но ориентироваться лучше на цифру: она точнее и не зависит от того, как вы различаете цвета.

Начните с открытых струн. Сыграйте До, Соль, Ре, Ля — тюнер должен назвать именно их. Это заодно проверка, что микрофон работает и слышит инструмент, а не шум комнаты.

Ведите смычок ровно. Тюнер показывает ноту не сразу, а примерно через треть секунды — ждёт, пока звук установится. Это сделано намеренно: в момент атаки звук ещё не имеет определённой высоты, и показывать там можно только неправду. Короткие отрывистые ноты тюнер поэтому не покажет.

Что тюнер делает внутри

Коротко, без формул.

Струна колеблется — туда-сюда, одинаково много раз в секунду. Программа берёт кусочек записанного звука и ищет, через какое время звук повторяет сам себя. Это время и есть период колебания. Зная период, частоту получаем делением, а по частоте находим ближайшую ноту.

Дальше остаётся сравнить: на какой частоте нота должна звучать и на какой звучит на самом деле. Разница и показывается в центах.

Три вещи, которые пришлось учесть:

Виолончель — не синус. В её звуке кроме основного тона есть обертоны, и звук «похож на себя» не только через один период, но и через два, и через три. Если выбирать самое похожее, можно ошибиться в два раза — это дало бы ноту на октаву ниже. Поэтому программа берёт не самое похожее совпадение, а первое подходящее: настоящий период всегда наступает раньше кратных.

Низким нотам нужно время. Струна До колеблется 65 раз в секунду, один период — 15 миллисекунд. Чтобы сравнить звук с самим собой, в кусок должно поместиться несколько периодов. Мы измерили: меньше 40 мс — определить не удаётся, при 30 мс ошибка достигает 35 центов. Программа берёт кусок примерно в 85 мс — с запасом, и задержка при этом незаметна.

Лучше промолчать, чем соврать. В тишине и на шуме любой алгоритм выдаёт какое-то число. Программа оценивает, насколько уверенно определён тон, и при низкой уверенности не показывает ничего.

Чего тюнер пока не умеет

Не учитывает, что струнники играют не по темперации. Тюнер сравнивает с равномерной темперацией — той, по которой настроено фортепиано. Но виолончелист интонирует иначе: ведущий тон берётся чуть выше, в двойных нотах строится чистый интервал. Показания «на 10 центов выше» в таких местах могут быть не ошибкой, а правильной игрой. Как это учесть — открытый вопрос.

Ждёт треть секунды перед первым показанием. Это не задержка из-за медленных вычислений, а осознанное решение.

Пока смычок «схватывает» струну, колебание на основной частоте ещё не установилось. Замер на записях показал: в первые доли секунды основной тон в 30–50 раз слабее второй гармоники, то есть его почти нет. Тюнер в этот момент честно показывал то, что звучит, — ноту октавой выше.

Лечить это в самом алгоритме не получилось: четыре способа были проверены и отвергнуты, все делали хуже. Сработало простое — не показывать ничего, пока звук не установится. Перебор по записям дал точную границу:

Пауза перед показомОшибок на записях
186 мс8
279 мс4
372 мс0

Поэтому тюнер молчит первую треть секунды каждой ноты. После этого на записях открытых струн не остаётся ни одной ошибки — всё, что показано, верно. Ценой примерно 3% показаний, которые скрываются вместе с атакой.

Записи, на которых это измерено, лежат в проекте — можно послушать и проверить самому: До · Соль · Ре · Ля

Разбор запускается командой node tools/analyze-recording.mjs static/audio/cello-d3.m4a — она печатает покадрово, что нашёл детектор в каждый момент.

Что дальше