原文链接:Onset Detection Part 5: The (Discrete) Fourier Transform

警告:这是我理解离散傅里叶变换的方法,在一些地方可能是错误的。对于傅里叶变换的正确解释,我建议阅读

http://www.dspguide.com/ch8.htm

(译注:上面的链接我没打开,个人推荐看下面这一篇)

http://www.opticsjournal.net/Mobile/postdetails/PT160728000122iOlRn?code=3&from=singlemessage&isappinstalled=0

最后我们来看看可怕的傅里叶变换。让我们复习一些我们已经知道的东西。首先要记住的是,我们的音频数据是从某种录音设备中获取的,或者是数字合成的。在任何情况下,我们所拥有的是测量离散时间点的振幅,我们称之为样本。我们可以有单声道样本也可以有立体声样本,在后一种情况下,每个时间点有两个样本而不是一个。采样频率是我们每秒测量的采样数(对于立体声,我们将左右通道的采样同时计算为一个)。以下是音符 A (440Hz)的1024个样本,采样频率为44100Hz:

图片来自原文,谁能告诉我咋把水印去了?

注意:左边的垂直线不是实际图像的一部分。是wordpress搞砸了

采样速率为44100Hz的1024个样本的时间跨度为4307ms。从这张图中我们可以看到,这些样本形成了类似于正弦波的东西。事实上,这些样本是使用Math.sin()生成的,就像我们在本系列第一篇文章中所做的那样,它证实了声音只不过是不同频率和振幅的正弦波的混合物。

一个叫傅里叶的聪明数学家曾经提出一个定理,所有可能的函数都可以用一系列所谓的正弦曲线来近似,正弦曲线是具有不同频率和振幅的正弦波(实际上高斯已经知道了这一点,但傅里叶得到了名声)。他为所谓的连续函数做了所有这些魔术你们会在学校的分析课上记得(你们记得分析,对吧?)它被推广到离散函数中,你猜怎么着,我们的样本就是,一个时间上的离散函数。现在,傅里叶变换把一个信号分解成一组不同频率和振幅的正弦信号。如果我们对离散音频信号进行傅里叶变换我们就得到了时域音频信号的频域表示。这个变换是可逆的,所以我们可以这样或那样做。从现在开始,我们只考虑音频信号上的离散傅里叶变换,以免使问题过于复杂。

时域信号的频域告诉我们什么?简单地说,它告诉我们频率对时域信号有多大的影响。频域信号可以告诉我们音频信号中是否有440Hz的音符A以及这个音符相对于整首曲子有多高。这是非常棒的,因为它允许我们调查特定的频率。从上一篇文章的频率图中我们知道各种乐器可以产生不同的频率。如果我们想专注于唱歌我们可以看看频率范围比如80Hz到1000Hz。当然,乐器的频率范围是重叠的,这可能会导致一些问题。但是我们稍后会讲到。

现在,我们用离散傅里叶变换来分析频率。给定一个离散时间信号,例如以特定采样率测量的样本,我们得到一个离散频域。作为一个中间阶段,我们得到了频域的实部和虚部。最后一句中有一些可怕的术语,我们快速过一遍。傅里叶变换将时间信号分解为正弦信号的系数。实部包含特定频率余弦的傅里叶系数(余弦和正弦相等)以及相同频率正弦的傅里叶系数。对于我们的用例来说,这种表示并不那么重要。我们要用的是所谓的频谱它是由原始傅里叶变换的实部和虚部计算出来的。频谱告诉我们每个频率对原始时域音频信号的贡献。从现在开始,我们假设已经计算了这个频谱,这个频谱在框架中是由一个名为FFT(取自Minim)的类来完成的,它可以减轻一些你当下的痛苦。如果你想了解如何从傅里叶变换的实部和虚部转换到频谱,请阅读本篇开始时我提供的链接。

