因此,我试图制作一种针对澳大利亚鸟类的鸟类沙扎姆(因为我在这里没有看到)。请不要告诉我这对真实的音频样本不起作用,我很清楚这一点,我这么做只是为了好玩和学习更多的编码:)
到目前为止,我已经得到了这个代码(我承认我从互联网上偷了很多代码):
def hash_file(filename):
""""This function returns the SHA-1 hash
of the file passed into it"""
# make a hash object
h = hashlib.blake2s()
# open file for reading in binary mode
with open(filename,'rb') as file:
# loop till the end of the file
chunk = 0
while chunk != b'':
# read only 1024 bytes at a time
chunk = file.read(1024)
h.update(chunk)
# return the hex representation of digest
return h.hexdigest()
import os
from pydub import AudioSegment
from pydub.utils import make_chunks
list_of_sounds = {}
directory = r'Bird_Calls'
for filename in os.listdir(directory):
if filename.endswith(".mp3"):
#print(os.path.join(directory, filename))
#print(hash_file(os.path.join(directory,filename)))
hasha=hash_file(os.path.join(directory,filename))
list_of_sounds[hasha] = [filename]
else:
continue
print(list_of_sounds)
import pyaudio
import wave
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100
RECORD_SECONDS = 5
WAVE_OUTPUT_FILENAME = "tmp.mp3"
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("* recording")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("* done recording")
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
recorded=hash_file("tmp.mp3")
if recorded in list_of_sounds:
print(filename)
问题是,当我录制音频时(即使只是播放我知道在数据库中的呼叫,然后只是录制以获取哈希值),哈希值仍然不同。我知道这是由于时间/音频质量/背景噪声等方面的轻微偏移造成的。有没有办法使我的哈希值“更模糊”以增加冲突的可能性?还是我完全走错了路。请不要向我指出dejavu程序的方向,我相信它工作得很好,但我想看看我是否能自己编写这个程序。谢谢
1条答案
按热度按时间sc4hvdpw1#
您已选择blake2s作为哈希函数。这是一个加密散列函数,这意味着它被设计用来对输入的每个字节产生一个非常不同的结果。
对你来说,这意味着:如果你的mp3只差一个字节,那么产生的哈希值就已经大不相同了。
增加碰撞的数量没有帮助。实际上情况正好相反:任何其他文件(即使是文本文件、word文档或类似文件)都会有更高的更改以匹配您的鸟歌。
您需要的是一个专门为音频设计的哈希函数。对于类似shazam的功能,即:
它对计时的要求相对严格,因为我们希望所有播放都具有相同的速度(这可能会因制造公差和温度而有所不同,但可能小于1%)
它必须允许时间转换,因为录制可能迟早会开始
它对频率的要求相对严格,因为它是以特定的频率录制的,我们希望回放会产生类似的结果(如果使用均衡器,并且每个扬声器都有不同的谐振频率,则结果可能会有所不同)
它必须允许振幅变化,因为播放声音可能更大或从更远的地方录制
它必须允许噪音和环境声音
对于鸟类来说,算法变得更加困难,因为
它必须允许时差,因为不是每只鸟都以相同的速度歌唱
它必须允许频率偏移,因为鸟类可能会以不同的频率唱歌,它们没有什么可调的
为了解决图片中显示的一些问题,shazam使用频谱而不是波形,因此您需要的是傅里叶变换(通常是fft,而不是很多DFT)。他们不会做一次,但他们会以小的增量做,所以他们会得到瀑布光谱图,比如
但是他们仍然需要考虑有一个时间偏移(X轴上的位移)和响度的差异(更强烈的颜色)。你还需要考虑两个轴上的位移和拉伸。
也许在光谱图上做一些像图像处理的事情。您可以尝试识别具有当前频率和缺失频率的边缘和区域,如下所示:
这样你可以说这两种声音都包含4个边缘,2个缺失频率区域和4个当前频率区域,并且它们彼此的相对位置是相似的。
这正是你需要的。