最近做音频信号处理的时候,需要对数据做fft变换。关于fft原理:

请参考:FFT算法讲解——麻麻我终于会FFT了!

matlab实现fft函数很简单,直接调用fft即可。但java实现起来就有点难了。参考了比较好两篇java实现的博客:

A.Java实现算法导论中快速傅里叶变换FFT递归算法

B.快速傅里叶变换及java实现

通过比对。A博客只实现了数组长度是2的幂次的函数,其他就没有实现,B博客是实现了所有的,但其中有几处错误。最后实现方法如下:

1)FFT函数

这个函数A和B基本上差不多,但B博客的n为1时,返回要改一下。

public static Complex[] fft(Complex[] x) {

int n = x.length;

// 因为exp(-2i*n*PI)=1,n=1时递归原点

if (n == 1){

// 这里和B博客中有一点变化

return new Complex[]{x[0]};

}

// 如果信号数为奇数,使用dft计算

if (n % 2 != 0) {

return dft(x);

}

// 提取下标为偶数的原始信号值进行递归fft计算

Complex[] even = new Complex[n / 2];

for (int k = 0; k < n / 2; k++) {

even[k] = x[2 * k];

}

Complex[] evenValue = fft(even);

// 提取下标为奇数的原始信号值进行fft计算

// 节约内存

Complex[] odd = even;

for (int k = 0; k < n / 2; k++) {

odd[k] = x[2 * k + 1];

}

Complex[] oddValue = fft(odd);

// 偶数+奇数

Complex[] result = new Complex[n];

for (int k = 0; k < n / 2; k++) {

// 使用欧拉公式e^(-i*2pi*k/N) = cos(-2pi*k/N) + i*sin(-2pi*k/N)

double p = -2 * k * Math.PI / n;

Complex m = new Complex(Math.cos(p), Math.sin(p));

result[k] = evenValue[k].plus(m.multiple(oddValue[k]));

// exp(-2*(k+n/2)*PI/n) 相当于 -exp(-2*k*PI/n),其中exp(-n*PI)=-1(欧拉公式);

result[k + n / 2] = evenValue[k].minus(m.multiple(oddValue[k]));

}

return result;

}

2)DFT函数

这个函数主要参考B博客的,修改的地方有:

a.当长度为1时,返回值

b.算cos,sin函数参数的时候,把-2 * k* Math.PI / n改为-2 * i * k* Math.PI / n;;

public static Complex[] dft(Complex[] x) {

int n = x.length;

// exp(-2i*n*PI)=cos(-2*n*PI)+i*sin(-2*n*PI)=1

if (n == 1)

return new Complex[]{x[0]};

Complex[] result = new Complex[n];

for (int i = 0; i < n; i++) {

result[i] = new Complex(0, 0);

for (int k = 0; k < n; k++) {

//使用欧拉公式e^(-i*2pi*k/N) = cos(-2pi*k/N) + i*sin(-2pi*k/N)

double p = -2 * i * k* Math.PI / n;

Complex m = new Complex(Math.cos(p), Math.sin(p));

result[i] = result[i].plus(x[k].multiple(m));

}

}

return result;

}

3)Complex代码

