Как стать автором
Обновить
0
e-legion
Делаем приложения, которыми пользуются миллионы

Как мы делали Guitar Tuner

Время на прочтение3 мин
Количество просмотров28K
В этом посте мы расскажем о создании нашего бесплатного приложения Guitar Tuner под Android.

image

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

Есть в математике такая замечательная вещь, как преобразование Фурье. Это преобразование даёт частотный спектр аналогового сигнала. То есть любой сигнал можно представить как сумму синусоидальных кривых разной частоты и разной амплитуды.

image

Таким образом, если сигнал сам по себе является синусоидой, то в разложении по частотам у него будет только один член, то есть в сигнале будет присутствовать одна частота. Если сигнал сложный, то и спектр сложный.
tumblr statistics

Музыкальные инструменты играют какую-то определённую ноту и одновременно множество призвуков (обертонов), что значит, что спектр имеет сложную структуру, однако играемая нота (частота) в спектре имеет наибольшую амплитуду. Как правило имеется также некоторое число гармоник в сигнале, то есть частот, кратных основной (удвоенная, утроенная, т.д.).

image

Таким образом, для определения звучащей на гитаре ноты необходимо снять с микрофона телефона звуковой поток, взять от него Фурье-образ, найти частоту с наибольшей амплитудой, провести соответствие частоты и ноты.

Проблемы


На каждом из этапов нас поджидали неприятности. Кроме последнего, разумеется, где таблицы соответствий известны, да и несложно вычислимы из известной частоты 440 Гц для ноты ля 1-ой октавы, а также известного соотношения между частотами одной ноты соседних октав (в 2 раза) и известного количества нот в октаве.

Во-первых, в те давние времена первой версии Android OS, не существовало открытого Java API для работы со звуковым потоком с микрофона. Был API для воспроизведения звука, но не для считывания потока с микрофона. Однако существовал Native-код Speech Recongnition системы, которая работала со снимаемым звуковым потоком. В итоге в качестве хака была написана обёртка для работы с этими Native-потоками. Как потом оказалось, это откликнулось весьма печальными результатами. Но об этом позже.

Следующим этапом было получение Фурье-образа сигнала. Естественно, был использован алгоритм быстрого преобразования Фурье (БПФ). Мы сразу же задумались, что это, как самая вычислительно сложная задача, будет самым узким местом в производительности тюнера. Естественным решением было бы написать эту часть на C, а не на Java, но мы решили сравнить оба решения. Реализовав Cooley–Tukey версию алгоритма БПФ на Java и на C мы провели небольшой benchmark и увидели, что разница во времени была почти на два порядка! Кто выиграл, очевидно. Однако нам удалось улучшить результаты Java версии почти на порядок, заменив работу с комплексными числами как с объектами Complex на простые пары чисел. В итоге результат Java-версии стал достаточно быстрым, и мы решили использовать его, дабы избежать использование лишнего native-кода (в общем-то менее портабельного).

Далее начались самые интересные проблемы. Взглянув на спектральные картинки, мы увидели вовсе не то, чего ожидали. Вместо большой амплитуды основной частоты и сильно меньших амплитуд кратных гармоник, мы увидели едва заметную основную частоту и амплитуды гармоник, подчиняющиеся непонятным нам законам. После долгих попыток понять зависимости, представшие перед нами, в итоге мы свалили всё на Speech Recongnition. Мол, это он выделяет те частоты, которые превалируют в человеческой речи.

Решения


Так как альтернативного источника для чтения потока у нас тогда не было, нужно было как-то выкручиваться. Пришлось отказаться от начальной цели сделать универсальный тюнер, а вместо этого делать тюнер для предзабитых наборов инструментов: шести- и семиструнных гитар, четырёх-, пяти-, шестиструнных бас-гитар и прочего. Иными словами, пользователь тюнера, перед тем как издавать звук на инструменте, сам выбирает ту струну, которую он хочет настроить, а потом только играет. Таким образом, мы уже знаем ту референтную частоту, которую в идеале нужно получить. А зная из спектральной картины сигнала одну из гармоник искомой ноты, мы можем (делением) узнать отклонение реально основной частоты от референтной. Иными словами, частота с максимальной амплитудой в «испорченном» speech recogniser'ом сигнале целочисленно делится на искомую частоту, получается номер гармоники. Далее, делением вычисляется действительно основная частота звучащей ноты, вычисляется разность между искомой и звучащей частотами, нормируется на длину отображаемой шкалы, отображается пользователю.

Позднее появился API для работы с аудио потоком с микрофона, и тюнер был переделан с его использованием, но в данный момент на его поддержку нет
ресурсов, поэтому он находится не в идеальном состоянии. Несмотря на это, им активно пользуются более 50000 Android-пользователей.

Такая вот поучительная история. Надеюсь полученная информация пригодится вам в дальнейшем. С удовольствием отвечу на все вопросы.
Теги:
Хабы:
Всего голосов 100: ↑90 и ↓10+80
Комментарии68

Публикации

Информация

Сайт
www.e-legion.ru
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия

Истории