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 파일에서 작업하십시오. 시끄러운 녹음이나 멜로디를 빨리 연주하지 못할 수도 있습니다.
  • 상당히 정확해야합니다. 허용 오차는 +/- 50ms입니다. 따라서 비트가 1500ms에서 발생하고 솔루션에서 1400을보고하면 허용되지 않습니다.
  • 무료 소프트웨어 만 사용하십시오. 원하는 언어로 무료로 제공되는 타사 소프트웨어를 사용하는 것처럼 ffmpeg를 호출 할 수 있습니다.

당첨 기준은 제공된 파일의 노이즈에도 불구하고 비트를 성공적으로 감지하는 능력입니다. 동점 인 경우 가장 짧은 솔루션이 승리합니다 (타사 코드의 길이는 계산에 추가되지 않음).


1
이것은 흥미로워 보이지만, 이것은 컨테스트입니다. "수정"보다 더 정확하게 우승 기준을 정의해야합니다.
Fabinout

알았어 이제 좋아?
Björn Lindqvist

18
좋은 콘테스트는 관심있는 부분을 분리시킵니다. 여기서 당신은 비트 식별에 관심이있는 것 같습니다. 이것은 확실히 흥미로운 DSP 문제입니다. 그렇다면 왜 프로그램이 MP3 파일 형식의 복잡성을 처리 (또는 아웃소싱)하게합니까? RAW (샘플 속도, 비트 심도 및 엔디안에 대한 허용 된 가정) 또는 WAV (유사)를 취함으로써 문제가 개선 될 것입니다.
피터 테일러

3
콘테스트의 요점은 모든 조각을 처리하는 것입니다. mp3와의 인터페이스에 어려움을 겪으면 골프 스크립트에서 해결하기가 어려울 수 있습니다. 그보다 적은 것은 아니지만, 그 과제는 잘 구체화되어 있고 (faict) 완전히 토픽이기 때문에 부정성은 매우 실망 스럽습니다.
Björn Lindqvist

8
@ BjörnLindqvist 당신은 마음을 개선하기 위해 제안을해서는 안됩니다. 이전의 의견이 삭제되지 않은 한 여기에는 부정적인 의견이 없으며 개선을위한 제안 만 있습니다.
Gareth

답변:


6

Python 2.7 492 바이트 (beats.mp3 전용)

이 답변은 비트를 식별 할 수 beats.mp3있지만 beats2.mp3또는의 모든 음을 식별하지는 않습니다 noisy-beats.mp3. 내 코드에 대한 설명을 한 후 이유에 대해 자세히 설명하겠습니다.

PyDub ( https://github.com/jiaaro/pydub )를 사용 하여 MP3를 읽습니다. 다른 모든 처리는 NumPy입니다.

골프 코드

파일 이름이있는 단일 명령 행 인수를 사용합니다. 각 비트를 별도의 라인에 ms 단위로 출력합니다.

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

Ungolfed Code

# 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 기반 접근법을 시도하고 싶습니다.
Dominic A.

좋아. 그래도 잘 했어.
Rɪᴋᴇʀ
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.