Я пытаюсь обнаружить некоторое эхо в звуке, исходящем от микрофона. Эхо-сигналы будут периодическими и с одним из двух возможных смещений. Я слышал, что мне нужно автокоррелировать кепстр сигнала, чтобы обнаружить присутствие этих эхо-сигналов. Можете ли вы предоставить код с использованием инфраструктуры Accelerate, который показывает, как обнаруживать эхо в аудиоданных?
Автокорреляция кепстра
Ответы (3)
Я не совсем уверен, почему вы автоматически коррелируете кепстр. Однако автокорреляция дает вам представление, связанное с кепстром, поэтому я предполагаю, что вы хотите просто автоматически коррелировать свой сигнал.
В самом простом варианте он выполняется следующим образом:
int sample = 0;
int sampleMax = inSize;
while( sample < sampleMax )
{
vDSP_vsmul( pInput, 1, pInputSample, tempBuffer, 1, sampleMax );
const size_t kAutoCorrWritePos = outSize - sampleMax - sample;
vDSP_vsadd( &pOutput[kAutoCorrWritePos], 1, tempBuffer, 1, &pOutput[kAutoCorrWritePos], 1, sampleMax )
sample++;
}
Однако это очень медленная операция. К счастью, корреляция может быть выполнена несколькими различными способами. Самый быстрый метод - выполнить БПФ, умножить комплексные значения на сопряженные сами по себе, а затем обратное БПФ.
Или в iOS у вас есть хорошо оптимизированный vDSP_conv:
std::vector< float > paddedBuffer( (inSize + inSize) - 1 );
memcpy( &paddedBuffer.front(), pInput, sizeof( float ) * inSize );
vDSP_conv( &paddedBuffer.front(), 1, (float*)pInput, 1, (float*)pOutput + (inSize - 1), 1, inSize, inSize );
// Reflect the auto correlation for the true output.
int posWrite = (inSize - 1);
int posRead = (inSize - 1);
while( posWrite > 0 )
{
posWrite--;
posRead++;
pOutput[posWrite] = pOutput[posRead];
}
Итак, теперь у вас есть автокорреляция, что вы с ней делаете?
Ну, во-первых, прямо посередине у вас будет самая высокая вершина. Это точка нулевого отставания. Затем вам нужно выполнить сканирование справа от этого центрального пика, чтобы идентифицировать вторичные пики. Если вы ищете определенный пик с определенным смещением, вы можете просто проверить количество выборок от центрального пика и проверить, есть ли там пик. Если нет, то сигнала, который вы ищете, нет. Если он есть, то сигнал есть.
Редактировать: стоит отметить, что при ширине окна в 512 выборок, если задержка, которую вы просматриваете, превышает примерно 128, может не хватить сигнала корреляции, чтобы его можно было обнаружить. Корреляция работает, предоставляя пики в точках повторяющихся сигналов в выборочных данных. При лаге 128 у вас достаточно данных, чтобы эта точка повторилась 4 раза. На 256 вы можете увидеть повторение точки только дважды. Это повлияет на высоту корреляционного пика. После 256 вы можете вообще не заметить пик по сравнению со случайными факторами повторяемости. Тем не менее, поэкспериментируйте с различными размерами окна, чтобы увидеть, что дает вам наиболее надежные результаты.
Автокорреляция — это, по сути, взаимная корреляция сигнала с самим собой, которая в основном представляет собой обнаружение сходства в самом сигнале с определенной временной задержкой. Что на самом деле является хорошей идеей для поиска эха в сигнале. Хотя я не могу дать вам наиболее точное и правильное решение, вы сможете написать свое собственное, используя информацию, найденную по ссылкам ниже.
На это уже есть ответы:
- Цель C — Взаимная корреляция для оценки задержки звука
- https://dsp.stackexchange.com/questions/736/how-do-i-implement-cross-correlation-to-prove-two-audio-files-are-similar
- Выполнение автокорреляции с помощью vDSP_conv из Apple Accelerate Framework
Исходный код для vDSP (Accelerate framework) доступен на Github от Kunal Kandekar. Это может быть хорошей отправной точкой.
https://github.com/kunalkandekar/vDSPxcorr
Если вы знаете длину задержки эха, вы можете построить гораздо более эффективный фильтр:
https://dsp.stackexchange.com/questions/14951/тривиально-эхо-сепарация
Где вы читаете, чтобы использовать кепстр?