MP3ファイルでビートを見つける


27

この課題では、あなたの仕事は、mp3形式で簡単な録音を行い、ファイル内のビートの時間オフセットを見つけることです。2つの録音例がここにあります。

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

これは、前の2つよりもはるかにノイズの多い3番目の録音です。

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

たとえば、最初の録音の長さは65秒であり、正確に76ビートを含みます(誤算しない限り)。あなたの仕事は、そのようなmp3ファイルを入力として受け取り、ファイル内のビートのミリ秒単位の時間オフセットのシーケンスを出力するプログラムを考案することです。ビートは、もちろん、ギタリストが1つまたは複数の弦を弾くときに発生します。

あなたのソリューションは:

  • 同様の「複雑さ」のmp3ファイルで作業します。ノイズの多い録音や、すぐに演奏されるメロディに失敗する可能性があります-私は気にしません。
  • かなり正確に。許容誤差は+/- 50ミリ秒です。したがって、ビートが1500ミリ秒で発生し、ソリューションが1400を報告する場合、それは受け入れられません。
  • フリーソフトウェアのみを使用してください。ffmpegを呼び出すことは、選択した言語に対応する無料のサードパーティソフトウェアを使用する場合と同様に許可されます。

勝利の基準は、提供されたファイルのノイズにもかかわらず、ビートを正常に検出する能力です。同点の場合、最短のソリューションが優先されます(サードパーティのコードの長さはカウントに追加されません)。


1
これは面白そうに見えますが、これはコンテストです。「正しさ」よりも正確に勝利基準を定義する必要があります。
Fabinout 14年


18
良いコンテストは、関心のある部分を分離します。ここでは、ビートの識別に興味があるようです。これは確かに興味深いDSPの問題です。それでは、なぜプログラムがMP3ファイル形式の複雑さを処理(または外部委託)するのでしょうか?質問は、RAW(サンプルレート、ビット深度、およびエンディアンについて許容される仮定を使用)またはWAV(同様に)のいずれかを取ることで改善されます。
ピーターテイラー14年

3
コンテストのポイントは、これらすべてのピースを処理することです。おそらく、mp3とのやり取りが困難な場合、golfscriptで解決するのが難しくなります。それでもなお、課題は明確に指定されており、(注目)完全に話題になっているため、否定性は非常に落胆します。
ビョルンリンドクヴィスト14年

8
@BjörnLindqvistあなたは心の改善のための提案を取るべきではありません。以前のコメントが削除されていない限り、ここには否定的なコメントは表示されず、改善の提案のみが表示されます。
ガレス14年

回答:


6

Python 2.7 492バイト(beats.mp3のみ)

この答えはビートを特定できますが、またはのbeats.mp3すべてのノートを特定しません。コードの説明の後、理由について詳しく説明します。beats2.mp3noisy-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、これは本当にうまく機能します。このスペクトログラムは、時間(x軸)と周波数(y軸)でのパワーの分布を示しています。私のコードは基本的にy軸を1行にまとめます。 beats.jpeg 視覚的には、ビートがどこにあるかを見るのは本当に簡単です。黄色の線が何度も消えていきます。beats.mp3スペクトログラムをフォローしながら、どのように機能するかを確認することを強くお勧めします。

次に行きますnoisy-beats.mp3(実際、beats2.mp3。より簡単だからです noisy-beats.png。もう一度、録音を続けることができるかどうかを確認してください。ほとんどの行はかすかに見えますが、まだあります。静かな音が始まります。今では、単に振幅ではなく周波数(y軸)の変化によって音を見つける必要があるため、音を見つけるのが特に難しくなります。

beats2.mp3信じられないほど挑戦的です。スペクトログラムbeats2.jpeg は次のとおりです 。最初のビットには、いくつかの行がありますが、いくつかのメモが実際に行を越えています。音を確実に識別するには、音のピッチ(基本波および倍音)の追跡を開始し、それらがどこで変化するかを確認する必要があります。最初のビットが動作すると、2番目のビットはテンポが2倍になります!

基本的に、これらすべてを確実に識別するには、いくつかの派手なノート検出コードが必要だと思います。これは、DSPクラスの誰かにとって良い最終プロジェクトになるようです。


すべての要件を満たしていないため、これは許可されていないと思います。良い答えですが、いくつかの作業が必要です。
Rɪᴋᴇʀ

ええ、私は望んでいたようにこの方法がうまくいかなかったことに少し失望しています。これは、他の誰かがそれを突き刺すのに役立つかもしれないと思います。今週の空き時間があれば、より良い結果が得られる新しいFFTベースのアプローチを試してみたいと思います。
ドミニクA.

さて、クール。いい仕事だ。
Rɪᴋᴇʀ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.