Автокорреляция возвращает случайные результаты с микрофонным входом (используя фильтр верхних частот)
Извините, что задал вопрос, похожий на тот, который я задавал ранее ( Проблема БПФ (возвращает случайные результаты)), но я просмотрел обнаружение основного тона и автокорреляцию и нашел некоторый код для определения основного тона, используя автокорреляцию.
Я пытаюсь сделать обнаружение высоты тона пения пользователей. Проблема в том, что он возвращает случайные результаты. У меня есть некоторый код с http://code.google.com/p/yaalp/ который я преобразовал в C++ и изменил (ниже). Моя частота дискретизации 2048, а размер данных 1024. Я определяю высоту как синусоидальной волны, так и микрофонного входа. Частота синусоидальной волны равна 726,0, и она обнаруживает 722,950820 (что вполне нормально), но она обнаруживает высоту микрофона как случайное число от 100 до 1050.
Сейчас я использую фильтр верхних частот для удаления смещения постоянного тока, но он не работает. Я делаю это правильно, и если да, что еще я могу сделать, чтобы это исправить? Любая помощь будет принята с благодарностью!
(Исправлена)
Спасибо,
Найл.
Изменить: Изменен код для реализации фильтра верхних частот с частотой среза 30 Гц (из Что такое фильтры верхних и нижних частот ?), Кто-нибудь может сказать мне, как преобразовать фильтр нижних частот с помощью свертки в фильтр верхних частот??) но он все еще возвращает случайные результаты. Подключить его к VST-хосту и использовать VST-плагины для сравнения спектров, к сожалению, для меня не вариант.
Редактировать: Исправлено, спасибо за помощь всем, но я так и не заработал, теперь использую новый код.
4 ответа
Я не эксперт по звуку, но если вы используете сэмплирование с 44100 (я думаю, сэмплов в секунду) и используете 1024 точки данных. Вы работаете с данными на 1/40 секунды. Меня не удивляет, что текущая высота звука сильно варьируется в зависимости от того, какую пьесу вы выберете. Если вы хотите определить среднюю или основную высоту голоса, я бы ожидал, что потребуется около 1 секунды данных.
Проблема в вашей функции findBestCandidates():
Внутри этой функции вы получаете доступ к массиву input от 0 до length - 1. Когда вы вызываете эту функцию внутри функции receivePitchCalculation(), "входы" - это "результаты", а "длина" - это "nHiPeriodInSamples". Но "результаты" только распределяются и заполняются до "nHiPeriodInSamples - nLowPeriodInSamples - 1". Поэтому, если nLowPeriodInSamples больше 0, вы получаете доступ к нераспределенной и случайной памяти внутри функции findBestCandidates()!
РЕДАКТИРОВАТЬ:
Другая ошибка заключается в том, что вы заполняете каждую запись 'nResolution' массива 'results' в функции detectPitchCalculation(), но получаете доступ к каждой записи в функции findBestCandidates() (через аргумент 'input'). Но так как вы вызываете функцию receivePitchCalculation() с 'nResolution=1', это не объясняет вашу конкретную проблему... поэтому я посмотрю немного подробнее. Но это определенно будет проблемой, если вы называете это с более высоким разрешением.
При частоте дискретизации 44,1 кГц, 1024 выборки - это данные с чуть более чем 23 мсек. Разве не возможно, что это просто недостаточно данных, чтобы вычислить высоту человеческого певца?
Я имею в виду, что звук, который я могу издавать и который длится 23 мс, вероятно, не является тем, над чем у меня много контроля высоты звука; Я ожидал бы, что этот вид измерения будет сделан в течение немного более длинных периодов времени.
Я не вижу проблемы в вашем коде, но я не очень хорош в C. Но я бы попробовал следующее, чтобы найти проблему:
- работать с данными, где результат известен, например, с sin(x) в качестве ввода
- запустите его с небольшим размером данных (например, 2)
Сравните результаты с известными правильными. Вы должны быть в состоянии найти их в Интернете или сделать их вручную.
Если случайность означает: один и тот же вход, другой выход, скорее всего, у вас есть ошибка в инициализации переменных. Используйте отладчик и известный ввод, чтобы проверить, что все переменные, особенно все элементы массивов, правильно инициализированы.