определить количество пиков в аудиозаписи

12

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

Вот то, что я попробовал с файлом моего разговора на английском языке (мой фактический случай использования на кисуахили). Стенограмма записи этого примера: «Я пытаюсь использовать функцию таймера. Я смотрю на паузы, вокализации». Всего в этом отрывке 22 слога.

WAV-файл: https://www.dropbox.com/s/koqyfeaqge8t9iw/test.wav?dl=0

seewaveПакет в R велик, и есть несколько потенциальных функций. Перво-наперво, импортируйте файл волны.

library(seewave)
library(tuneR)
w <- readWave("YOURPATHHERE/test.wav")  
w
# Wave Object
# Number of Samples:      278528
# Duration (seconds):     6.32
# Samplingrate (Hertz):   44100
# Channels (Mono/Stereo): Stereo
# PCM (integer format):   TRUE
# Bit (8/16/24/32/64):    16

Первое, что я попробовал, была timer()функция. Одна из вещей, которую он возвращает, - это продолжительность каждой вокализации. Эта функция идентифицирует 7 вокализаций, что намного меньше 22 слогов. Быстрый взгляд на сюжет показывает, что вокализации не равны слогам.

t <- timer(w, threshold=2, msmooth=c(400,90), dmin=0.1)
length(t$s)
# [1] 7

введите описание изображения здесь

Я также попробовал функцию fpeaks без установки порога. Вернулось 54 пика.

ms <- meanspec(w)
peaks <- fpeaks(ms)

введите описание изображения здесь

Это отображает амплитуду по частоте, а не по времени. Добавление порогового параметра, равного 0,005, отфильтровывает шум и уменьшает счет до 23 пиков, что довольно близко к фактическому количеству слогов (22).

введите описание изображения здесь

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

Эрик Грин
источник
2
Это очень интересный вопрос, но вы можете получить лучшую помощь по методам на сайте вопросов и ответов Stack Exchange .
eipi10
хорошо спасибо. проверим, если никто не ответит. очень признателен.
Эрик Грин
Просто идея, но стоит ли подумать о проведении анализа изменений ? Анализ может быть легко предпринят в R с использованием changepointпакета. Проще говоря, анализ точек изменения фокусируется на обнаружении изменений, связанный пример касается торговых данных, но было бы интересно применить эту технику к звуковым данным.
Конрад
Я собираюсь принять ответ, который набрал наибольшее количество голосов, и это моя попытка реализовать другую идею CV. Я думаю, что основной вопрос остается, однако: как использовать особенности записей, чтобы точно определить количество пиков, которое соответствует количеству произносимых слогов. Спасибо за все идеи. Я отправлю сюда, когда у меня будет решение.
Эрик Грин

Ответы:

5

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

Общий подход состоит в том, чтобы сгладить данные и затем найти пики, сравнивая локальный максимальный фильтр с сглаживанием.

Первым шагом является создание argmaxфункции:

argmax <- function(x, y, w=1, ...) {
  require(zoo)
  n <- length(y)
  y.smooth <- loess(y ~ x, ...)$fitted
  y.max <- rollapply(zoo(y.smooth), 2*w+1, max, align="center")
  delta <- y.max - y.smooth[-c(1:w, n+1-1:w)]
  i.max <- which(delta <= 0) + w
  list(x=x[i.max], i=i.max, y.hat=y.smooth)
}

Его возвращаемое значение включает аргументы локальных максимумов (x) - которые отвечают на вопрос - и индексы в массивы x и y, где встречаются эти локальные максимумы (i).

Я внес небольшие изменения в testфункцию построения графиков: (а) для явного определения x и y и (b) для отображения количества пиков:

test <- function(x, y, w, span) {
  peaks <- argmax(x, y, w=w, span=span)

  plot(x, y, cex=0.75, col="Gray", main=paste("w = ", w, ", span = ", 
                                              span, ", peaks = ", 
                                              length(peaks$x), sep=""))
  lines(x, peaks$y.hat,  lwd=2) #$
  y.min <- min(y)
  sapply(peaks$i, function(i) lines(c(x[i],x[i]), c(y.min, peaks$y.hat[i]),
                                    col="Red", lty=2))
  points(x[peaks$i], peaks$y.hat[peaks$i], col="Red", pch=19, cex=1.25)
}

