Как сопоставить два аудиособытия (определить, похожи ли они) в Python

Для моего проекта я должен определить, похожи ли два аудиофайла и когда первый аудиофайл содержится во втором. Моя проблема в том, что я пытался использовать librosa numpy.correlate. Я не знаю, правильно ли я поступаю. Как я могу определить, содержится ли звук в другом аудиофайле?

import librosa
import numpy
long_audio_series, long_audio_rate = librosa.load("C:\\Users\\Jerry\\Desktop\\long_file.mp3")
short_audio_series, short_audio_rate = librosa.load("C:\\Users\\Jerry\\Desktop\\short_file.mka")

for long_stream_id, long_stream in enumerate(long_audio_series):
    for short_stream_id, short_stream in enumerate(short_audio_series):
        print(numpy.correlate(long_stream, short_stream))

person Jerry Palmiotto    schedule 01.08.2019    source источник
comment
Что за звук в этих событиях? Какова продолжительность типичного события?   -  person Jon Nordby    schedule 02.08.2019
comment
@jonnor 30 минут — это long_audio, а короткое аудио — 1:30 минуты.   -  person Jerry Palmiotto    schedule 02.08.2019


Ответы (1)


Простое сравнение звуковых сигналов long_audio_series и short_audio_series, вероятно, не сработает. Я бы порекомендовал сделать аудиофингерпринтинг, если быть более точным, по сути бедняковую версию того, что делает Shazam. Конечно, есть патент и бумага, но вы можете начать с это очень понятное описание. Вот центральное изображение, карта созвездий (CM), из этой статьи:

Изображение карты созвездий с https://willdrevo.com/fingerprinting-and-audio-recognition-with-python/

Если вы не хотите масштабироваться до очень большого количества песен, вы можете пропустить всю часть хеширования и сосредоточиться на поиске пиков.

Итак, что вам нужно сделать, это:

  1. Создайте спектрограмму мощности (легко с помощью librosa.core.stft ).
  2. Найдите локальные пики во всех ваших файлах (это можно сделать с помощью scipy.ndimage.filters.maximum_filter) для создания CM, т. е. 2D-изображения, содержащие только пики. Результирующий CM обычно является двоичным, то есть содержит 0 для отсутствия пиков и 1 для пиков.
  3. Сдвиньте свой запрос CM (на основе short_audio_series) по каждому из вашей базы данных CM (на основе long_audio_series). Для каждого временного шага подсчитайте, сколько «звезд» (т.е. 1s) выровнено, и сохраните счет вместе со смещением слайда (по сути, положением короткого звука в длинном звуке).
  4. Выберите максимальное количество и верните соответствующий короткий звук и позицию в длинном звуке. Вам нужно будет преобразовать номера кадров обратно в секунды.

Пример для «слайда» (непроверенный образец кода):

import numpy as np

scores = {}
cm_short = ...  # 2d constellation map for the short audio
cm_long = ...   # 2d constellation map for the long audio
# we assume that dim 0 is the time frame
# and dim 1 is the frequency bin
# both CMs contains only 0 or 1
frames_short = cm_short.shape[0]
frames_long = cm_long.shape[0]
for offset in range(frames_long-frames_short):
    cm_long_excerpt = cm_long[offset:offset+frames_short]
    score = np.sum(np.multiply(cm_long_excerpt, cm_short))
    scores[offset] = score
# TODO: find the highest score in "scores" and
# convert its offset back to seconds

Теперь, если ваша база данных велика, это приведет к слишком большому количеству сравнений, и вам также придется реализовать схему хеширования, которая также описана в статье, на которую я ссылался выше.

Обратите внимание, что описанная процедура соответствует только идентичным записям, но допускает шум и небольшие искажения. Если это не то, что вам нужно, уточните сходство, потому что это может быть что угодно (паттерны ударных, последовательность аккордов, инструменты и т. д.). Классический способ, основанный на DSP, для поиска сходства для этих признаков заключается в следующем: извлеките соответствующий признак для коротких кадров (например, 256 выборок), а затем вычислите сходство. Например, если вас интересует гармонический контент, вы можете извлечь векторы цветности. , а затем вычислить расстояние между векторами цветности, например, косинусное расстояние. Когда вы вычисляете сходство каждого кадра в сигнале вашей базы данных с каждым кадром в сигнале запроса, вы получаете что-то похожее на матрица самоподобия (SSM) или матрица повторения (RM). Диагональные линии в SSM/RM обычно указывают на аналогичные участки.

person Hendrik    schedule 02.08.2019
comment
Что вы имеете ввиду под КМ? у меня нет БД - person Jerry Palmiotto; 02.08.2019
comment
CM = карта созвездия - person Hendrik; 02.08.2019
comment
Обычно задача формулируется как обращение к базе данных аудиодокументов с образцом. Если у вас есть только один длинный файл, это ваша база данных. Ваш короткий файл — это ваш запрос. - person Hendrik; 02.08.2019
comment
Как я могу сдвинуть свой CM для соответствия запросу «Извините, я новичок в обработке звука»? - person Jerry Palmiotto; 02.08.2019
comment
Создайте CM для вашего длинного документа и для вашего короткого документа. Используя нарезку numpy, создайте отрывок из длинного документа, который будет таким же длинным, как и ваш короткий документ. Затем просто np.multiply два изображения и np.sum результат. Это ваш счет. Теперь, чтобы прокрутить, выберите другой отрывок из длинного КМ, сдвинутый на один кадр и т. д. - person Hendrik; 02.08.2019
comment
Последний вопрос, как мне CM пики всего с двумя аудиофайлами? - person Jerry Palmiotto; 02.08.2019
comment
Каждый аудиофайл должен быть преобразован в карту созвездия (КМ) — знаете, это просто метафора. На самом деле это просто пики на спектрограмме. - person Hendrik; 02.08.2019