Python 2.7 492 byte (chỉ beats.mp3)
Câu trả lời này có thể xác định các nhịp trong beats.mp3
, nhưng sẽ không xác định tất cả các ghi chú trên beats2.mp3
hoặc noisy-beats.mp3
. Sau phần mô tả mã của tôi, tôi sẽ đi vào chi tiết tại sao.
Điều này sử dụng PyDub ( https://github.com/jiaaro/pydub ) để đọc trong MP3. Tất cả các xử lý khác là NumPy.
Mã đánh gôn
Đưa ra một đối số dòng lệnh với tên tệp. Nó sẽ xuất ra từng nhịp trong ms trên một dòng riêng biệt.
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
Mã bị đánh cắp
# 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
Tại sao tôi bỏ lỡ ghi chú trên các tệp khác (và tại sao chúng rất khó khăn)
Mã của tôi xem xét các thay đổi về công suất tín hiệu để tìm ghi chú. Đối với beats.mp3
, điều này hoạt động thực sự tốt. Biểu đồ phổ này cho thấy công suất được phân phối theo thời gian (trục x) và tần số (trục y). Mã của tôi về cơ bản thu gọn trục y xuống một dòng.
Trực quan, thật dễ dàng để xem nhịp đập ở đâu. Có một đường màu vàng lặp đi lặp lại. Tôi rất khuyến khích bạn lắng nghe beats.mp3
trong khi bạn theo dõi trên phổ để xem nó hoạt động như thế nào.
Tiếp theo tôi sẽ đi đến noisy-beats.mp3
(vì điều đó thực sự dễ dàng hơn beats2.mp3
.
Một lần nữa, hãy xem liệu bạn có thể làm theo cùng với ghi âm hay không. Hầu hết các dòng đều mờ hơn, nhưng vẫn ở đó. Tuy nhiên, ở một số điểm, chuỗi phía dưới vẫn đổ chuông khi các ghi chú yên tĩnh bắt đầu. Điều đó làm cho việc tìm kiếm chúng đặc biệt khó khăn, bởi vì bây giờ, bạn phải tìm thấy chúng bằng cách thay đổi tần số (trục y) thay vì chỉ biên độ.
beats2.mp3
là một thách thức vô cùng. Đây là quang phổ
Trong bit đầu tiên, có một số dòng, nhưng một số ghi chú thực sự chảy qua các dòng. Để xác định một cách đáng tin cậy các ghi chú, bạn phải bắt đầu theo dõi cao độ của các ghi chú (cơ bản và hài hòa) và xem những thay đổi đó. Khi bit thứ nhất hoạt động, bit thứ hai cứng gấp đôi nhịp độ gấp đôi!
Về cơ bản, để xác định một cách đáng tin cậy tất cả những điều này, tôi nghĩ rằng nó cần một số mã phát hiện ghi chú ưa thích. Có vẻ như đây sẽ là một dự án tốt cuối cùng cho một người trong lớp DSP.