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

Обзор

Общая цель этого этапа заключалась в том, чтобы начать согласование звука с текстами песен. Сейчас я ищу построчное выравнивание, то есть строки текстов с Genius.com помечаются меткой времени, обозначающей, когда в песне поется этот текст. Это многоступенчатый процесс:

  • Сначала мы сравниваем самоподобие и разделяем звук на разделы, а затем маркируем эти разделы в зависимости от того, насколько они похожи друг на друга. Таким образом, мы можем легче определить основные структуры, такие как припевы, куплеты и т. Д.
  • Затем мы удаляем звук из фоновых инструментальных композиций, оставляя нам только вокал или как можно ближе к нему.
  • В-третьих, мы подсчитываем количество слогов в каждом разделе песни как в аудио, так и в тексте.
  • Наконец, мы используем эти данные по слогам, а также результаты сегментации, чтобы сопоставить каждый раздел в аудио с каждым разделом в тексте.

Я также добавил модульные тесты и интеграцию с Travis и codecov, но я не буду здесь вдаваться в подробности.

Вокальная изоляция

Поскольку я установил MaD TwinNet в фазе 1, у меня была вокальная изоляция в той степени, в которой мы хотели быть готовы. Однако модели авторов показали себя довольно ужасно во многих песнях, на которых я их тестировал, поэтому я приступил к переобучению модели на наборе данных относительно новых песен в MedleyDB V2, который я запускал на сервере CCExtractor, поскольку он занимал более 10 дней без GPU. Эта новая модель работает лучше, хотя есть некоторые вещи, которые мы можем улучшить:

  • Когда голоса настраиваются автоматически или обычно обрабатываются электронным способом, модель склонна думать, что эти голоса являются инструментами, и отсекает их. Он также склонен думать, что высокие частоты малого барабана и хай-хэта также являются голосами, поэтому оставляет их при себе. Существуют гиперпараметры, используемые для обучения модели, которую я оставил такой же, как бумажная версия; это можно оптимизировать.
  • В общем, в процессе обучения было выполнено более 100 пакетов, что заставляет меня задуматься, не перетренирована ли теперь модель и не соответствует ли она типам треков в MedleyDB. Возможно, более широкий выбор трасс, а также более осознанный тренировочный процесс также улучшат его.

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

Подсчет слогов

У подсчета слогов есть две основные стороны: одна - это определение ядер слогов, или SND, о котором я говорил в моем последнем посте, а другая - подсчет количества слогов в словах в текстах.

В первом случае мы немного продвинулись вперед, изменив параметры, используемые скриптом Praat, особенно подняв порог децибел для того, что шум считается тишиной, с -25 дБ до -15 дБ. Это позволило мне отфильтровать много фоновой музыки, от которой TwinNet не мог избавиться. Я также изменил скрипт, чтобы он возвращал список временных меток, на которые попал каждый слог, а не просто подсчет количества слогов.

В последнем случае пришлось начинать с нуля. Я проверил массу программ расстановки переносов на Github, включая Pyphen и Syllabipy, а также более наивную версию, в которой подсчет слогов основан на некоторых фундаментальных правилах, касающихся гласных и дифтонгов. Все трое неплохо справлялись с общими словами, но им приходилось сопротивляться, как только они встречали незнакомые слова, такие как повестка в суд. В конце концов, я остановился на своей собственной реализации слогового алгоритма по аналогии Маршана и Дампера (SbA), который требует огромных корпусов ранее слоговых слов. К счастью, эти корпуса можно также использовать как словарь, чтобы проверить, есть ли у нас предыдущие данные по силлабификации слова. Текущий механизм подсчета текстовых слогов сначала проверяет массивные наборы данных CMUdict и NETTALK, чтобы узнать, есть ли у нас предыдущие данные, выполняет SbA, если нет, а затем переходит к наивной версии, если SbA терпит неудачу. Затем он добавляет это слово в словарь.

SbA очень успешен и точен в подавляющем большинстве случаев, но, по правде говоря, большинство нужных нам слов уже есть в наших корпусах. Когда используются сокращенные слова, такие как «шакин» или сленг, тогда вступает в дело SbA. Это не очень быстро, но в большинстве песен это не нужно очень часто.

Сегментация / маркировка

Изначально я планировал использовать Spotify API, который может быстро возвращать некоторый анализ звука на дорожке, включая прогнозы относительно того, где, по его мнению, дорожка может быть разделена на разные части. Основная проблема заключалась в том, что не было доступной маркировки, так как Spotify не сообщал нам, какие разделы больше всего похожи друг на друга. Вторая проблема заключается в том, что Spotify не так хорошо умеет разбивать песню на части после прослушивания нескольких сэмплов.

Таким образом, я обратился к MSAF, активно разрабатываемому набору алгоритмов сегментации и маркировки, которые автор либо скомпилировал из своих репозиториев, либо реализовал сам. Проведя несколько тестов, я пришел к выводу, что лучшим алгоритмом сегментации является OLDA, что означает порядковый линейный дискриминантный анализ, а лучшим алгоритмом маркировки является FMC2D, который означает двумерные коэффициенты величины Фурье. Алгоритм маркировки вернет, учитывая набор таймфреймов, возвращенных алгоритмом сегментации, список числовых меток (думаю, 0, 1, 2,…), которые обозначают, какие таймфреймы наиболее похожи друг на друга: сегменты, которые все были помечены как 3, например, будет иметь похожие звуки.

Честно говоря, я не знаю, как именно работают эти алгоритмы, и у меня нет очень строгого способа продемонстрировать, что OLDA и FMC2D на самом деле являются лучшими алгоритмами для этого проекта, но MSAF позволяет легко переключаться между разные алгоритмы для удобного тестирования. На данный момент я остановился на этой паре, и они очень впечатляюще работают для самых разных жанров, на которых я тестировал их и отмечал вручную.

