Подтвердить что ты не робот

Pitch распознавание музыкальных нот на смартфоне

С ограниченными ресурсами, такими как более медленные процессоры, размер кода и оперативная память, как лучше всего определить высоту музыкальной ноты, похожую на то, что сделает электронный или программный тюнер?

Должен ли я использовать:

  • Kiss FFT
  • FFTW
  • Дискретное преобразование вейвлета
  • автокорреляции
  • анализ пересечения нуля
  • фильтры с октавной разметкой

другие?

Вкратце, что я пытаюсь сделать, это признать одну музыкальную ноту, две октавы ниже середины C до двух октав выше, играемую на любом (разумном) инструменте. Я хотел бы быть в пределах 20% от полутона - другими словами, если пользователь играет слишком плоскую или слишком резкую, мне нужно это отличить. Тем не менее, мне не нужна точность, необходимая для настройки.

4b9b3361

Ответ 1

Если вам не нужна такая точность, может быть достаточно БПФ. Window фрагмент аудио сначала, чтобы вы получили четко определенные пики, а затем найдите первый значительный пик.

Ширина бина = частота дискретизации/размер FFT:

Основы диапазон от от 20 Гц до 7 кГц, поэтому будет достаточной частота дискретизации 14 кГц. Следующая "стандартная" частота дискретизации составляет 22050 Гц.

Затем размер FFT определяется требуемой точностью. Выход FFT является линейным по частоте, тогда как музыкальные тона логарифмичны по частоте, поэтому наихудшая точность будет на низких частотах. Для 20% полутона при 20 Гц вам понадобится ширина 1,2 Гц, что означает длину FFT 18545. Следующая мощность двух составляет 2 15= 32768. Это 1,5 секунды данных, и для вычисления моего ноутбука требуется 3 мс.

Это не будет работать с сигналами, которые имеют " отсутствующие основные", и найти "первый значительный" пик несколько сложно ( поскольку гармоники часто выше фундаментальных), но вы можете найти способ, который соответствует вашей ситуации.

Автокорреляция и спектр гармонических продуктов лучше найти истинную фундаментальную для волны вместо одной из гармоник, но я не думают, что они имеют дело с inharmonicity, и большинство инструментов, таких как фортепиано или гитара, являются ангармоничными (гармоники немного отличаются от того, что они должны быть), Однако это зависит от ваших обстоятельств.

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

Я написал несколько разных методов в Python для сравнения.

Ответ 2

Если вы хотите сделать распознавание тона в реальном времени (и с точностью до 1/100 полутона), ваша единственная реальная надежда - это подход с нулевым пересечением. И это слабая надежда, к сожалению. Zero-cross может оценивать шаг только с нескольких длин волн данных, и это может быть сделано с помощью мощности обработки смартфона, но это не особенно точно, поскольку крошечные ошибки в измерении длин волн приводят к большим ошибкам в предполагаемой частоте. Устройства, такие как гитарные синтезаторы (которые выводят шаг из гитарной струны с помощью всего лишь нескольких длин волн), работают путем квантования измерений на нотах шкалы. Это может сработать для ваших целей, но имейте в виду, что пересечение нуля отлично работает с простыми формами сигналов, но имеет тенденцию работать все меньше и меньше с более сложными звуками инструмента.

В моем приложении (программном синтезаторе, который работает на смартфонах) я использую записи отдельных заметок инструмента в качестве сырья для волнообразного синтеза, и для того, чтобы создавать заметки на определенном шаге, мне нужно знать фундаментальный шаг с точностью до 1/1000 полутона (мне действительно нужна только точность 1/100, но я OCD об этом). Для этого подход с нулевым пересечением слишком неоправдан, и подходы, основанные на БПФ, либо слишком неточны, либо слишком медленны (или иногда).

Лучший подход, который я нашел в этом случае, - использовать автокорреляцию. С автокорреляцией вы в основном угадываете шаг, а затем измеряете автокорреляцию своего образца на соответствующей длине волны. Сканируя по диапазону правдоподобных смол (скажем A = 55 Гц через A = 880 Гц) полутонами, я нахожу наиболее коррелированный шаг, затем выполняю более мелкозернистый сканирование в окрестности этого тона, чтобы получить более точное значение.

Самый лучший для вас подход полностью зависит от того, что вы пытаетесь использовать для этого.

Ответ 3

Я не знаком со всеми описанными вами способами, но то, что вы выбираете, должно зависеть в первую очередь от характера ваших входных данных. Вы анализируете чистые тона, или ваш источник ввода имеет несколько заметок? Является ли речь особенностью вашего вклада? Существуют ли какие-либо ограничения на время, затрачиваемое на выбор данных? Можете ли вы скомпрометировать некоторую точность скорости?

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

Autocorrelation сравнивает два сигнала во временной области. Наивная реализация является простой, но относительно дорогостоящей для вычисления, поскольку для этого требуется раздельное различие между всеми точками исходного и сдвинутого по времени сигналов с последующим дифференцированием для определения точек поворота в функции автокорреляции, а затем выбор минимума, соответствующего основная частота. Существуют альтернативные методы. Например, Средняя разница в размерах - очень дешевая форма автокорреляции, но точность страдает. Все методы автокорреляции подвержены риску октавных ошибок, поскольку в функции существуют пики, отличные от фундаментальных.

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

В частотном пространстве методы, основанные на FFT, могут быть достаточно эффективными для ваших целей. Одним из примеров является метод спектра гармонических продуктов, который сравнивает спектр мощности сигнала с версиями с пониженной дискретизацией на каждой гармонике и идентифицирует высоту тона, умножая спектры вместе, чтобы получить четкий пик.

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

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

Ответ 4

В моем проекте danstuner я взял код из Audacity. Он по существу взял БПФ, затем нашел пиковую мощность, положив кубическую кривую на БПФ и набрав пик этой кривой. Работает очень хорошо, хотя мне пришлось защищаться от прыжков в октаву.

См. Spectrum.cpp.

Ответ 5

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

Что-то, с чем я экспериментировал (в качестве проекта на стороне дома):

  • Образец звука с АЦП с любой частотой дискретизации, которая вам нужна.
  • Определить уровни кратковременных положительных и отрицательных пиков формы волны (скользящее окно или подобное). То есть детектор огибающей.
  • Сделайте прямоугольную волну, которая поднимается высоко, когда волновая форма попадает на 90% (или около того) положительной огибающей и становится низкой, когда волновая форма проходит в пределах 90% от отрицательной огибающей. То есть квадратная волна с гистерезисом.
  • Измерьте частоту этой прямоугольной волны с прямым вычислением счета/времени, используя столько образцов, сколько вам нужно, чтобы получить требуемую точность.

Однако я обнаружил, что с входами с моей электронной клавиатуры для некоторых звуков инструментов ему удалось подобрать 2 × базовую частоту (следующая октава). Это был побочный проект, и я никогда не собирался реализовывать решение, прежде чем переходить к другим вещам. Но я думал, что это обещало намного меньше загрузки процессора, чем FFT.