Ударов в минуту от аудио входа в реальном времени - PullRequest
43 голосов
/ 17 сентября 2008

Я бы хотел написать простое приложение на C # для мониторинга линейного звука и давать мне текущие (ну, скользящее среднее) удары в минуту.

Я видел эту статью от gamedev , и это абсолютно не помогло. Я попытался реализовать то, что он делал, но это просто не сработало.

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

Ответы [ 8 ]

26 голосов
/ 17 сентября 2008

Рассчитать powerpectrum с помощью скользящего окна FFT: Взять 1024 образца:

double[] signal = stream.Take(1024);

Подайте его по алгоритму БПФ:

double[] real = new double[signal.Length];
double[] imag = new double[signal.Length);
FFT(signal, out real, out imag);

Вы получите реальную часть и воображаемую часть. НЕ выбрасывайте мнимую часть. Сделайте то же самое с реальной частью воображаемого. Хотя верно, что мнимая часть не совпадает с действительной по пи / 2, она все еще содержит 50% информации о спектре.

EDIT:

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

for (i=0; i < real.Length; i++) real[i] = real[i] * real[i];

Аналогично для мнимой части.

for (i=0; i < imag.Length; i++) imag[i] = imag[i] * imag[i];

Теперь у вас есть спектр мощности для последних 1024 выборок. Где первая часть спектра - это низкие частоты, а последняя часть спектра - это высокие частот.

Если вы хотите найти BPM в популярной музыке, вам, вероятно, стоит сосредоточиться на басе. Вы можете подобрать интенсивность низких частот, суммируя нижнюю часть спектра мощности. Какие цифры использовать, зависит от частоты дискретизации:

double bassIntensity = 0;
for (i=8; i < 96; i++) bassIntensity += real[i];

Теперь сделайте то же самое снова, но переместите окно на 256 выборок, прежде чем вычислять новый спектр. Теперь вам нужно рассчитать bassIntensity для каждых 256 сэмплов.

Это хороший вход для вашего анализа BPM. Когда бас тихий, у вас нет ритма, а когда он громкий, у вас есть ритм.

Удачи!

15 голосов
/ 17 сентября 2008

Есть отличный проект под названием Dancing Monkeys, который процедурно генерирует танцевальные шаги DDR из музыки. Большая часть того, что он делает, основана на (обязательно очень точном) анализе ударов, и в их проектной статье подробно описываются различные алгоритмы обнаружения ударов и их пригодность для данной задачи. Они включают ссылки на оригинальные статьи для каждого из алгоритмов. Они также опубликовали код Matlab для своего решения. Я уверен, что среди них вы можете найти то, что вам нужно.

Это все доступно здесь: http://monket.net/dancing-monkeys-v2/Main_Page

8 голосов
/ 17 сентября 2008

Не то чтобы я имел представление о том, как это реализовать, но с точки зрения звуковой инженерии вам нужно сначала отфильтровать. Хиты басового барабана будут первыми проверять. Фильтр низких частот, который дает вам частоту ниже 200 Гц, должен дать вам довольно четкое представление о басовом барабане. Ворота также могут быть необходимы для очистки любых помех от других инструментов с такими низкими гармониками.

Следующей проверкой будут хитрые удары. Вы должны были бы эквалайзер этого. «Трещина» в ловушке составляет около 1,5 кГц от памяти, но вам, безусловно, нужно будет остановить этот.

Следующая задача - разработать алгоритм для броских ударов. Как бы вы программно нашли ритм 1? Я предполагаю, что вы будете отслеживать предыдущие доли и использовать шаблон, соответствующий чему-то или другому. Итак, вам, вероятно, понадобится несколько тактов, чтобы точно найти ритм. Тогда есть проблемы с синхронизацией, такие как 4/4, 3/4, 6/8, вау, я не могу себе представить, что потребуется, чтобы сделать это точно! Я уверен, что это будет стоить серьезных денег компаниям, занимающимся аудио-аппаратным и программным обеспечением.

6 голосов
/ 17 сентября 2008

Это ни в коем случае не простая проблема. Я постараюсь дать вам только обзор.

Что вы можете сделать, это что-то вроде следующего:

  1. Вычислить среднюю (среднеквадратичную) громкость сигнала по блокам, скажем, 5 миллисекунд. (Никогда раньше этого не делал, я не знаю, какой будет хороший размер блока.)
  2. Возьмите преобразование Фурье «заблокированного» сигнала, используя алгоритм FFT.
  3. Найти компонент в преобразованном сигнале, который имеет наибольшую величину.

Преобразование Фурье - это в основном способ вычисления силы всех частот, присутствующих в сигнале. Если вы сделаете это по «заблокированному» сигналу, то, вероятно, частота удара будет самой сильной.

Может быть, вам сначала нужно применить фильтр, чтобы сосредоточиться на определенных частотах (например, на низких частотах), которые обычно содержат наибольшую информацию о BPM.

5 голосов
/ 27 апреля 2012

Я нашел эту библиотеку, которая, похоже, имеет довольно солидную реализацию для обнаружения ударов в минуту . http://soundtouchdotnet.codeplex.com/

Он основан на http://www.surina.net/soundtouch/index.html, который используется во многих проектах DJ http://www.surina.net/soundtouch/applications.html

1 голос
/ 18 ноября 2010

Прежде всего, то, что производит Халлгрим, не является функцией спектральной плотности мощности. Статистические периодичности в любом сигнале можно определить с помощью функции автокорреляции. Фурье-преобразование автокорреляционного сигнала является спектральной плотностью мощности. Доминирующие пики в PSD, отличные от 0 Гц, будут соответствовать эффективной периодичности сигнала (в Гц) ...

0 голосов
/ 08 марта 2015

Я бы порекомендовал проверить аудиобиблиотеку BASS и оболочку BASS.NET. Он имеет встроенный класс BPMCounter.

Подробности для этой конкретной функции можно найти на http://bass.radio42.com/help/html/0833aa5a-3be9-037c-66f2-9adfd42a8512.htm.

0 голосов
/ 21 марта 2009

Простой способ сделать это - заставить пользователя ритмично нажимать на кнопку и считать количество нажатий, деленное на время.

...