使用 python 音频处理的音符检测
Posted
技术标签:
【中文标题】使用 python 音频处理的音符检测【英文标题】:Music note detection using python audio processing 【发布时间】:2018-11-14 11:25:34 【问题描述】:我给我的代码提供了一些没有提供适当输出的音频文件。 代码:
import numpy as np
import math
import wave
import os
import struct
def note_detect(audio_file):
Detected_Note = ""
beta = 1
max_notes = 100
sampling_freq = 38050
window_size = (sampling_freq / 37)
threshold = 600
array = [440.00, 130.8, 329.6, 196]
notes = ['A4', 'C3', 'E4', 'G3' ]
Identified_Notes = []
file_length = audio_file.getnframes()
sound = np.zeros(file_length)
for i in range(file_length):
data = audio_file.readframes(1)
data = struct.unpack("<h", data)
sound[i] = int(data[0])
sound = np.divide(sound, float(2**15))
sound_square = np.square(sound)
frequency = []
dft = []
i = 0
j = 0
k = 0
while(i<=len(sound_square)-window_size):
s = 0.0
j = 0
while(j<=window_size):
s = s + sound_square[i+j]
j = j + 1
if s < threshold:
if(i-k>window_size*4):
dft = np.array(dft)
dft = np.fft(sound[k:i])
dft=np.argsort(dft)
if(dft[0]>dft[-1] and dft[1]>dft[-1]):
i_max = dft[-1]
elif(dft[1]>dft[0] and dft[-1]>dft[0]):
i_max = dft[0]
else :
i_max = dft[1]
frequency.append((i_max*sampling_freq)/(i-k))
dft = []
k = i+1
i = i + window_size
print('length',len(frequency))
print("frequency")
for i in frequency :
print(i)
idx = (np.abs(array-i)).argmin()
Identified_Notes.append(notes[idx])
print(Identified_Notes)
Detected_Note=max(Identified_Notes,key=Identified_Notes.count)
return Detected_Note
if __name__ == "__main__":
path = os.getcwd()
file_name = path + "\Task_1.1_Audio_files\Audio_4.wav"
audio_file = wave.open(file_name)
Detected_Note = note_detect(audio_file)
print("\n\tDetected Note = " + str(Detected_Note))
x = raw_input("\n\tWant to check output for all Audio Files - Y/N: ")
if x == 'Y':
Detected_Note_list = []
file_count = len(os.listdir(path + "\Task_1.1_Audio_files"))
for file_number in range(1, file_count):
file_name = path + "\Task_1.1_Audio_files\Audio_"+str(file_number)+".wav"
audio_file = wave.open(file_name)
Detected_Note = note_detect(audio_file)
Detected_Note_list.append(Detected_Note)
print("\n\tDetected Notes = " + str(Detected_Note_list))
音频文件链接: https://drive.google.com/open?id=1KVEQQUqBvwgDPf2JC_uQ0L6M_gzGDG6l
Audio_6.wav 的相应输出为 A4,Audio_4.wav 为 E4,Audio_5.wav 为 G3
【问题讨论】:
嗨,欢迎来到 SO。请查看Help centre。特别是,请在帖子中包含代码并解释您的问题。什么是“适当的输出”?它和你得到的有什么不同?没有人知道,除了你。 欢迎来到 SO ;) 请在 how to ask a good question 阅读这篇文章。这将包括对您要实现的目标的正确描述、您的代码(或相关的 sn-ps)以及显示您迄今为止尝试过的内容和可能的错误消息的努力。 我已经按照你的建议上传了代码。 【参考方案1】:这可能是因为您使用的是自定义矩形窗口,请尝试使用 scipy.signal 中的 blackmanharris 并使用 np.argmax 来计算 i_max。 我检查了音频文件,它们只有 1 个频率,但您从算法中计算出 4 个频率,然后取最高频率。 我已经调整了代码看一下,但Audio_4.wav文件仍然显示我这边的注释E5,这可能是你给的注释可能是错误的,你能检查一下吗?
def matching_freq(freq):
note=""
if(freq>15 and freq<17.32):
note= "C0"
return note
elif(freq>17.32 and freq<19.45):
note="D0"
return note
elif(freq>19.45 and freq<20.8):
note="E0"
return note
elif(freq>20.8 and freq<23.12):
note="F0"
return note
elif(freq>23.12 and freq<25.96):
note="G0"
return note
elif(freq>25.96 and freq<29.14):
note="A0"
return note
elif(freq>29.14 and freq<31):
note="B0"
return note
elif(freq>31 and freq<34.65):
note="C1"
return note
elif(freq>34.65 and freq<38.89):
note="D1"
return note
elif(freq>38.89 and freq<42):
note="E1"
return note
elif(freq>42 and freq<46.25):
note="F1"
return note
elif(freq>46.25 and freq<51.91):
note="G1"
return note
elif(freq>51.91 and freq<58.27):
note="A1"
return note
elif(freq>58.27 and freq<63):
note="B1"
return note
elif(freq>63 and freq<69.30):
note="C2"
return note
elif(freq>69.30 and freq<77.78):
note="D2"
return note
elif(freq>77.78 and freq<85):
note="E2"
return note
elif(freq>85 and freq<92.50):
note="F2"
return note
elif(freq>92.50 and freq<103.83):
note="G2"
return note
elif(freq>103.83 and freq<116.54):
note="A2"
return note
elif(freq>116.54 and freq<126):
note="B2"
return note
elif(freq>126 and freq<138.59):
note="C3"
return note
elif(freq>138.59 and freq<155.56):
note="D3"
return note
elif(freq>155.56 and freq<168):
note="E3"
return note
elif(freq>168 and freq<185):
note="F3"
return note
elif(freq>185 and freq<207.65):
note="G3"
return note
elif(freq>207.65 and freq<233.08):
note="A3"
return note
elif(freq>233.08 and freq<253):
note="B3"
return note
elif(freq>253 and freq<277.18):
note="C4"
return note
elif(freq>277.18 and freq<311.13):
note="D4"
return note
elif(freq>311.13 and freq<338):
note="E4"
return note
elif(freq>338 and freq<369.99):
note="F4"
return note
elif(freq>369.99 and freq<415.3):
note="G4"
return note
elif(freq>415.3 and freq<466.16):
note="A4"
return note
elif(freq>466.16 and freq<500):
note="B4"
return note
elif(freq>500 and freq<554.37):
note="C5"
return note
elif(freq>554.37 and freq<622.25):
note="D5"
return note
elif(freq>622.25 and freq<675):
note="E5"
return note
elif(freq>675 and freq<740):
note="F5"
return note
elif(freq>740 and freq<830):
note="G5"
return note
elif(freq>830 and freq<932):
note="A5"
return note
elif(freq>932 and freq<1000):
note="B5"
return note
elif(freq>1000 and freq<1108):
note="C6"
return note
elif(freq>1108 and freq<1244):
note="D6"
return note
elif(freq>1244 and freq<1350):
note="E6"
return note
elif(freq>1350 and freq<1480):
note="F6"
return note
elif(freq>1480 and freq<1661.22):
note="G6"
return note
elif(freq>1661.22 and freq<1864):
note="A6"
return note
elif(freq>1864 and freq<2000):
note="B6"
return note
elif(freq>2000 and freq<2217.46):
note="C7"
return note
elif(freq>2217.46 and freq<2489.02):
note="D7"
return note
elif(freq>2489.02 and freq<2700):
note="E7"
return note
elif(freq>2700 and freq<2960):
note="F7"
return note
elif(freq>2960 and freq<3322.4):
note="G7"
return note
elif(freq>3322.4 and freq<3729):
note="A7"
return note
elif(freq>3729.31 and freq<4040):
note="B7"
return note
elif(freq>4040 and freq<4435):
note="C8"
return note
elif(freq>4435 and freq<4978):
note="D8"
return note
elif(freq>4978 and freq<5350):
note="E8"
return note
elif(freq>5350 and freq<5919):
note="F8"
return note
elif(freq>5919 and freq<6644):
note="G8"
return note
elif(freq>6644 and freq<7458):
note="A8"
return note
elif(freq>7458 and freq<8000):
note="B8"
return note
def note_detect(audio_file):
Detected_Note = []
length = audio_file.getnframes()
sound = np.zeros(length)
for i in range(length):
data = audio_file.readframes(1)
data = struct.unpack("<h", data)
sound[i] = int(data[0])
sound = np.divide(sound, float(2**15))
window = sound * np.blackmanharris(len(sound))
f = np.fft.fft(window)
i_max = np.argmax(abs(f))
print(i_max)
freq = (i_max * fs)/len(sound)
print(freq)
Detected_Note = matching_freq(freq)
return Detected_Note`
【讨论】:
我已经检查了所有的音频文件,它们给出了我的查询中给出的适当输出。我已经浏览了您的代码,并在名为 Audio_2.wav 的驱动器中添加了一个音频文件,其中包含注释 A4,通过您的代码,我得到了 E7。以上是关于使用 python 音频处理的音符检测的主要内容,如果未能解决你的问题,请参考以下文章
音频处理使用 PolyPhone 软件修正 SoundFont 音源中的不规范音符 ( 设置音符频率校正 )
音频处理Melodyne 选择工具使用 ( 主工具简介 | 修改音高 | 自动吸附 | 音符长度修改 | 长度自动吸附 | 设置音符分离线 | 设置片段分离线 )
音频处理Melodyne 网络缩放功能 ( 音符分离线 | 片段分离线 | 窗口滚动条 | 网格缩放 | 修改图像显示位置 | 显示五线谱 )