由于变换的离散性,并非所有可能的频率都会出现在频谱中。频率被绑定,也就是说多个频率被合并成一个单独的值。离散傅里叶变换能给出的最大频率也就是奈奎斯特频率。它等于时域信号采样率的一半。假设我们有一个采样频率为44100Hz的音频信号,尼奎斯特频率为22050Hz。当我们把信号转换到频域,我们得到频率箱(frequency bins)高达22050Hz。有多少个这样的箱?样本数的一半加一。当我们对1024个样本进行变换时,我们得到513个频率箱,每个频率箱的带宽(频率范围)为奈奎斯特频率,除以除第一个和最后一个有一半带宽的桶外的桶数。假设我们有1024个样本以44100Hz采样。第一个存储箱将表示0到22050 / 513 / 2~ 21.5Hz的频率(请记住,第一个存储箱只有正常带宽的一半)。下一个方框表示21.5Hz到21.5Hz的频率加上22050 / 513 ~ 43Hz == 64.5Hz(再一次21.5Hz到64.5Hz,带宽为43Hz)。下一个范围是64.5Hz到107.5Hz,以此类推。

当我们对音频数据进行离散傅里叶变换时,我们对样本窗口进行离散傅里叶变换,例如1024个样本是一个常见的窗口大小。窗口的大小决定了得到的频谱的分辨率,即频谱中频率箱的数量将随着我们变换样本的数量线性增加。样本窗口越大,容器的粒度越细,它们的带宽就越小。为了计算频谱,我们使用了一种特殊的算法,称为快速傅里叶变换(FFT),它运行在O(n log n)中,与采用O(n*n)的朴素傅里叶变换相比,它非常快。几乎所有的FFT实现都要求示例窗口的大小为2的整数次幂。256 512 1024 2048可以,273不行。我们在框架中使用的FFT实现也有这个“限制”。

因此,无需赘言,我将向您展示上图中描述的样本的光谱

注意:左右的垂直线不是实际图像的一部分。是wordpress搞砸了

是的,就是这样。x轴表示频率箱,y轴表示频率箱的振幅。我们清楚地看到在左边的一个peek,其余的频谱是零。这个峰值对应于包含频率440Hz的频率库,我们为其中的音符A生成1024个样本。我们还看到它不是一个干净的峰值,左边和右边的箱子也接收到一些振幅。这叫做泄漏,是我们无法解决的问题。在我们的例子中,这不是一个大问题,但在其他应用程序场景中,它可能是一个大问题。下面是生成上述两幅图像的程序:

public class FourierTransformPlot
{public static void main( String[] argv ){final float frequency = 440; // Note A       float increment = (float)(2*Math.PI) * frequency / 44100;      float angle = 0;       float samples[] = new float[1024];      for( int i = 0; i < samples.length; i++ ){samples[i] = ((float)Math.sin( angle ));angle += increment;         }FFT fft = new FFT( 1024, 44100 );fft.forward( samples );Plot plotSamples = new Plot( "Samples", 512, 512 );plotSamples.plot( samples, 2, Color.white );Plot plotSpectrum = new Plot( "Spectrum", 512, 512);plotSpectrum.plot(fft.getSpectrum(), 1, Color.white );}
}

头几行应该很熟悉,我们只是以44000Hz的采样率生成1024个样本。实际上这个程序中只有两行有趣的代码。第一个是实例化FFT对象的地方。构造函数需要两个参数,我们用来生成频谱的采样率 和样本窗口大小。下一行执行傅里叶变换和频谱计算。我们所要做的就是传入一个浮点数组,其中包含的样本大小与我们在FFT构造函数中指定的大小相同。这就是我们需要做的来得到我们宝贵的频率箱。剩下的是绘制样本和光谱。注意对fft.getSpectrum()的调用。这个方法将返回我们调用FFT.forward()所做的上一个傅里叶变换的频谱。

哎呀,那太恶心了。我建议大家多读一下离散傅里叶变换。它是所有音频工程师必备的数学工具。虽然大多数音频工程师会像我们一样使用工具箱,但熟悉周围的环境并没有坏处。

现在我们已经装备好了所有我们需要的东西来启动我们的起点/节奏检测器。请继续关注下一篇文章。

音符起始点检测(音频节奏检测)(5)相关推荐

  1. 音符起始点检测(音频节奏检测)(1)

