基于Android乐音识别(2)

549 查看

目录

  1. 傅里叶变换

  2. matlab代码实现&&仿真

  3. 基频提取比对

傅里叶变换

距离上一次更新博客,已经好久了,相信看了我上一篇文章的,现在对我的这篇文章可能比较期待了,这个更新晚的原因一个是由于最近课程比较紧,所以对于乐音识别的研究搁置了一段时间,再就是其中也出现了一些问题,导致我们改变了一下自己的策略。

进入正题,学过高数的同学,对傅里叶变化这个概念应该都不会陌生,但是具体是做什么的呢?知乎上之前看到一篇文章,关于傅里叶变换的,讲的非常详细,附带个地址。傅里叶分析之掐死教程(完整版)对于我们之前的信号,我们的分析都是在时域上的,对于在时域上的信号
只是根据我们的量化程度,对于幅度所采取的一个表示方式,但是对于我们确定它具体是哪一个音阶是无法实现的,所以需要我们对其进行傅里叶变化,将其从时域信号图转化到我们的频域上来,然后根据相关的频域参数来确定我们其具体是属于哪一个音阶。在做傅里叶变化的时候遇到了一个小坑,导致在这上面纠结了很久,一个是因为对于matlab不是很熟悉,再就是本身现在在做的事情就是点歪的一个技能点。通过对声音进行傅里叶变化,我们也可以做一些很有趣的事情,比如根据电话按键的声音对于相应的按键的监听,因为在电话出现时,没有数字信号这回事,所以也就不存在一些数字处理器,所以对于电话的按键,是对于电话按键的声音的模拟信号进行监听来确定的,每一个按键都是由两个不同的频率进行叠加来得到的,所以我们可以对电话的按键音,进行一个切割,将有声段拿出来之后,做一个傅里叶变化得到其中的两个频率,然后和相依的频率表进行一个比对,这也是之前新闻上说的某少年获取周鸿祎手机号的方法。

Matlab的实现和仿真

[y, Fs] = audioread('/Users/chenjensen/Desktop/record.mp3');
plot(abs(fft(y)))

通过audioread来读取我们的音频文件,这里的y是关于音频的数字信号序列,Fs是我们的采样频率,通过利用fft得到如下图

我们之前讲过通过傅里叶变化,我们可以得到这个声音的频率,似乎我们的事情已经结束了,得到一个接近1600的值,这也是之前犯得一个错误,这里提供的声音是我们中音D,其频率523.25,但是这里得到确实这么大,公式也是没有错的,开始这让我怀疑我才去这种提取基频的方式不对,最终被同学发现了错误,就是x轴单位的问题,我们通过fft变化,x轴的最大范围是我们的采样频率,而其每个单位确并不是1,而是我们的采样频率/采样点数,按照这种思路再来做一个计算

z=44100/length(y)

z = 0.3300

通过对原图形进行放大,最后发现该值接近于1590
计算我们的这两个值的乘积:1590*0.3300=524.7000
和我们的原始数据523.25非常接近了,我们通过这个大概可以估计出我们的音阶了。
当然这里还存在的一个疑问是我们得到的一个口琴的音,不可能只是单纯的存在一个频率的,一个声音肯定是由多个音叠加而成的,只是在该音阶,该种频率表达的更为充分,然后我们可以利用这个频率来表示这个音阶,我们要取的频率是其在y轴上的值最大的。同时对于傅里叶的变化我们得到图形是对称的,我们只需要取其前面一部分。

基频提取和比对

通过对于基频的提取和比对,我们可以得到我们的当前的音阶。

该文只是单纯针对傅里叶变化展开,连接上篇文章,我们提取出来有声段之后,就可以对这些有声段进行一个傅里叶变化来获取其频率值,而不是像对其全部进行傅里叶变化。

具体的实现细节,将会在后续文章更新,欢迎各位一起交流提升。

下篇更新Android中java代码的具体实现,项目也会在github开源。