Знайдіть удари у 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
Сенс конкурсу полягає в обробці всіх цих творів. Можливо, це ускладнює її вирішення в голфскрипті, якщо у нього важко взаємодіяти з mp3-кодом. Незважаючи на це, виклик чітко визначений та (звірний) повністю на тему, тому негатив дуже переживає.
Бьорн Ліндквіст

8
@ BjörnLindqvist Ви не повинні приймати пропозиції щодо вдосконалення. Якщо якийсь попередній коментар не видалено, я не бачу тут жодних негативних коментарів, лише пропозицій щодо вдосконалень.
Гарет

Відповіді:


6

Python 2.7 492 байтів (лише beats.mp3)

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

Для читання у форматі MP3 використовується PyDub ( https://github.com/jiaaro/pydub ). Вся інша обробка - 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це працює дуже добре. Ця спектрограма показує, як розподіляється потужність за часом (вісь x) та частотою (вісь y). Мій код в основному згортає вісь y до одного рядка. beats.jpeg Візуально насправді легко зрозуміти, де б'ються. Є жовта лінія, яка звужується знову і знову. Я настійно рекомендую вам слухати, beats.mp3поки ви стежите за спектрограмою, щоб побачити, як вона працює.

Далі я перейду до цього noisy-beats.mp3(адже це насправді простіше, ніж beats2.mp3. noisy-beats.pngЩе раз перегляньте, чи можете ви продовжувати запис. Більшість рядків слабкіші, але все ж є. Однак у деяких місцях нижня рядок усе ще дзвонить, коли починаються тихі ноти. Це робить їх особливо важкими, тому що тепер ви повинні знайти їх за зміною частоти (вісь y), а не просто амплітудою.

beats2.mp3неймовірно складно. Ось спектрограма beats2.jpeg У першому біті є деякі лінії, але деякі примітки дійсно кровоточать по лініях. Щоб надійно визначити ноти, вам слід почати відстежувати крок нот (фундаментальні та гармонічні) та бачити, де вони змінюються. Як тільки перший біт працює, другий біт удвічі важчий, ніж темп подвоюється!

По суті, для надійної ідентифікації всього цього, я думаю, що потрібен якийсь код виявлення примхливих приміток. Схоже, це було б гарним заключним проектом для когось із класу DSP.


Я думаю, що це не дозволено, оскільки воно не відповідає всім вимогам. Гарна відповідь, але вона потребує певної роботи.
Rɪᴋᴇʀ

Так, я трохи розчарований, що цей метод не вийшов, як я сподівався. Я думаю, що це може допомогти комусь іншому, хто хоче зробити це на удар. Якщо я отримаю трохи вільного часу на цьому тижні, я сподіваюся спробувати новий підхід на основі FFT, який повинен дати кращі результати.
Домінік А.

Гаразд, круто. Хороша робота, хоча.
Rɪᴋᴇʀ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.