public class Complex {

private final double re; // the real part

private final double im; // the imaginary part

// create a new object with the given real and imaginary parts

public Complex(double real, double imag) {

re = real;

im = imag;

}

// return a string representation of the invoking Complex object

public String toString() {

if (im == 0)

return re + "";

if (re == 0)

return im + "i";

if (im < 0)

return re + " - " + (-im) + "i";

return re + " + " + im + "i";

}

// return abs/modulus/magnitude

public double abs() {

return Math.hypot(re, im);

}

// return angle/phase/argument, normalized to be between -pi and pi

public double phase() {

return Math.atan2(im, re);

}

// return a new Complex object whose value is (this + b)

public Complex plus(Complex b) {

Complex a = this; // invoking object

double real = a.re + b.re;

double imag = a.im + b.im;

return new Complex(real, imag);

}

// return a new Complex object whose value is (this - b)

public Complex minus(Complex b) {

Complex a = this;

double real = a.re - b.re;

double imag = a.im - b.im;

return new Complex(real, imag);

}

// return a new Complex object whose value is (this * b)

public Complex multiple(Complex b) {

Complex a = this;

double real = a.re * b.re - a.im * b.im;

double imag = a.re * b.im + a.im * b.re;

return new Complex(real, imag);

}

// scalar multiplication

// return a new object whose value is (this * alpha)

public Complex multiple(double alpha) {

return new Complex(alpha * re, alpha * im);

}

// return a new object whose value is (this * alpha)

public Complex scale(double alpha) {

return new Complex(alpha * re, alpha * im);

}

// return a new Complex object whose value is the conjugate of this

public Complex conjugate() {

return new Complex(re, -im);

}

// return a new Complex object whose value is the reciprocal of this

public Complex reciprocal() {

double scale = re * re + im * im;

return new Complex(re / scale, -im / scale);

}

// return the real or imaginary part

public double re() {

return re;

}

public double im() {

return im;

}

// return a / b

public Complex divides(Complex b) {

Complex a = this;

return a.multiple(b.reciprocal());

}

// return a new Complex object whose value is the complex exponential of

// this

public Complex exp() {

return new Complex(Math.exp(re) * Math.cos(im), Math.exp(re) * Math.sin(im));

}

// return a new Complex object whose value is the complex sine of this

public Complex sin() {

return new Complex(Math.sin(re) * Math.cosh(im), Math.cos(re) * Math.sinh(im));

}

// return a new Complex object whose value is the complex cosine of this

public Complex cos() {

return new Complex(Math.cos(re) * Math.cosh(im), -Math.sin(re) * Math.sinh(im));

}

// return a new Complex object whose value is the complex tangent of this

public Complex tan() {

return sin().divides(cos());

}

// a static version of plus

public static Complex plus(Complex a, Complex b) {

double real = a.re + b.re;

double imag = a.im + b.im;

Complex sum = new Complex(real, imag);

return sum;

}

// See Section 3.3.

public boolean equals(Object x) {

if (x == null)

return false;

if (this.getClass() != x.getClass())

return false;

Complex that = (Complex) x;

return (this.re == that.re) && (this.im == that.im);

}

// See Section 3.3.

public int hashCode() {

return Objects.hash(re, im);

}

}

最后运行情况

matlab

matlab运行结果

上边是输入的数组,下边是fft输出数组。

java

java运行结果

