БПФ на iPhone, чтобы игнорировать фоновый шум и находить более низкие частоты

Я реализовал проект Деметри Pitch Detector для iPhone и столкнулся с двумя проблемами. 1) любой фоновый шум посылает бананы считывания частоты и 2) звуки более низкой частоты не воспроизводятся правильно. Я попытался настроить свою гитару, и пока работали более высокие струны, тюнер не мог правильно различить низкую E.

Код определения высоты тона находится в RIOInterface.mm и выглядит примерно так ...

// get the data
AudioUnitRender(...);

// convert int16 to float
Convert(...);

// divide the signal into even-odd configuration
vDSP_ctoz((COMPLEX*)outputBuffer, 2, &A, 1, nOver2);

// apply the fft
vDSP_fft_zrip(fftSetup, &A, stride, log2n, FFT_FORWARD);

// convert split real form to split vector
vDSP_ztoc(&A, 1, (COMPLEX *)outputBuffer, 2, nOver2);

Затем Деметри определяет «доминирующую» частоту следующим образом:

float dominantFrequency = 0;
int bin = -1;
for (int i=0; i<n; i+=2) {
    float curFreq = MagnitudeSquared(outputBuffer[i], outputBuffer[i+1]);
    if (curFreq > dominantFrequency) {
        dominantFrequency = curFreq;
        bin = (i+1)/2;
    }
}
memset(outputBuffer, 0, n*sizeof(SInt16));

// Update the UI with our newly acquired frequency value.
[THIS->listener frequencyChangedWithValue:bin*(THIS->sampleRate/bufferCapacity)];

Для начала, я считаю, что мне нужно применить LOW PASS FILTER ... но я не эксперт по БПФ и не знаю, где и как это сделать с данными, возвращаемыми функциями vDSP. Я тоже не уверен, как повысить точность кода на низких частотах. Похоже, существуют и другие алгоритмы для определения доминирующей частоты - но опять же, поиск толчка в правильном направлении при использовании данных, возвращаемых фреймворком Apple Accelerate.

ОБНОВИТЬ:

Фреймворк ускорения на самом деле имеет некоторые оконные функции. Я настраиваю такое базовое окно

windowSize = maxFrames;
transferBuffer = (float*)malloc(sizeof(float)*windowSize);
window = (float*)malloc(sizeof(float)*windowSize);
memset(window, 0, sizeof(float)*windowSize);
vDSP_hann_window(window, windowSize, vDSP_HANN_NORM); 

который я затем применяю, вставляя

vDSP_vmul(outputBuffer, 1, window, 1, transferBuffer, 1, windowSize); 

перед функцией vDSP_ctoz. Затем я изменяю остальную часть кода, чтобы использовать transferBuffer вместо outputBuffer ... но до сих пор не заметил каких-либо кардинальных изменений в окончательном предположении о питче.


person Luther Baker    schedule 24.08.2011    source источник
comment
две вещи, которые я помню по игре с этим материалом несколько лет назад: вы можете установить уровень шумоподавления для фонового звука, просто вычтя необработанные входные данные из заранее определенного количества (о котором вы можете догадываться, пока не придумаете хороший алгоритм), устанавливая все, что ниже 0 до 0. и более низкие частоты, по какой-то причине я не могу вспомнить, не регистрируются громче, чем выше, поэтому вам нужно увеличивать громкость низких частот экспоненциально, прежде чем сравнивать с более высокими преобладающая частота.   -  person jcomeau_ictx    schedule 25.08.2011
comment
Кажется, вы не применяете подходящую оконную функцию до вашего БПФ, поэтому в спектре мощности будет много артефактов, которые, вероятно, испортят любую попытку обнаружения высоты тона.   -  person Paul R    schedule 25.08.2011
comment
Вот почти повторяющийся вопрос с аналогичным ответом: stackoverflow.com/questions/4227420/   -  person hotpaw2    schedule 25.08.2011


Ответы (4)


Шаг - это не то же самое, что пиковая амплитуда частотного бина (что может дать вам напрямую БПФ в структуре Accelerate). Таким образом, любой детектор пиковой частоты не будет надежным для оценки высоты тона. Фильтр нижних частот не поможет, если в ноте отсутствует или очень слабая основная составляющая (обычная для некоторых голосов, звуков фортепиано и гитары) и / или много мощных обертонов в ее спектре.

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

