Использовать свертку, чтобы найти эталонный аудиосэмпл в непрерывном потоке звука

в моем предыдущем вопросе о поиске эталонного аудиосэмпла в более крупном аудиосэмпле было предложено использовать свертку.
Используя DSPUtil , я смог это сделать. Я немного поигрался с ним и попробовал различные комбинации аудиосэмплов, чтобы посмотреть, каков результат. Чтобы визуализировать данные, я просто выгружал необработанный звук в виде чисел в Excel и создал диаграмму, используя эти числа. Пик виден , но я действительно не знаю, как это мне помогает. У меня есть следующие проблемы:

  • Я не знаю, как определить начальную позицию совпадения в исходном аудиосэмпле по местоположению пика.
  • Я не знаю, как мне применить это с непрерывный поток звука, чтобы я мог реагировать, как только появляется эталонный образец звука.
  • Я не понимаю, почему изображение 2 и изображение 4 (см. ниже) так сильно различаются, хотя оба представляют собой образец звука свернутый сам с собой ...

Любая помощь приветствуется.

  • Звуковой сигнал сам с собой:
  • Более длинный аудиосэмпл без звукового сигнала, соединенный с звуковым сигналом:
  • Более длинный аудиосэмпл точки 3 свернулся сам с собой:
  • ОБНОВЛЕНИЕ и решение:
    Благодаря обширной помощи Хана я смог достичь своей цели.
    После того, как я свернул свою собственную медленную реализацию без БПФ, я нашел alglib , который обеспечивает быструю реализацию. У моей проблемы есть одно основное предположение: один из аудиосэмплов полностью содержится в другом.
    Итак, следующий код возвращает смещение в сэмплах в большем из двух аудиоэмплов и нормализованное значение взаимной корреляции с этим смещением. 1 означает полную корреляцию, 0 означает отсутствие корреляции и -1 означает полную отрицательную корреляцию:

    private void CalcCrossCorrelation(IEnumerable data1, 
                                      IEnumerable 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:
    Никаких новых ответов не требуется! Я назначил награду, чтобы вручить награду Хану за его постоянные усилия с этим вопросом!

    9
    задан Glorfindel 10 August 2019 в 11:05
    поделиться