Найти ритмы в файле MP3

27

В этой задаче ваша задача - взять простую запись в формате mp3 и найти временные смещения ударов в файле. Два примера записи здесь:

https://dl.dropboxusercontent.com/u/24197429/beats.mp3 https://dl.dropboxusercontent.com/u/24197429/beats2.mp3

Вот третья запись с гораздо большим шумом, чем две предыдущие:

https://dl.dropboxusercontent.com/u/24197429/noisy-beats.mp3

Например, первая запись длится 65 секунд и содержит ровно (если я не учел!) 76 ударов. Ваша задача - разработать программу, которая принимает такой mp3-файл в качестве входных данных и выводит последовательность временных смещений в миллисекундах ударов в файле. Конечно, ритм должен возникать, когда гитарист играет на одной или нескольких струнах.

Ваше решение должно:

  • Работа над любым mp3 файлом аналогичной «сложности». Он может проигрывать шумные записи или быстро проигрываемые мелодии - мне все равно.
  • Будь довольно точным. Допуск составляет +/- 50 мс. Таким образом, если биение происходит в 1500 мс, а ваше решение сообщает 1400, это недопустимо.
  • Используйте только бесплатное программное обеспечение. Вызов ffmpeg разрешен, как и использование любого свободно доступного программного обеспечения сторонних производителей для вашего языка по вашему выбору.

Критерием победы является способность успешно определять удары, несмотря на шум в прилагаемых файлах. В случае ничьей выигрывает самое короткое решение (длина стороннего кода не учитывается).

Бьорн Линдквист
источник
1
Даже если это выглядит интересно, это соревнование, вы должны определить критерии победы более точно, чем «Правильность».
Fabinout
ок лучше сейчас ??
Бьорн Линдквист
18
Хороший конкурс изолирует интересную часть. Здесь вас интересует идентификация ударов, что, безусловно, является интересной проблемой DSP. Так зачем заставлять программы обрабатывать (или передавать на аутсорсинг) сложности формата файлов MP3? Вопрос мог бы быть улучшен, если взять либо RAW (с допустимыми предположениями о частоте дискретизации, глубине в битах и ​​порядке байтов), либо WAV (аналогично).
Питер Тейлор
3
Суть конкурса заключается в обработке всех этих частей. Возможно, из-за этого трудно решить эту проблему при помощи сценария golfscript, если ему трудно взаимодействовать с mp3. Тем не менее, задача хорошо определена и (на самом деле) полностью по теме, поэтому негативность очень тревожит.
Бьорн Линдквист
8
@ BjörnLindqvist Вы не должны принимать предложения по улучшению для сердца. Если какой-либо предыдущий комментарий не был удален, я не вижу здесь никаких отрицательных комментариев, только предложения по улучшению.
Гарет

Ответы:

6

Python 2.7 492 байта (только beats.mp3)

Этот ответ может идентифицировать удары в beats.mp3, но не идентифицирует все примечания на beats2.mp3или noisy-beats.mp3. После описания моего кода я подробно расскажу, почему.

Это использует PyDub ( https://github.com/jiaaro/pydub ) для чтения в MP3. Вся остальная обработка - это NumPy.

Гольф-код

Принимает один аргумент командной строки с именем файла. Он будет выводить каждый удар в мс на отдельной строке.

import sys
from math import *
from numpy import *
from pydub import AudioSegment
p=square(AudioSegment.from_mp3(sys.argv[1]).set_channels(1).get_array_of_samples())
n=len(p)
t=arange(n)/44.1
h=array([.54-.46*cos(i/477) for i in range(3001)])
p=convolve(p,h, 'same')
d=[p[i]-p[max(0,i-500)] for i in xrange(n)]
e=sort(d)
e=d>e[int(.94*n)]
i=0
while i<n:
 if e[i]:
  u=o=0
  j=i
  while u<2e3:
   u=0 if e[j] else u+1
   #u=(0,u+1)[e[j]]
   o+=e[j]
   j+=1
  if o>500:
   print "%g"%t[argmax(d[i:j])+i]
  i=j
 i+=1

Код без правил

# Import stuff
import sys
from math import *
from numpy import *
from pydub import AudioSegment

# Read in the audio file, convert from stereo to mono
song = AudioSegment.from_mp3(sys.argv[1]).set_channels(1).get_array_of_samples()

# Convert to power by squaring it
signal = square(song)
numSamples = len(signal)

# Create an array with the times stored in ms, instead of samples
times = arange(numSamples)/44.1

# Create a Hamming Window and filter the data with it. This gets rid of a lot of
# high frequency stuff.
h = array([.54-.46*cos(i/477) for i in range(3001)])
signal = convolve(signal,h, 'same') #The same flag gets rid of the time shift from this

# Differentiate the filtered signal to find where the power jumps up.
# To reduce noise from the operation, instead of using the previous sample,
# use the sample 500 samples ago.
diff = [signal[i] - signal[max(0,i-500)] for i in xrange(numSamples)]

# Identify the top 6% of the derivative values as possible beats
ecdf = sort(diff)
exceedsThresh = diff > ecdf[int(.94*numSamples)]

# Actually identify possible peaks
i = 0
while i < numSamples:
 if exceedsThresh[i]:
  underThresh = overThresh = 0
  j=i
  # Keep saving values until 2000 consecutive ones are under the threshold (~50ms)
  while underThresh < 2000:
   underThresh =0 if exceedsThresh[j] else underThresh+1
   overThresh += exceedsThresh[j]
   j += 1
  # If at least 500 of those samples were over the threshold, take the maximum one
  # to be the beat definition
  if overThresh > 500:
   print "%g"%times[argmax(diff[i:j])+i]
  i=j
 i+=1

Почему я скучаю по заметкам на других файлах (и почему они невероятно сложны)

Мой код смотрит на изменения мощности сигнала, чтобы найти заметки. Ибо beats.mp3это работает очень хорошо. Эта спектрограмма показывает, как мощность распределяется по времени (ось х) и частоте (ось у). Мой код в основном сворачивает ось Y до одной строки. beats.jpeg Визуально действительно легко увидеть, где находятся биты. Есть желтая линия, которая сужается снова и снова. Я настоятельно рекомендую вам послушать, beats.mp3пока вы следите за спектрограммой, чтобы увидеть, как она работает.

Далее я перейду к noisy-beats.mp3(потому что это на самом деле проще, чем beats2.mp3. шумный-beats.pngЕще раз, посмотрите, можете ли вы следовать за записью. Большинство строк слабее, но все же есть. Однако в некоторых местах нижняя строка все еще звонит, когда начинаются тихие ноты, что делает их поиск особенно трудным, потому что теперь вы должны найти их по изменению частоты (ось Y), а не только амплитуде.

beats2.mp3невероятно сложно. Вот спектрограмма. beats2.jpeg В первом бите есть несколько строк, но некоторые ноты действительно кровоточат. Чтобы надежно идентифицировать ноты, вы должны начать отслеживать высоту ноты (основной и гармонический) и видеть, где они меняются. Как только первый бит заработает, второй бит будет вдвое сильнее, чем темп удваивается!

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

Доминик А.
источник
Я думаю, что это не разрешено, потому что это не соответствует всем требованиям. Хороший ответ, но для этого нужна работа.
Rɪᴋᴇʀ
Да, я немного разочарован, этот метод не сработал, как я надеялся. Я полагаю, что это может помочь кому-то еще, кто хочет нанести удар. Если у меня будет свободное время на этой неделе, я надеюсь попробовать новый подход, основанный на БПФ, который должен дать лучшие результаты.
Доминик А.
ОК, круто. Хорошая работа, хотя.
R16