Выравнивание

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

Алгоритм, на который я остановился, был довольно прост: подход DP, предложенный исследователями Gracenote. По сути, мне пришлось бы сегментировать и аудио, и тексты, угадывать, какие разделы были припевами, куплетами и т. Д., А затем просматривать оба списка сегментов, учитывая вероятность того, что наши предположения ранее были правильными или неверными.

Что касается звука, я уже подробно описал MSAF и точность разделения звука на разделы. Что касается текстов песен, к счастью, в Genius есть политика форматирования, в которой используются [скобки] для заголовков каждого раздела словами Припев, Куплет и т. Д., Поэтому мне самому не пришлось выполнять какие-либо действия с этой целью. Тем не менее, некоторые проблемы, с которыми я столкнулся с этим, и эти проблемы, которые мне еще предстоит решить, заключаются в том, что многие менее популярные песни не имеют этих заголовков, поскольку не так много людей заботятся, и даже когда заголовки помечены, они могут быть помечены со странными вещами, такими как Breakdown в Bad Day Дэниела Пауэра. В конце концов, мне придется разработать более надежный синтаксический анализатор текстов Genius.

После определения сегментации остальную часть алгоритма было относительно просто реализовать. Самым сложным было решить, какой лейбл из MSAF присвоить «припев». Я решил использовать двоякую метрику. Во-первых, для каждой метки я генерирую плотность слогов в секунду для каждого раздела аудио с этой меткой, используя временные метки слога из SND. Вместо этого участки с плотностью ≥ 0,7 будут помечены как «инструментальные» и не будут учитываться в процессе выравнивания DP. С помощью этих плотностей я вычислил их стандартное отклонение и, таким образом, насколько схожи части одного лейбла друг с другом на лирическом уровне. Во-вторых, я нормализую количество слогов как для каждого раздела, заданного Genius, так и для каждого раздела в конкретной метке в аудио, и смотрю, на какой метке нормализованное количество слогов ближе всего к фактическому нормализованному количеству слогов в тексте. Таким образом, я могу использовать обе эти метрики, чтобы получить меру евклидова расстояния; метка с наименьшим расстоянием будет обозначена хором.

Результаты

Собирая все вместе, основной конвейер для песни будет выглядеть примерно так:

Я понимаю, что сложно точно объяснить, что происходит, но вы можете проверить код в моем репозитории в autosynch / align.py.

В качестве примера тестового примера, выполненного на примере «Head Full of Doubt / Road Full of Promise» братьев Аветт, мы можем получить следующий результат:

Song: Head Full of Doubt, Road Full of Promise
Artist: The Avett Brothers
Genre: folk
Segmentation/labeling: olda/fmc2d
Section boundaries (sec):
[0.0 - 0.09287981859410431] 
Instrumental
[0.09287981859410431 - 14.675011337868481]
Instrumental
[14.675011337868481 - 35.80517006802721]
Verse 1
[35.80517006802721 - 63.85487528344671]
Verse 2
[63.85487528344671 - 95.66621315192744]
Chorus
[95.66621315192744 - 130.21750566893425]
Verse 3
[130.21750566893425 - 159.79972789115646]
Chorus
[159.79972789115646 - 181.44072562358278]
Instrumental
[181.44072562358278 - 195.2798185941043]
Instrumental
[195.2798185941043 - 201.73496598639457]
Instrumental
[201.73496598639457 - 236.9364172335601]
Chorus
[236.9364172335601 - 248.77859410430838]
Instrumental
[248.77859410430838 - 288.25251700680275]
Outro
Time taken: 168.76940298080444

Я еще не полностью отформатировал вывод, чтобы он выглядел так, но, по сути, это результат выполнения нашего полного процесса над смешанным аудиофайлом этой песни. Если вы послушаете песню на Spotify, вы увидите, что выравнивание здесь почти идеальное, что действительно захватывающе! Как видите, время, затрачиваемое только на процесс выравнивания, составляет примерно 2 минуты 49 секунд; если вы добавите время, затрачиваемое TwinNet, общее количество времени составит около 3 минут при использовании графического процессора (без графического процессора это может занять около 4 минут 40 секунд). Сама песня длится 4 минуты 48 секунд, что многообещающе, поскольку предполагает, что эту задачу можно выполнить почти в реальном времени, если разделить ее на более мелкие партии и, таким образом, применить ее к потоковой передаче Spotify.

Следующие шаги

К сожалению, предстоит еще долгий путь. Хотя эта песня оказалась успешной, на некоторых других песнях, на которых я ее тестировал, например, «God is a woman» Арианы Гранде или «Man of the Year» школьника Q, результаты неясны. Неудовлетворительные результаты в значительной степени являются результатом сочетания проблем из-за того, что TwinNet не разделяет должным образом вокал, чрезмерного подсчета слогов SND, ошибок в сегментации и маркировке, а также плохого форматирования со стороны Genius. Однако все это можно оптимизировать, и одна из моих основных целей на заключительном этапе - оптимизировать все компоненты моего текущего процесса выравнивания на основе сегментации. После того, как этот процесс станет более надежным, я могу перейти к построчному выравниванию, что кажется очень выполнимым. Мои первоначальные мысли заключаются в том, чтобы использовать результаты SND, чтобы грубо разделить каждую секцию на строки, а затем использовать анализ фонем, чтобы выровнять вещи более точно. Посмотрим, как это пойдет!

Соответствующие ссылки

репозиторий автосинхронизации: https://github.com/chriswang030/autosynch/tree/phase2

Веса MaD TwinNet: https://zenodo.org/record/3351632