Как и fpeaksподход, о котором я упоминал в своем первоначальном вопросе, этот подход также требует значительных настроек. Я не буду знать «правильный» ответ (т. Е. Количество слогов / пиков), поэтому я не уверен, как определить правило принятия решения.

par(mfrow=c(3,1))
test(ms[,1], ms[,2], 2, 0.01)
test(ms[,1], ms[,2], 2, 0.045)
test(ms[,1], ms[,2], 2, 0.05)

введите описание изображения здесь

На данный момент fpeaksмне кажется немного менее сложным, но все же не удовлетворяющим.

Эрик Грин
источник
Это может быть неудовлетворительным, потому что ваши параметры лесса не обеспечивают достаточного сглаживания. Выбор более гладкого должен основываться на характере данных и целях; это не то, что можно оставить на усмотрение вычислительной платформы и значений по умолчанию, которые она предоставляет.
whuber
Это не значения по умолчанию. Просто примеры. Я озадачен более сложной проблемой неконтролируемого обучения в этом случае. Я не знаю, сколько слогов в записях, поэтому я не уверен, как настроить пакет файлов. Постоянные параметры, вероятно, не имеют смысла, но я не уверен, как установить некоторые другие правила принятия решений (например, другие метрики волны, которые можно использовать для определения оптимальных значений для этих параметров). Я думаю, что мне нужно создать тренировочный набор, который поможет некоторому алгоритму установить эти параметры. Не уверен, хотя.
Эрик Грин
В вашей команде to loessя не вижу аргументов, явно приведенных для степени сглаживания. На самом деле, нет смысла бегать по лессу через движущееся окно: оно уже делает это внутри.
whuber
Я понимаю вашу точку зрения. Я предположил, что это wбыл аргумент в сглаживании. Вот как автор оригинального решения описал функцию: «Есть два параметра, которые должны быть настроены в зависимости от обстоятельств: w - это полуширина окна, используемого для вычисления локального максимума ... Другой - в данном случае не явный code - это аргумент span сглаживания лесса ".
Эрик Грин
Этот автор включил в wкачестве одного из параметров, потому что он имел в виду очень общий подход, при котором сглаживатель может не быть лессом, но, возможно, будет оконным медианой, или Хеннингом, или чем-то еще, что считается подходящим для статистического поведения данных и Задачи аналитика. Свойства многих из этих сглаживателей будут зависеть от ширины окна.
whuber
1

