Используйте свертку, чтобы найти эталонный аудио образец в непрерывном потоке звука
В моем предыдущем вопросе о поиске эталонного аудиосэмпла в более крупном аудиосэмпле было предложено использовать свертку.
Используя DSPUtil, я смог это сделать. Я немного поиграл с ним и попробовал различные комбинации аудио-сэмплов, чтобы увидеть, каков был результат. Чтобы визуализировать данные, я просто поместил необработанный звук в виде чисел в Excel и создал диаграмму с использованием этих чисел. Пик виден, но я не знаю, как это мне помогает. У меня есть эти проблемы:
- Я не знаю, как определить начальную позицию матча в исходном аудиосэмпле из местоположения пика.
- Я не знаю, как мне применять это с непрерывным потоком аудио, чтобы я мог реагировать, как только эталонный аудио образец будет получен.
- Я не понимаю, почему изображение 2 и изображение 4 (см. Ниже) так сильно различаются, хотя оба представляют собой аудиосэмпл, свернутый с самим собой...
Любая помощь высоко ценится.
Следующие изображения являются результатом анализа с использованием Excel:
- Более длинный аудиосэмпл с опорным звуком (звуковой сигнал) ближе к концу: http://img801.imageshack.us/img801/976/values1.png
- Звуковой сигнал свернулся сам с собой: http://img96.imageshack.us/img96/6720/values2i.png
- Более длинный аудиосэмпл без звукового сигнала, свернутого со звуковым сигналом: http://img845.imageshack.us/img845/1091/values3.png
- Более длинный аудиосэмпл из пункта 3 свернулся сам с собой: http://img38.imageshack.us/img38/1272/values4.png
ОБНОВЛЕНИЕ и решение:
Благодаря обширной помощи Хана, я смог достичь своей цели.
После того, как я развернул свою медленную реализацию без FFT, я нашел alglib, который обеспечивает быструю реализацию. Есть одно основное предположение к моей проблеме: один из аудиосэмплов полностью заключен в другой.
Таким образом, следующий код возвращает смещение в сэмплах в большем из двух аудиосэмплов и нормализованное значение взаимной корреляции при этом смещении. 1 означает полную корреляцию, 0 означает отсутствие корреляции вообще, а -1 означает полную отрицательную корреляцию:
private void CalcCrossCorrelation(IEnumerable<double> data1,
IEnumerable<double> data2,
out int offset,
out double maximumNormalizedCrossCorrelation)
{
var data1Array = data1.ToArray();
var data2Array = data2.ToArray();
double[] result;
alglib.corrr1d(data1Array, data1Array.Length,
data2Array, data2Array.Length, out result);
var max = double.MinValue;
var index = 0;
var i = 0;
// Find the maximum cross correlation value and its index
foreach (var d in result)
{
if (d > max)
{
index = i;
max = d;
}
++i;
}
// if the index is bigger than the length of the first array, it has to be
// interpreted as a negative index
if (index >= data1Array.Length)
{
index *= -1;
}
var matchingData1 = data1;
var matchingData2 = data2;
var biggerSequenceCount = Math.Max(data1Array.Length, data2Array.Length);
var smallerSequenceCount = Math.Min(data1Array.Length, data2Array.Length);
offset = index;
if (index > 0)
matchingData1 = data1.Skip(offset).Take(smallerSequenceCount).ToList();
else if (index < 0)
{
offset = biggerSequenceCount + smallerSequenceCount + index;
matchingData2 = data2.Skip(offset).Take(smallerSequenceCount).ToList();
matchingData1 = data1.Take(smallerSequenceCount).ToList();
}
var mx = matchingData1.Average();
var my = matchingData2.Average();
var denom1 = Math.Sqrt(matchingData1.Sum(x => (x - mx) * (x - mx)));
var denom2 = Math.Sqrt(matchingData2.Sum(y => (y - my) * (y - my)));
maximumNormalizedCrossCorrelation = max / (denom1 * denom2);
}
BOUNTY:
Новые ответы не требуются! Я учредил награду, чтобы вручить ее Хану за его постоянные усилия по решению этого вопроса!
2 ответа
Здесь мы идем за награду:)
Чтобы найти конкретный опорный сигнал в большем звуковом фрагменте, вам нужно использовать алгоритм взаимной корреляции. Основные формулы можно найти в этой статье Википедии.
Кросс-корреляция - это процесс, с помощью которого сравниваются 2 сигнала. Это делается путем умножения обоих сигналов и суммирования результатов для всех выборок. Затем один из сигналов сдвигается (обычно на 1 выборку), и расчет повторяется. Если вы попытаетесь визуализировать это для очень простых сигналов, таких как один импульс (например, 1 сэмпл имеет определенное значение, а остальные сэмплы равны нулю), или чисто синусоидальной волны, вы увидите, что результат взаимной корреляции действительно мера того, насколько оба сигнала похожи, и задержка между ними. Другая статья, которая может предоставить больше понимания, может быть найдена здесь.
Эта статья Пола Бурка также содержит исходный код для простой реализации во временной области. Обратите внимание, что статья написана для общего сигнала. Аудио обладает тем специальным свойством, что долгосрочное среднее значение обычно равно 0. Это означает, что средние значения, используемые в формуле Пола Буркса (mx и my), могут быть опущены. Существуют также быстрые реализации взаимной корреляции на основе FFT (см. ALGLIB).
(Максимальное) значение корреляции зависит от значений отсчетов в аудиосигналах. Однако в алгоритме Пола Бурка максимум масштабируется до 1,0. В случаях, когда один из сигналов полностью содержится в другом сигнале, максимальное значение достигнет 1. В более общем случае максимум будет ниже, и необходимо будет определить пороговое значение, чтобы решить, достаточно ли похожи сигналы.
Вместо свертки вы должны использовать корреляцию. Размер пика корреляции говорит о том, насколько одинаковы оба сигнала, о положении пика, их относительном положении во времени или о задержке между обоими сигналами.