java 音频 傅立叶_关于FFT分析音频的小归纳
最近工作上在做关于音乐游戏的内容,其中需要分析音频找节奏点(或者说是重音点)。
学习了一系列相关知识后,了解到一段音乐的波形图可以分解成不同频率的波形图,也就是由时域到频域的转换。
借用其他博主的图就比较容易理解了,如下所示。
波从时域到频域的转换可以通过傅里叶变换实现,关于傅里叶变换的知识可以从最上面的链接学习或者自行查找(傅里叶真厉害!!!)。
计算机处理的音频在时域上是离散的数据,我们可以使用离散傅里叶变换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分析音频的小归纳相关推荐
- python音频特征提取_使用Python对音频进行特征提取
写在前面 因为喜欢玩儿音乐游戏,所以打算研究一下如何用深度学习的模型生成音游的谱面.这篇文章主要目的是介绍或者总结一些音频的知识和代码. 恩.如果没玩儿过的话,音乐游戏大概是下面这个样子. 下面进入正 ...
- python 音频处理_基于Python的音频数据处理研究与应用
收稿日期: ! " " # $ " % $ " & 作者简介: 何月顺 ( ' ( & ' -) , 男, 湖南道州人, 博士研究生, 主要研究 ...
- java项目教训_[免费电子书]分析超过600,000个Java项目的经验教训
java项目教训 建立明智的错误处理工作流程需要什么? 调查和解决生产中的应用程序错误对于维持性能和可靠性至关重要. 但是,这并不意味着要花很多时间. 要理解为什么在生产中的故障排除,可这样的头痛,我 ...
- python的实时音频传送_使用Python使用音频传输数据
你需要看看调制技术.正常程序如下:用纠错码使二进制数据冗余 将数据调制成离散信号 D/A转换器 物理介质传输 A/D转换器采样 解调 误差修正 如果你想做的更简单,那么你可以跳过纠错部分,但这会带来风 ...
- java肝癌晚期_生信分析43.肿瘤浸润免疫与肝癌(HCCDB+oncomine)
生信论文的套路 ONCOMINE从全景.亚型两个维度做表达差异分析: 临床标本从蛋白水平确认(或HPA数据库),很重要: Kaplan-Meier Plotter从临床意义的角度阐明其重要性: cBi ...
- java人体识别_【人体分析-人像分割】JavaAPI示例代码
接口能力: 对于输入的一张图片(可正常解码,且长宽比适宜),识别人体的轮廓范围,与背景进行分离,适用于拍照背景替换.照片合成.身体特效等场景.输入正常人像图片,返回分割后的二值结果图和分割类型(目前仅 ...
- java人体识别_【人体分析-人体属性识别】-Java示例代码
人体属性识别,即对于输入的一张图片(可正常解码,且长宽比适宜),输出图片中的所有人体的静态属性,包含坐标信息.性别.年龄阶段.衣着(含颜色).是否带帽子.是否带眼镜.是否背包.是否抽烟.是否使用手机. ...
- java黄金分割点游戏_结对编程1——黄金点小游戏项目简介及需求分析
一.项目成员 2018141461085 龚泽楠 2018141461012 蔡铧荣 二.项目名称 黄金点小游戏 三.项目简介 游戏规则: N个同学( N通常大于 10 ),每人写一个 0~100 之 ...
- 数字信号处理实验三用fft对信号作频谱分析_机器学习中的音频特征:理解Mel频谱图...
如果你像我一样,试着理解mel的光谱图并不是一件容易的事.你读了一篇文章,却被引出了另一篇,又一篇,又一篇,没完没了.我希望这篇简短的文章能澄清一些困惑,并从头解释mel的光谱图. 信号 信号是一定量 ...
最新文章
- 三层架构和MVC模式
- boost::tti模块测试函数模板
- java 字符串模糊匹配_Java实现伪查询(全匹配+模糊匹配)
- 锻炼产品架构思维的4个维度
- 《C语言深度解剖》学习笔记之内存管理
- java基础反射知识总结_非常好的Java基础反射总结
- 中断占据CPU时间的计算问题
- Linux打印cups API及代码范例链接
- c4d安装没有出现语言文字,关于C4D以及渲染器插件安装时遇到的问题以及解决方法...
- 三消游戏算法图文详解
- 使用POJO对象绑定请求参数
- 展会推广有哪些好的创意 怎样让展会推广更有创意
- 【原创】MATLAB汽车制动防抱死模型ABS模型
- Navicat15安装使用
- Docker-compose容器编排
- 为什么谷歌越来越牛逼, 而百度却沦为江湖骗子?
- python在线diff工具在哪_Python - deepdiff
- [转]QNX与Linux OS比较优劣-QNX与Linux两家未来有望独霸车载电子操作系统
- 静态存储区与动态存储区
- (示例一)功能简单的小区快递管理系统(二维数组存储数据)
热门文章
- shell 编程 入门到实战详解
- 使用Profiler进行性能分析
- 【弹子兵法】四国军棋棋盘、棋子与记谱【基础篇】
- astar不能用了_截图快捷键,手把手教你截屏快捷键Ctrl+Alt+A不能用了怎么办
- 计算机软件系统发展历史,一文带你了解操作系统发展史
- Paper:自动驾驶领域SAE标准之《道路机动车辆驾驶自动化系统相关术语的分类和定义》官方英文原文翻译与解读(二)
- 计算k段流水线执行n条指令的执行时间
- 致得E6协同文档管理软件 推出4.0免费版
- 工作点滴1 - Cisco IOS ver12.4 dampening bug - 思科路由器端口抑制漏洞
- hive 以beeline的模式启动