2021-08-24 21:41:51
几天前,我写了一篇文章,介绍了以图搜图的原理(以图搜图是怎么回事儿),结尾有这么一句话:
下回咱们介绍下「听歌识曲」是怎么回事儿。
我的天,当时就是为了凑字数随口这么一说。实际上,我根本不知道「听歌识曲」是怎么回事儿,怎么讲?
就这样拖了两个星期,每天都过的很忐忑。今天终于狠下心来,又是Google又是百度,还看了几篇论文,写了几行代码,才敢动笔,不保证讲的深,但求讲个大概。毕竟是自己吹过的牛逼,含着泪也要把它吹完。
听歌识曲和你在百度上搜索一个关键词并没什么区别,最大的难题在于歌曲本身是二进制数据,无法直接拿到后台数据库做对比,所以如何根据判断一个音频和另一个音频是匹配的,是这个问题的关键。「以图搜图」的时候,我们通过对图片进行缩放、灰度处理,最后提取出一个64位的哈希值作为特征码,用它去做匹配。同样,对于歌曲,我们也可以想办法找到这首歌的特征,也就是音乐的指纹,简称乐纹。
找乐纹第一步,就是要把一首歌或者一段录音转换成单声道、低采样率的wav格式。这一步和「以图搜图」先要缩放图片类似,排除其他干扰,但是保留了音乐的整体特征。
前面的文章讲过,音频无非是声卡对声波的采样生成的。我们拿到一个音频文件,很自然的就可以把它的波形图画出来。
波形图上,波的起伏就是我们平时说的音量大小,幅度越大,声音越响量。还有一个信息,就是这样的波越密越拥挤,表示它的变化很快,频率很高,我们会听到声音比较尖锐。所以描述一段音频,一般需要两个东西,一个是响度,另一个是频率。
举个简单的例子,有一段音频,是凤凰传奇的《最炫民族风》,女的频率快,音调比较高,男的音调低。歌曲从前奏到达高潮,响度也会不断提高。
但是真正的音频波形图,并不是这么简单的:
它更像是很多波形图堆叠在一起了。一个音频里,在某个时刻,有人声有伴奏,有男声有女声,这些都是不同频率的,在波形图上却无法分辨出来。所以我们采集音频的乐纹的时候,要把波形图转换成频谱图。频谱图这个专业名词你可能没听过,但你一定见过这个东西。
这张gif里,每一帧表示一个时刻的频谱。横轴是频率,单位是赫兹,纵轴还是声音的响度。假如在《最炫民族风》这个音频里只有两个频率,即男声的低频和女声的高频,那么这张图里就只有两根柱子在蹦跶了。很明显,频谱图既有音调又有音量,我们就可以从中提取乐纹了。当然,如何从波形图得到频谱图呢,中间要经过傅里叶变换,信号与系统的东西,别找我,想想就头疼。
乐纹无非就是最能表现一首歌特征的一些数据,而且一首歌的乐纹不是只有一个,而是可以分成很多片段,每个片段都有自己的乐纹。这里我们的规则是,从每张频谱图里,选取音量最大的几个频率作为特征点,由它们生成这个片段的乐纹。怎么理解呢?在某个小的音频片段里,如果某个频率的音量很大,比如《最炫民族风》里的女声唱到了最高潮的部分,这个点就凸显出来了,而且不容易识别错,所以很适合做特征点。
现在,假设我们的后台服务器上,有几百万首歌曲,每首歌都分成很多片段,也就是有很多乐纹。用户上传了一段录音,经过相同的分析,我们也提取了若干乐纹,如何通过录音的乐纹,去查找最合适的歌曲呢?
换个说法,现在我们的后台服务器上,有几百万个网页,每个网页有很多关键词。用户提交了一句话,我们提取了若干个关键词,如何通过这些关键词,找到最合适的网页呢?
没错,和搜索引擎一样的做法,我们前面讲过倒排索引,你可以去看一下。有一点不同就是,假如一段录音匹配到了两首音乐,也就是说,录音的乐纹,在这两首歌中都有,如何评价谁更相似呢?其实很简单,我们当然希望最佳答案不光能匹配到录音的所有乐纹,而且希望它匹配到的乐纹的先后顺序,时间间隔等等,和录音里是一样的才行。就像下面的图片,虽然音乐1和音乐2里都有录音的乐纹,但是,音乐1的乐纹排列和录音的乐纹排列集合几乎是一模一样的,所以考虑录音是出自音乐1的。
总结一下,听歌识曲,一个是对数据库里的所有音乐提取乐纹。对每一首音乐,先算出它的频谱图,然后把它分成一段一段的,每一段都在频谱图上找几个点作为特征点,几个特征点生成这一片段的乐纹。一首歌通常有很多乐纹,都以倒排索引的形式存到数据库里。上传上来的录音,也是先找所有的乐纹,然后去数据库里检索,最后考虑乐纹的排列,时间等因素,找到最相似的音乐。
下回介绍一下《人脸识别 》是怎么回事儿。
说点题外话,昨天的直播很多朋友都看了,也有不少朋友没看,阅读原文是回放的地址,果果第一次上镜就献给你们了。有人问我为啥突然想到做直播呢,其实很简单,主要是想露个脸,攒攒人气。年底了,冲下KPI,就指望各位多多转发一下了。