Автокорреляция кепстра

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


person codeman    schedule 10.03.2014    source источник
comment
Я подумал, что вы хотели сказать «спектр», поэтому решил поискать кепстр — каждый день узнавайте что-то новое!   -  person David K    schedule 11.03.2014


Ответы (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 вы можете вообще не заметить пик по сравнению со случайными факторами повторяемости. Тем не менее, поэкспериментируйте с различными размерами окна, чтобы увидеть, что дает вам наиболее надежные результаты.

person Goz    schedule 15.03.2014
comment
Большое спасибо. Таким образом, inSize будет моим размером буфера (в моем случае 512)? Если моя переменная для звуковых данных, поступающих с микрофона, представляет собой данные с плавающей запятой *, то это будет представлять pInput? - person codeman; 15.03.2014
comment
@codeman: Да, вы правы насчет inSize. Точно. Если это не поплавки, вам нужно преобразовать их в поплавки. - person Goz; 16.03.2014
comment
Спасибо Гоз. Как должен быть определен/распределен pOutput? - person codeman; 17.03.2014
comment
У меня это так: pOutput = (float *) malloc(inSize * sizeof(float)); Но я получаю эту ошибку: malloc: *** ошибка для объекта 0xbbfe404: неверная контрольная сумма для освобожденного объекта - объект, вероятно, был изменен после освобождения. - person codeman; 17.03.2014
comment
Все еще дает мне эту ошибку: malloc: *** ошибка для объекта 0xb356c04: неверная контрольная сумма для освобожденного объекта - объект, вероятно, был изменен после освобождения. - person codeman; 17.03.2014
comment
@codeman: Причина, по которой вы получаете эту ошибку, заключается в том, что вы пишете за пределами malloc. К сожалению, я не могу понять, где возникает такая ошибка... - person Goz; 17.03.2014
comment
давайте продолжим это обсуждение в чате - person codeman; 17.03.2014
comment
Если я закомментирую строку vDSP_conv, я не получу ошибку. - person codeman; 17.03.2014

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

На это уже есть ответы:

Исходный код для vDSP (Accelerate framework) доступен на Github от Kunal Kandekar. Это может быть хорошей отправной точкой.

https://github.com/kunalkandekar/vDSPxcorr

person Legoless    schedule 10.03.2014

Если вы знаете длину задержки эха, вы можете построить гораздо более эффективный фильтр:

https://dsp.stackexchange.com/questions/14951/тривиально-эхо-сепарация

Где вы читаете, чтобы использовать кепстр?

person P i    schedule 23.03.2014