packagecom.xu.music.player.fft;importjava.util.stream.Stream;publicclassFFT{/**
* compute the FFT of x[], assuming its length is a power of 2
*
* @param x
* @return
*/publicstaticComplex[]fft(Complex[] x){int n = x.length;// base caseif(n ==1){returnnewComplex[]{x[0]};}// radix 2 Cooley-Tukey FFTif(n %2!=0){thrownewRuntimeException("N is not a power of 2");}// fft of even termsComplex[] even =newComplex[n /2];for(int k =0; k < n /2; k++){
even[k]= x[2* k];}Complex[] q =fft(even);// fft of odd termsComplex[] odd = even;// reuse the arrayfor(int k =0; k < n /2; k++){
odd[k]= x[2* k +1];}Complex[] r =fft(odd);// combineComplex[] y =newComplex[n];for(int k =0; k < n /2; k++){double kth =-2* k *Math.PI/ n;Complex wk =newComplex(Math.cos(kth),Math.sin(kth));
y[k]= q[k].plus(wk.times(r[k]));
y[k + n /2]= q[k].minus(wk.times(r[k]));}return y;}/**
* compute the inverse FFT of x[], assuming its length is a power of 2
*
* @param x
* @return
*/publicstaticComplex[]ifft(Complex[] x){int n = x.length;Complex[] y =newComplex[n];// take conjugatefor(int i =0; i < n; i++){
y[i]= x[i].conjugate();}// compute forward FFT
y =fft(y);// take conjugate againfor(int i =0; i < n; i++){
y[i]= y[i].conjugate();}// divide by Nfor(int i =0; i < n; i++){
y[i]= y[i].scale(1.0/ n);}return y;}/**
* compute the circular convolution of x and y
*
* @param x
* @param y
* @return
*/publicstaticComplex[]cconvolve(Complex[] x,Complex[] y){// should probably pad x and y with 0s so that they have same length and are powers of 2if(x.length != y.length){thrownewRuntimeException("Dimensions don't agree");}int n = x.length;// compute FFT of each sequence,求值Complex[] a =fft(x);Complex[] b =fft(y);// point-wise multiply,点值乘法Complex[] c =newComplex[n];for(int i =0; i < n; i++){
c[i]= a[i].times(b[i]);}// compute inverse FFT,插值returnifft(c);}/**
* compute the linear convolution of x and y
*
* @param x
* @param y
* @return
*/publicstaticComplex[]convolve(Complex[] x,Complex[] y){Complex zero =newComplex(0,0);// 2n次数界,高阶系数为0.Complex[] a =newComplex[2* x.length];for(int i =0; i < x.length; i++){
a[i]= x[i];}for(int i = x.length; i <2* x.length; i++){
a[i]= zero;}Complex[] b =newComplex[2* y.length];for(int i =0; i < y.length; i++){
b[i]= y[i];}for(int i = y.length; i <2* y.length; i++){
b[i]= zero;}returncconvolve(a, b);}/**
* Complex[] to double array for MusicPlayer
*
* @param x
* @return
*/publicstaticDouble[]array(Complex[] x){//for MusicPlayerint len = x.length;//修正幅过小 输出幅值 * 2 / length * 50returnStream.of(x).map(a -> a.abs()*2/ len *50).toArray(Double[]::new);}/**
* display an array of Complex numbers to standard output
*
* @param x
* @param title
*/publicstaticvoidshow(Double[] x,String... title){for(String s : title){System.out.print(s);}System.out.println();System.out.println("-------------------");for(int i =0, len = x.length; i < len; i++){System.out.println(x[i]);}System.out.println();}/**
* display an array of Complex numbers to standard output
*
* @param x
* @param title
*/publicstaticvoidshow(Complex[] x,String title){System.out.println(title);System.out.println("-------------------");for(int i =0, len = x.length; i < len; i++){// 输出幅值需要 * 2 / lengthSystem.out.println(x[i].abs()*2/ len);}System.out.println();}/**
* 将数组数据重组成2的幂次方输出
*
* @param data
* @return
*/publicstaticDouble[]pow2DoubleArr(Double[] data){// 创建新数组Double[] newData =null;int dataLength = data.length;int sumNum =2;while(sumNum < dataLength){
sumNum = sumNum *2;}int addLength = sumNum - dataLength;if(addLength !=0){
newData =newDouble[sumNum];System.arraycopy(data,0, newData,0, dataLength);for(int i = dataLength; i < sumNum; i++){
newData[i]=0d;}}else{
newData = data;}return newData;}/**
* 去偏移量
*
* @param originalArr 原数组
* @return 目标数组
*/publicstaticDouble[]deskew(Double[] originalArr){// 过滤不正确的参数if(originalArr ==null|| originalArr.length <=0){returnnull;}// 定义目标数组Double[] resArr =newDouble[originalArr.length];// 求数组总和Double sum =0D;for(int i =0; i < originalArr.length; i++){
sum += originalArr[i];}// 求数组平均值Double aver = sum / originalArr.length;// 去除偏移值for(int i =0; i < originalArr.length; i++){
resArr[i]= originalArr[i]- aver;}return resArr;}}
2.2 Complex.java
packagecom.xu.music.player.fft;importjava.util.Objects;publicclassComplex{privatefinaldouble re;// the real partprivatefinaldouble im;// the imaginary part// create a new object with the given real and imaginary partspublicComplex(double real,double imag){
re = real;
im = imag;}// a static version of pluspublicstaticComplexplus(Complex a,Complex b){double real = a.re + b.re;double imag = a.im + b.im;Complex sum =newComplex(real, imag);return sum;}// sample client for testingpublicstaticvoidmain(String[] args){Complex a =newComplex(3.0,4.0);Complex b =newComplex(-3.0,4.0);System.out.println("a = "+ a);System.out.println("b = "+ b);System.out.println("Re(a) = "+ a.re());System.out.println("Im(a) = "+ a.im());System.out.println("b + a = "+ b.plus(a));System.out.println("a - b = "+ a.minus(b));System.out.println("a * b = "+ a.times(b));System.out.println("b * a = "+ b.times(a));System.out.println("a / b = "+ a.divides(b));System.out.println("(a / b) * b = "+ a.divides(b).times(b));System.out.println("conj(a) = "+ a.conjugate());System.out.println("|a| = "+ a.abs());System.out.println("tan(a) = "+ a.tan());}// return a string representation of the invoking Complex object@OverridepublicStringtoString(){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/magnitudepublicdoubleabs(){returnMath.hypot(re, im);}// return angle/phase/argument, normalized to be between -pi and pipublicdoublephase(){returnMath.atan2(im, re);}// return a new Complex object whose value is (this + b)publicComplexplus(Complex b){Complex a =this;// invoking objectdouble real = a.re + b.re;double imag = a.im + b.im;returnnewComplex(real, imag);}// return a new Complex object whose value is (this - b)publicComplexminus(Complex b){Complex a =this;double real = a.re - b.re;double imag = a.im - b.im;returnnewComplex(real, imag);}// return a new Complex object whose value is (this * b)publicComplextimes(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;returnnewComplex(real, imag);}// return a new object whose value is (this * alpha)publicComplexscale(double alpha){returnnewComplex(alpha * re, alpha * im);}// return a new Complex object whose value is the conjugate of thispublicComplexconjugate(){returnnewComplex(re,-im);}// return a new Complex object whose value is the reciprocal of thispublicComplexreciprocal(){double scale = re * re + im * im;returnnewComplex(re / scale,-im / scale);}// return the real or imaginary partpublicdoublere(){return re;}publicdoubleim(){return im;}// return a / bpublicComplexdivides(Complex b){Complex a =this;return a.times(b.reciprocal());}// return a new Complex object whose value is the complex exponential of// thispublicComplexexp(){returnnewComplex(Math.exp(re)*Math.cos(im),Math.exp(re)*Math.sin(im));}// return a new Complex object whose value is the complex sine of thispublicComplexsin(){returnnewComplex(Math.sin(re)*Math.cosh(im),Math.cos(re)*Math.sinh(im));}// return a new Complex object whose value is the complex cosine of thispublicComplexcos(){returnnewComplex(Math.cos(re)*Math.cosh(im),-Math.sin(re)*Math.sinh(im));}// return a new Complex object whose value is the complex tangent of thispublicComplextan(){returnsin().divides(cos());}// See Section 3.3.@Overridepublicbooleanequals(Object x){if(x ==null){returnfalse;}if(this.getClass()!= x.getClass()){returnfalse;}Complex that =(Complex) x;return(this.re == that.re)&&(this.im == that.im);}// See Section 3.3.@OverridepublicinthashCode(){returnObjects.hash(re, im);}}
文章目录 前言1、价值分解的研究现状2、Individual-Global-Max Property3、Linear and Monotonic Value Decomposition3.1线性值分解3.2 单调值分解 前言
中心化价值函数能够缓解一些多智能体强化学习当中的问题,如非平稳性、局部可观测、信用分配与均衡选择等问题…
59. 螺旋矩阵 II
题目
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1: 输入:n 3
输出:[[1,2,3],[8,9,4],[7,6,5]]示例 2:
输入&a…
题目:
138. 随机链表的复制 给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。 要求:构造这个链表的 深拷贝 深拷贝应该正好由 n 个 全新 节点组成,其中…
事务
比如说将张三的银行账户拿出一千给李四,首先需要查询张三的账户余额,扣除1000,然后如果给李四加上1000的过程中出现异常会回滚事务,临时修改的数据会回复回去。
-- 1. 查询张三账户余额
select * from account where name …