У меня были похожие проблемы при анализе профилей электрофореза белка. Я решил их, применив некоторые функции пакета msprocess R ко вторым производным профилей (см. Https://fr.wikipedia.org/wiki/D%C3%A9pouillement_d 'une_courbe # Position_et_hauteur_du_pic). Это было опубликовано здесь: http://onlinelibrary.wiley.com/doi/10.1111/1755-0998.12389/abstract;jsessionid=8EE0B64238728C0979FF71C576884771.f02t03

Я понятия не имею, может ли подобное решение работать на вас. Удачи

user17493.bis
источник
спасибо, @ user17493.bis. Слава вам за публикацию с дополнительным материалом. мне будет намного легче попробовать эту идею!
Эрик Грин
0

Вот библиотека на Python, которую я использовал ранее, пытаясь оценить периодичность путем нахождения пиков в функции автокорреляции.

Он использует разности первого порядка / дискретные производные для обнаружения пиков и поддерживает настройку по пороговым параметрам и параметрам минимального расстояния (между последовательными пиками). Можно также улучшить разрешение пика, используя гауссову оценку плотности и интерполяцию (см. Ссылку).

Он работал довольно хорошо для меня без особых настроек, даже для шумных данных. Попробуйте.

tool.ish
источник
Спасибо, @ tool.ish. Это похоже на хорошую альтернативу методам R, которые я цитировал. Однако я думаю, что у меня все еще есть проблемы с настройкой.
Эрик Грин,
0

Я хотел бы предложить решение с использованием changepointпакета. В приведенном ниже упрощенном примере делается попытка идентифицировать пики, определенные здесь как точки изменения, путем просмотра одного канала из доступных данных.

пример

Источник данных

# Libs
library(seewave)
library(tuneR)

# Download
tmpWav <- tempfile(fileext = ".wav")
download.file(url = "https://www.dropbox.com/s/koqyfeaqge8t9iw/test.wav?dl=0",
              destfile = tmpWav)

# Read
w <- readWave(filename = tmpWav)

Подготовка данных

# Libs
require(changepoint)

# Create time series data for one channel as an example
leftTS <- ts(data = w@left)

## Preview
plot.ts(leftTS)

Диаграмма, сгенерированная посредством plot.tsзвонка: Канал как временной ряд

Анализ изменений

changepointПакет предоставляет ряд опции для идентификации изменения / пиков в данных. Приведенный ниже код предоставляет только простой пример поиска 3 пиков с помощью метода BinSeg :

# BinSeg method (example)
leftTSpelt <- cpt.var(data = leftTS, method = "BinSeg", penalty = "BIC", Q = 3)
## Preview
plot(leftTSpelt, cpt.width = 3)

Полученный график: Некоторые точки изменения Также возможно получить значения:

cpts(leftTSpelt)
[1]  89582 165572 181053

Примечания стороны

Приведенный пример в основном касается иллюстрации того, как анализ точек изменения может быть применен к предоставленным данным; следует соблюдать осторожность в отношении параметров, передаваемых в cp.varфункцию. Подробное описание пакета и доступных функций приведено в следующей статье:

Killick, Rebecca and Eckley, Idris (2014) точка изменения: пакет R для анализа точек изменения. Журнал статистического программного обеспечения, 58 (3). С. 1-19.

ecp

ecpСтоит отметить еще один пакет R. ecpОблегчает предприятие непараметрический многомерный анализ точки изменения, которые могут быть полезны , если хотелось бы , чтобы идентифицировать точки изменения , происходящие по нескольким каналам.

Konrad
источник
Спасибо, @konrad. Я не знал ни об одном пакете, так что спасибо, что нашли время для демонстрации. Я думаю, что основная проблема, которую я испытываю со всеми этими пакетами, заключается в том, что я не знаю, сколько пиков искать, поэтому я не уверен, как настроить параметры. Это все еще похоже на ситуацию, когда я должен использовать некоторый алгоритм, чтобы определить, как установить параметры, чтобы точно определить правильное количество пиков (т. Е. Слогов).
Эрик Грин
@EricGreen В принципе, анализ точек изменения позволит вам определить свои пики, просто взглянув на распределение. Это будет вопрос применения подходящего метода, штрафов и так далее. Я бы посоветовал вам взглянуть на сайт, указанный в моем предыдущем комментарии, так как он подробно описывает процесс.
Конрад
Я не уверен, что вы в буквальном смысле имеете в виду, как распределить. У меня 2000 файлов, и мне нужен способ автоматизировать это. Даже если бы я мог просмотреть каждый файл, мне трудно увидеть количество слогов в виде пиков. Может быть, я плотный, и я приду, чтобы увидеть преимущества этого подхода. Я все еще застрял на необходимости способа автоматической настройки параметров каждого файла, чтобы полученное число обнаруженных пиков было точным показателем количества слогов.
Эрик Грин,
@EricGreen Нет, не литературно, конечно. Если вы определитесь с соответствующими параметрами, которые следует передать одной из функций cpt, вы сможете запустить ее для любого количества объектов. Поскольку у меня нет опыта в лингвистике, я не знаю, соответствуют ли слоги обычным пикам, наблюдаемым в данных временных рядов.
Конрад
Попался. Я думаю, что я наткнулся на шаг «выяснить соответствующие параметры» для этого конкретного случая использования. Но я оценил все идеи и узнал о нескольких новых пакетах, которые могли бы стать хорошей альтернативой тем, которые я пробовал.
Эрик Грин,