    原文链接:Onset Detection Part 1: The Basics 在这篇文章中,我想开始一个小的循序渐进的系列,它将允许您为您的音乐游戏需求构建自己的起始点检测器(onset detec ...

  2. 音频节奏检测(Onset Detection)

    项目代码下载 https://download.csdn.net/download/weixin_43865690/39129840 1. 前言 最近市场上出现一些多个视频拼接而成MV,其原理是根据音 ...

  3. 音符起始点检测(音频节奏检测)(6)

    原文链接:Onset Detection Part 6: Onsets & Spectral Flux 在之前的一篇文章中,我从科学的角度讨论了起点/节拍检测.有很多不同的方案可以不同程度的做 ...

  4. 音符起始点检测(音频节奏检测)(4.5)

    原文链接:Onset Detection Part 4.5: What to expect (这篇文章没大翻译明白,建议阅读原文.大概内容就是在展示自制检测器对各种类型音乐的检测效果,以及和 audi ...

  5. 音符起始点检测(音频节奏检测)(2)

    原文链接:Onset Detection Part 2: A simple framework 好了,我刚刚为我们的起始点检测入门教程组合了一个简单的框架.它位于 http://code.google ...

  6. 音符起始点检测(音频节奏检测)(7)

    原文链接:Onset Detection Part 7: Thresholding & Peak picking 在上一篇文章中,我们看到了如何将一个随着时间的推移而演化为一个简单一维函数的复 ...

  7. python 声音强度检测_python检测音频中的静音

    #-*- coding: utf-8 -*- importosimportwavefrom time importsleepimportnumpy as np SUCCESS=0 FAIL= 1 #需 ...

  8. 音频算法检测发言者方位

    音频算法检测发言者方位:

  9. java mp3静音检测,音频自动增益 与 静音检测 算法 附完整C代码

    前面分享过一个算法<音频增益响度分析 ReplayGain 附完整C代码示例> 主要用于评估一定长度音频的音量强度, 而分析之后,很多类似的需求,肯定是做音频增益,提高音量诸如此类做法. ...

最新文章

  1. win7系统电脑语言栏怎么更换输入法
  2. 狗狗手机壁纸|爱宠必备
  3. EL表达式、 jstl标签
  4. 【note】Java程序设计基础第五版(上)
  5. [学习笔记-SLAM篇]视觉SLAM十四讲ch3
  6. JS格式化JSON,JSON着色
  7. 做国内最好的考勤软件,领航软件被评为2007中国软件创新100家典型企业
  8. android自定义秒表,Android实现的秒表计时器示例
  9. 栅格布局一般怎么用_Bootstrap每天必学之栅格系统(布局)
  10. 关于Altium AD20出现的Net NetU2_26 contains floating input pins (Pin U2-26)Net NetU2_26 has only one pin
  11. D45_摄像机组件Camera
  12. Bing必应(Yahoo雅虎)搜索引擎登录网站 - Blog透视镜
  13. Make WeChat Great Again
  14. 《刻意学习》读后感心得体会3000字左右
  15. Microsoft Visual Studio 2015 Installer Projects 打包 安装 部署
  16. elementui表格数据过滤
  17. 刚毕业萌新分享工作规划和面试经历
  18. 机器人指挥交通作文看图说话_交通机器人作文600字
  19. python hack js_Hack Python 整数对象
  20. Chrome 66 ES6模块测试

热门文章

  1. 七:Shell脚本:正则表达式与文本处理器三剑客grep,egrep, sed,awk
  2. hive获取近12个月数据
  3. 使用Python发送邮件(QQ邮箱为例)
  4. 基于MATLAB对低照度图像进行直方图均衡化和同态滤波操作
  5. 闫令琪:Games101 现代计算机图形学-光线追踪(三):渲染方程和路径追踪path ray tracing 作业Assignment07解析
  6. 世界上最顶尖的技术都在哪些国家?
  7. 2023springboot计算机毕业设计选题推荐、springboot计算机毕业设计题目大全
  8. [2011JMP]Some Serrin-type regularity criteria for weak solutions to the Navier-Stokes equations
  9. Facemark:使用OpenCV进行面部特征点检测
  10. 软件对硬盘性能测试,硬盘性能检测详细图文教程