最近工作上在做关于音乐游戏的内容,其中需要分析音频找节奏点(或者说是重音点)。

学习了一系列相关知识后,了解到一段音乐的波形图可以分解成不同频率的波形图,也就是由时域到频域的转换。

借用其他博主的图就比较容易理解了,如下所示。

波从时域到频域的转换可以通过傅里叶变换实现,关于傅里叶变换的知识可以从最上面的链接学习或者自行查找(傅里叶真厉害!!!)。

计算机处理的音频在时域上是离散的数据,我们可以使用离散傅里叶变换DFT(傅里叶变换在时域和频域上都呈离散的形式)获得频域上的离散数据。

快速傅立叶变换FFT是DFT的快速算法,其核心思路就是分治法的DFT,具体推导可以查看上面的第二个链接。

FFT 代码如下:

static void BitReverse(Complex[] cpData, intn)

{

Complex temp;int lim = 0;while ((1 << lim) < n) lim++;for (int i = 0; i < n; i++)

{int t = 0;for (int j = 0; j < lim; j++)

{if (((i >> j) & 1) != 0)

t|= (1 << (lim - j - 1));

}if (i

{

temp=cpData[i];

cpData[i]=cpData[t];

cpData[t]=temp;

}//i < t 防止交换两次

}

}static void FFT1(Complex[] cpData, boolforward)

{var n =cpData.Length;

BitReverse(cpData, n);//位反转

Complex[] omg= newComplex[n];for (int i = 0; i < n; i++)

{

omg[i]= new Complex((float)Math.Cos(2 * Math.PI * i / n), (float)Math.Sin(2 * Math.PI * i /n));

}

Complex temp ;for (int step = 2; step <= n; step *= 2)

{int m = step / 2;for (int j = 0; j < n; j +=step)for (int i = 0; i < m; i++)

{//蝶形运算

if(forward)

temp= omg[n / step * i] * cpData[j + i +m];elsetemp= omg[n / step * i].Conjugate() * cpData[j + i +m];

cpData[j+ i + m] = cpData[j + i] -temp;

cpData[j+ i] = cpData[j + i] +temp;

}

}

}

这个FFT,new了好多对象,效率不是很高。。。

再贴一个直接把复数的实部虚部轮流放在一个数组里直接算的,能快一些。

static void Reverse(float[] data, intn)

{int j = 0, k = 0;var top = n / 2;while (true)

{var t = data[j + 2];

data[j+ 2] = data[k +n];

data[k+ n] =t;

t= data[j + 3];

data[j+ 3] = data[k + n + 1];

data[k+ n + 1] =t;if (j >k)

{

t=data[j];

data[j]=data[k];

data[k]=t;

t= data[j + 1];

data[j+ 1] = data[k + 1];

data[k+ 1] =t;

t= data[j + n + 2];

data[j+ n + 2] = data[k + n + 2];

data[k+ n + 2] =t;

t= data[j + n + 3];

data[j+ n + 3] = data[k + n + 3];

data[k+ n + 3] =t;

}

k+= 4;if (k >=n)break;var h =top;while (j >=h)

{

j-=h;

h/= 2;

}

j+=h;

}

}static void FFT2(float[] data, boolforward)

{var n =data.Length;

n/= 2;

Reverse(data, n);float sign = forward ? 1 : -1;var mmax = 1;while (n >mmax)

{var istep = 2 *mmax;var theta = sign * (float)Math.PI /mmax;float wr = 1, wi = 0;var wpr = (float)Math.Cos(theta);var wpi = (float)Math.Sin(theta);for (var m = 0; m < istep; m += 2)

{for (var k = m; k < 2 * n; k += 2 *istep)

{var j = k +istep;var tempr = wr * data[j] - wi * data[j + 1];var tempi = wi * data[j] + wr * data[j + 1];

data[j]= data[k] -tempr;

data[j+ 1] = data[k + 1] -tempi;

data[k]= data[k] +tempr;

data[k+ 1] = data[k + 1] +tempi;

}var t =wr;

wr= wr * wpr - wi *wpi;

wi= wi * wpr + t *wpi;

}

mmax=istep;

}

}

static void Main(string[] args)

{int n =1024*512;float[] data = new float[2 *n];for (int i = 0; i < n; i++)

{

data[2 * i] =i;

data[2 * i + 1] = 0;

}

Complex[] cpData= newComplex[n];for (int i = 0; i < n; i++)

{

cpData[i]= new Complex(data[2 * i], data[2 * i + 1]);

}long s =DateTime.Now.Ticks;

FFT1(cpData,true);

Console.WriteLine("time:" + (DateTime.Now.Ticks - s) / 10000);

s=DateTime.Now.Ticks;

FFT2(data,true);

Console.WriteLine("time:" + (DateTime.Now.Ticks - s) / 10000);

Console.Read();

}

速度上还是差挺多的。。。

好了获得频率数据之后的流程就不再那么烧脑了(都怪自己早早把傅里叶变换还给课本了)。。。

找节奏点的逻辑大概如下(代码有点多就不贴了):

1.根据采样率依次获取数据,每次通过FFT得到一组复数数组。

2.计算出复数的模长,可以表示此频率下的声音大小,可以把一定范围的声音累加起来,可以用来表示低音、中音、高音。

3.对比每一帧的数据变化就可以判断出节奏点(声音变化大,可以表示是一个节奏点)。

其实能得到频域的值,针对不同的功能,大家后面就可以自由发挥了。

java 音频 傅立叶_关于FFT分析音频的小归纳相关推荐

  1. python音频特征提取_使用Python对音频进行特征提取

    写在前面 因为喜欢玩儿音乐游戏,所以打算研究一下如何用深度学习的模型生成音游的谱面.这篇文章主要目的是介绍或者总结一些音频的知识和代码. 恩.如果没玩儿过的话,音乐游戏大概是下面这个样子. 下面进入正 ...

  2. python 音频处理_基于Python的音频数据处理研究与应用

    收稿日期: ! " " # $ " % $ " & 作者简介: 何月顺 ( ' ( & ' -) , 男, 湖南道州人, 博士研究生, 主要研究 ...

  3. java项目教训_[免费电子书]分析超过600,000个Java项目的经验教训

    java项目教训 建立明智的错误处理工作流程需要什么? 调查和解决生产中的应用程序错误对于维持性能和可靠性至关重要. 但是,这并不意味着要花很多时间. 要理解为什么在生产中的故障排除,可这样的头痛,我 ...

  4. python的实时音频传送_使用Python使用音频传输数据

    你需要看看调制技术.正常程序如下:用纠错码使二进制数据冗余 将数据调制成离散信号 D/A转换器 物理介质传输 A/D转换器采样 解调 误差修正 如果你想做的更简单,那么你可以跳过纠错部分,但这会带来风 ...

  5. java肝癌晚期_生信分析43.肿瘤浸润免疫与肝癌(HCCDB+oncomine)

    生信论文的套路 ONCOMINE从全景.亚型两个维度做表达差异分析: 临床标本从蛋白水平确认(或HPA数据库),很重要: Kaplan-Meier Plotter从临床意义的角度阐明其重要性: cBi ...

  6. java人体识别_【人体分析-人像分割】JavaAPI示例代码

    接口能力: 对于输入的一张图片(可正常解码,且长宽比适宜),识别人体的轮廓范围,与背景进行分离,适用于拍照背景替换.照片合成.身体特效等场景.输入正常人像图片,返回分割后的二值结果图和分割类型(目前仅 ...

  7. java人体识别_【人体分析-人体属性识别】-Java示例代码

    人体属性识别,即对于输入的一张图片(可正常解码,且长宽比适宜),输出图片中的所有人体的静态属性,包含坐标信息.性别.年龄阶段.衣着(含颜色).是否带帽子.是否带眼镜.是否背包.是否抽烟.是否使用手机. ...

  8. java黄金分割点游戏_结对编程1——黄金点小游戏项目简介及需求分析

    一.项目成员 2018141461085 龚泽楠 2018141461012 蔡铧荣 二.项目名称 黄金点小游戏 三.项目简介 游戏规则: N个同学( N通常大于 10 ),每人写一个 0~100 之 ...

  9. 数字信号处理实验三用fft对信号作频谱分析_机器学习中的音频特征:理解Mel频谱图...

    如果你像我一样,试着理解mel的光谱图并不是一件容易的事.你读了一篇文章,却被引出了另一篇,又一篇,又一篇,没完没了.我希望这篇简短的文章能澄清一些困惑,并从头解释mel的光谱图. 信号 信号是一定量 ...

最新文章

  1. 三层架构和MVC模式
  2. boost::tti模块测试函数模板
  3. java 字符串模糊匹配_Java实现伪查询(全匹配+模糊匹配)
  4. 锻炼产品架构思维的4个维度
  5. 《C语言深度解剖》学习笔记之内存管理
  6. java基础反射知识总结_非常好的Java基础反射总结
  7. 中断占据CPU时间的计算问题
  8. Linux打印cups API及代码范例链接
  9. c4d安装没有出现语言文字,关于C4D以及渲染器插件安装时遇到的问题以及解决方法...
  10. 三消游戏算法图文详解
  11. 使用POJO对象绑定请求参数
  12. 展会推广有哪些好的创意 怎样让展会推广更有创意
  13. 【原创】MATLAB汽车制动防抱死模型ABS模型
  14. Navicat15安装使用
  15. Docker-compose容器编排
  16. 为什么谷歌越来越牛逼, 而百度却沦为江湖骗子?
  17. python在线diff工具在哪_Python - deepdiff
  18. [转]QNX与Linux OS比较优劣-QNX与Linux两家未来有望独霸车载电子操作系统
  19. 静态存储区与动态存储区
  20. (示例一)功能简单的小区快递管理系统(二维数组存储数据)

热门文章

  1. shell 编程 入门到实战详解
  2. 使用Profiler进行性能分析
  3. 【弹子兵法】四国军棋棋盘、棋子与记谱【基础篇】
  4. astar不能用了_截图快捷键,手把手教你截屏快捷键Ctrl+Alt+A不能用了怎么办
  5. 计算机软件系统发展历史,一文带你了解操作系统发展史
  6. Paper:自动驾驶领域SAE标准之《道路机动车辆驾驶自动化系统相关术语的分类和定义》官方英文原文翻译与解读(二)
  7. 计算k段流水线执行n条指令的执行时间
  8. 致得E6协同文档管理软件 推出4.0免费版
  9. 工作点滴1 - Cisco IOS ver12.4 dampening bug - 思科路由器端口抑制漏洞
  10. hive 以beeline的模式启动