java fft_java实现快速傅里叶变换(FFT)相关推荐

  1. Java中实现快速傅里叶变换FFT

    Java中实现快速傅里叶变换FFT 一.概述 1.傅里叶变换(FT) 2.离散傅里叶变换(DFT) 3.快速傅里叶变换(FFT) 1)单位根 2)快速傅里叶变换的思想 3)蝶形图 4)快速傅里叶变换的 ...

  2. Java编程实现快速傅里叶变换FFT

    快速傅里叶变换的时间复杂度分析 1 快速傅里叶变换FFT 1.1 理论分析 1.1.1 离散傅里叶变换 1.1.2 快速傅里叶变换 1.2 编程实现 1.2.1 算法思想 1.2.2 实验结果 1 快 ...

  3. 基于python的快速傅里叶变换FFT(二)

    基于python的快速傅里叶变换FFT(二) 本文在上一篇博客的基础上进一步探究正弦函数及其FFT变换. 知识点   FFT变换,其实就是快速离散傅里叶变换,傅立叶变换是数字信号处理领域一种很重要的算 ...

  4. 基于python的快速傅里叶变换FFT(一)

    基于python的快速傅里叶变换FFT(一) FFT可以将一个信号变换到频域.有些信号在时域上是很难看出什么特征的,但是如果变换到频域之后,就很容易看出特征了.这就是很多信号分析采用FFT变换的原因. ...

  5. MIT 线性代数 Linear Algebra 26:复矩阵,傅里叶矩阵, 快速傅里叶变换 FFT

    这一讲我们来讲一下复矩阵.线性代数中,复矩阵是避免不了的话题,因为一个简单实矩阵都有可能有复数特征值. 复矩阵 我们着重看一下复矩阵和实矩阵在运算上的区别. 距离 首先,一个复数向量的的距离求法发生了 ...

  6. OpenCV快速傅里叶变换(FFT)用于图像和视讯流的模糊检测

    OpenCV快速傅里叶变换(FFT)用于图像和视频流的模糊检测 翻译自[OpenCV Fast Fourier Transform (FFT) for blur detection in images ...

  7. Matlab如何进行利用离散傅里叶变换DFT (快速傅里叶变换FFT)进行频谱分析

    文章目录 1. 定义 2. 变换和处理 3. 函数 4. 实例演示 例1:单频正弦信号(整数周期采样) 例2:单频正弦信号(非整数周期采样) 例3:含有直流分量的单频正弦信号 例4:正弦复合信号 例5 ...

  8. 快速傅里叶变换FFT进行频谱分析(matlab)

    快速傅里叶变换FFT进行频谱分析(matlab) 本章摘要:FFT是离散傅立叶变换的快速算法,可以将一个信号变换到频域.有些信号在时域上是很难看出什么特征的,但是如果变换到频域之后,就很容易看出特征了 ...

  9. 快速傅里叶变换FFT C语言实现 可用于嵌入式系统进行模拟采样频谱分析

    快速傅里叶变换C语言实现 模拟采样进行频谱分析 FFT是DFT的快速算法用于分析确定信号(时间连续可积信号.不一定是周期信号)的频率(或相位.此处不研究相位)成分,且傅里叶变换对应的 ω \omega ...

最新文章

  1. 服务器安装配置流水帐
  2. linux 搭建gradle android jenkins打包机器,gradle 依赖 jar问题
  3. Wss 3.0安装指南(一)
  4. 一文搞懂:词法作用域、动态作用域、回调函数、闭包
  5. 一、Java 面向对象高级——Object类、常用API
  6. 机器人控制学习机器编程代码_机器学习正在征服显式编程
  7. HTML中的img标签无法显示图片的解决方案
  8. C语言中的函数(详解)
  9. python format是什么意思_python的format什么意思
  10. 【微信小程序开发日记01】和风天气OUC之初步构想
  11. 数据可视化之美:桑基图的前世今生
  12. 苹果手机打电话没有声音怎么回事_微信打电话没有声音
  13. 浅谈“决策引擎”在身份管理的应用
  14. vue 应用中Throttling navigation to prevent the browser from hanging.问题
  15. 回文日期 php,c语言程序实例大全,220个详细程序源代码
  16. 传统手工排程痛点多,带您了解APS高级计划排程系统
  17. 解决crx文件扩展程序chrome下载自动删除的问题
  18. Ubuntu手动安装pymysql(含pymysql的.whl及.tar.gz下载地址)
  19. 赵雅智_service电话监听2加接通电话录音
  20. Unity UGUI 数字使用图片显示-BMFont

热门文章

  1. python isinstance得用法记录
  2. 1675. Minimize Deviation in Array
  3. 嵌入式编程相关专业英语积累
  4. 困扰的Byte、bit 、和16进制之间的关系
  5. SQL必知必会(一)SQL基础篇
  6. Ureal:用ue4做出游戏中的爆炸特效真实感和力量感
  7. Ubuntu 怎么在 Libreoffice 中添加字体
  8. 使用e5405cpu服务器性能,科技知识:e5405相当于什么cpu
  9. http协议各个版本之解说
  10. 调用notifyDataSetChanged无法更新ListView