Для более надежной оценки музыкального тона обычно требуются другие методы. Некоторые из них включают методы автокорреляции (AMDF, ASDF), кепстр / кепстральный анализ, спектр гармонического произведения, фазовый вокодер и / или составные алгоритмы, такие как RAPT (надежный алгоритм для отслеживания высоты тона) и YAAPT. БПФ полезно только как часть некоторых из вышеперечисленных методов.

person hotpaw2    schedule 24.08.2011
comment
Спасибо @ hotpaw2. Мне придется углубиться в некоторые из перечисленных вами методов. Спасибо за предложения. - person Luther Baker; 26.08.2011
comment
Ссылки на описания некоторых других методов оценки высоты тона есть в моем блоге: nicholson.com/ rhn / dsp.html # 1 - person hotpaw2; 06.12.2015

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

Достаточно простого Hann (также известного как Hanning) окна.

person Paul R    schedule 25.08.2011
comment
Хороший ответ и красивый аватар: D - person some_id; 26.04.2013
comment
Не могу согласиться с этим комментарием. Вам необходимо применить оконный фильтр перед семплированием аналогового сигнала. После сэмплирования (т.е. после записи через микрофон или в виде WAV-формы) вам не нужно ничего фильтровать - если вы не ищете другой эффект. - person Ze Jibe; 28.07.2014
comment
@ZeJibe: возможно, вы запутались между применением оконной функции и использованием фильтр сглаживания? - person Paul R; 28.07.2014
comment
@ZeJibe: Нет проблем - не могли бы вы отменить голосование против? - person Paul R; 29.07.2014

Какая у вас частота дискретизации и размер блока? Low E составляет около 80 Гц, поэтому вам нужно убедиться, что ваш блок захвата достаточно длинный, чтобы захватить много циклов на этой частоте. Это связано с тем, что преобразование Фурье делит частотный спектр на интервалы шириной в несколько Гц каждый. Например, если вы выполняете выборку на частоте 44,1 кГц и имеете выборку из 1024 точек во временной области, каждая ячейка будет иметь ширину 44100/1024 = 43,07 Гц. Таким образом, низкий E будет во втором контейнере. По целому ряду причин (связанных со спектральной утечкой и природой конечных временных блоков), практически говоря, вы должны рассматривать первые 3 или 4 бина данных в результате БПФ с крайним подозрением.

Если вы снизите частоту дискретизации до 8 кГц, тот же размер блока даст вам интервалы шириной 7,8125 Гц. Теперь низкий E будет в 10-м или 11-м бункере, что намного лучше. Вы также можете использовать более длинный размер блока.

И как указывает Пол Р., вы ДОЛЖНЫ использовать окно, чтобы уменьшить спектральную утечку.

person mtrw    schedule 25.08.2011
comment
Я пробовал как 22050, так и 44100. Я также пробовал размеры блоков 1024, 2048 и 4096 в своего рода кольцевом буфере, который сохраняет данные каждого обратного вызова до тех пор, пока я не получу «размер блока». Я понимаю идею о том, что при фиксированном размере блока более низкая частота дискретизации даст мне немного более широкие интервалы и немного облегчит услышать низкий E. Тюнер начинает читать числа вроде 883 и 901. Очень близко к реальным тонам, кратным 2 и 3. - person Luther Baker; 26.08.2011
comment
Я генерирую тональные сигналы на другом iPhone, на котором сижу. Я заметил, что когда я `` увеличиваю его '', и мой чистый синусоидальный сигнал начинает звучать резким, тюнер теряет правильное значение, которое он отображал, и начинает отклоняться на другие частоты - не обязательно кратные 2 или 3 из основной тон, который я ищу. - person Luther Baker; 26.08.2011
comment
Более длинный размер блока - хорошее начало для любого из оценщиков высоты тона, но пик амплитуды БПФ по-прежнему не будет работать для любого звука с отсутствующей или слабой основной частотой (даже если из-за спада микрофона). - person hotpaw2; 26.08.2011

Функция частотной характеристики iPhone падает ниже 100–200 Гц (см. http://blog.faberacoustical.com/2009/ios/iphone/iphone-microphone-frequency-response-comparison/ в качестве примера).

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

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

person Bill H    schedule 21.08.2012