Path: blob/master/src/java.desktop/share/classes/com/sun/media/sound/FFT.java
41161 views
/*1* Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.media.sound;2627/**28* Fast Fourier Transformer.29*30* @author Karl Helgason31*/32public final class FFT {3334private final double[] w;35private final int fftFrameSize;36private final int sign;37private final int[] bitm_array;38private final int fftFrameSize2;3940// Sign = -1 is FFT, 1 is IFFT (inverse FFT)41// Data = Interlaced double array to be transformed.42// The order is: real (sin), complex (cos)43// Framesize must be power of 244public FFT(int fftFrameSize, int sign) {45w = computeTwiddleFactors(fftFrameSize, sign);4647this.fftFrameSize = fftFrameSize;48this.sign = sign;49fftFrameSize2 = fftFrameSize << 1;5051// Pre-process Bit-Reversal52bitm_array = new int[fftFrameSize2];53for (int i = 2; i < fftFrameSize2; i += 2) {54int j;55int bitm;56for (bitm = 2, j = 0; bitm < fftFrameSize2; bitm <<= 1) {57if ((i & bitm) != 0)58j++;59j <<= 1;60}61bitm_array[i] = j;62}6364}6566public void transform(double[] data) {67bitreversal(data);68calc(fftFrameSize, data, sign, w);69}7071private static double[] computeTwiddleFactors(int fftFrameSize,72int sign) {7374int imax = (int) (Math.log(fftFrameSize) / Math.log(2.));7576double[] warray = new double[(fftFrameSize - 1) * 4];77int w_index = 0;7879for (int i = 0, nstep = 2; i < imax; i++) {80int jmax = nstep;81nstep <<= 1;8283double wr = 1.0;84double wi = 0.0;8586double arg = Math.PI / (jmax >> 1);87double wfr = Math.cos(arg);88double wfi = sign * Math.sin(arg);8990for (int j = 0; j < jmax; j += 2) {91warray[w_index++] = wr;92warray[w_index++] = wi;9394double tempr = wr;95wr = tempr * wfr - wi * wfi;96wi = tempr * wfi + wi * wfr;97}98}99100// PRECOMPUTATION of wwr1, wwi1 for factor 4 Decomposition (3 * complex101// operators and 8 +/- complex operators)102{103w_index = 0;104int w_index2 = warray.length >> 1;105for (int i = 0, nstep = 2; i < (imax - 1); i++) {106int jmax = nstep;107nstep *= 2;108109int ii = w_index + jmax;110for (int j = 0; j < jmax; j += 2) {111double wr = warray[w_index++];112double wi = warray[w_index++];113double wr1 = warray[ii++];114double wi1 = warray[ii++];115warray[w_index2++] = wr * wr1 - wi * wi1;116warray[w_index2++] = wr * wi1 + wi * wr1;117}118}119120}121122return warray;123}124125private static void calc(int fftFrameSize, double[] data, int sign,126double[] w) {127128final int fftFrameSize2 = fftFrameSize << 1;129130int nstep = 2;131132if (nstep >= fftFrameSize2)133return;134int i = nstep - 2;135if (sign == -1)136calcF4F(fftFrameSize, data, i, nstep, w);137else138calcF4I(fftFrameSize, data, i, nstep, w);139140}141142private static void calcF2E(int fftFrameSize, double[] data, int i,143int nstep, double[] w) {144int jmax = nstep;145for (int n = 0; n < jmax; n += 2) {146double wr = w[i++];147double wi = w[i++];148int m = n + jmax;149double datam_r = data[m];150double datam_i = data[m + 1];151double datan_r = data[n];152double datan_i = data[n + 1];153double tempr = datam_r * wr - datam_i * wi;154double tempi = datam_r * wi + datam_i * wr;155data[m] = datan_r - tempr;156data[m + 1] = datan_i - tempi;157data[n] = datan_r + tempr;158data[n + 1] = datan_i + tempi;159}160return;161162}163164// Perform Factor-4 Decomposition with 3 * complex operators and 8 +/-165// complex operators166private static void calcF4F(int fftFrameSize, double[] data, int i,167int nstep, double[] w) {168final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize;169// Factor-4 Decomposition170171int w_len = w.length >> 1;172while (nstep < fftFrameSize2) {173174if (nstep << 2 == fftFrameSize2) {175// Goto Factor-4 Final Decomposition176// calcF4E(data, i, nstep, -1, w);177calcF4FE(fftFrameSize, data, i, nstep, w);178return;179}180int jmax = nstep;181int nnstep = nstep << 1;182if (nnstep == fftFrameSize2) {183// Factor-4 Decomposition not possible184calcF2E(fftFrameSize, data, i, nstep, w);185return;186}187nstep <<= 2;188int ii = i + jmax;189int iii = i + w_len;190191{192i += 2;193ii += 2;194iii += 2;195196for (int n = 0; n < fftFrameSize2; n += nstep) {197int m = n + jmax;198199double datam1_r = data[m];200double datam1_i = data[m + 1];201double datan1_r = data[n];202double datan1_i = data[n + 1];203204n += nnstep;205m += nnstep;206double datam2_r = data[m];207double datam2_i = data[m + 1];208double datan2_r = data[n];209double datan2_i = data[n + 1];210211double tempr = datam1_r;212double tempi = datam1_i;213214datam1_r = datan1_r - tempr;215datam1_i = datan1_i - tempi;216datan1_r = datan1_r + tempr;217datan1_i = datan1_i + tempi;218219double n2w1r = datan2_r;220double n2w1i = datan2_i;221double m2ww1r = datam2_r;222double m2ww1i = datam2_i;223224tempr = m2ww1r - n2w1r;225tempi = m2ww1i - n2w1i;226227datam2_r = datam1_r + tempi;228datam2_i = datam1_i - tempr;229datam1_r = datam1_r - tempi;230datam1_i = datam1_i + tempr;231232tempr = n2w1r + m2ww1r;233tempi = n2w1i + m2ww1i;234235datan2_r = datan1_r - tempr;236datan2_i = datan1_i - tempi;237datan1_r = datan1_r + tempr;238datan1_i = datan1_i + tempi;239240data[m] = datam2_r;241data[m + 1] = datam2_i;242data[n] = datan2_r;243data[n + 1] = datan2_i;244245n -= nnstep;246m -= nnstep;247data[m] = datam1_r;248data[m + 1] = datam1_i;249data[n] = datan1_r;250data[n + 1] = datan1_i;251252}253}254255for (int j = 2; j < jmax; j += 2) {256double wr = w[i++];257double wi = w[i++];258double wr1 = w[ii++];259double wi1 = w[ii++];260double wwr1 = w[iii++];261double wwi1 = w[iii++];262// double wwr1 = wr * wr1 - wi * wi1; // these numbers can be263// precomputed!!!264// double wwi1 = wr * wi1 + wi * wr1;265266for (int n = j; n < fftFrameSize2; n += nstep) {267int m = n + jmax;268269double datam1_r = data[m];270double datam1_i = data[m + 1];271double datan1_r = data[n];272double datan1_i = data[n + 1];273274n += nnstep;275m += nnstep;276double datam2_r = data[m];277double datam2_i = data[m + 1];278double datan2_r = data[n];279double datan2_i = data[n + 1];280281double tempr = datam1_r * wr - datam1_i * wi;282double tempi = datam1_r * wi + datam1_i * wr;283284datam1_r = datan1_r - tempr;285datam1_i = datan1_i - tempi;286datan1_r = datan1_r + tempr;287datan1_i = datan1_i + tempi;288289double n2w1r = datan2_r * wr1 - datan2_i * wi1;290double n2w1i = datan2_r * wi1 + datan2_i * wr1;291double m2ww1r = datam2_r * wwr1 - datam2_i * wwi1;292double m2ww1i = datam2_r * wwi1 + datam2_i * wwr1;293294tempr = m2ww1r - n2w1r;295tempi = m2ww1i - n2w1i;296297datam2_r = datam1_r + tempi;298datam2_i = datam1_i - tempr;299datam1_r = datam1_r - tempi;300datam1_i = datam1_i + tempr;301302tempr = n2w1r + m2ww1r;303tempi = n2w1i + m2ww1i;304305datan2_r = datan1_r - tempr;306datan2_i = datan1_i - tempi;307datan1_r = datan1_r + tempr;308datan1_i = datan1_i + tempi;309310data[m] = datam2_r;311data[m + 1] = datam2_i;312data[n] = datan2_r;313data[n + 1] = datan2_i;314315n -= nnstep;316m -= nnstep;317data[m] = datam1_r;318data[m + 1] = datam1_i;319data[n] = datan1_r;320data[n + 1] = datan1_i;321}322}323324i += jmax << 1;325326}327328calcF2E(fftFrameSize, data, i, nstep, w);329330}331332// Perform Factor-4 Decomposition with 3 * complex operators and 8 +/-333// complex operators334private static void calcF4I(int fftFrameSize, double[] data, int i,335int nstep, double[] w) {336final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize;337// Factor-4 Decomposition338339int w_len = w.length >> 1;340while (nstep < fftFrameSize2) {341342if (nstep << 2 == fftFrameSize2) {343// Goto Factor-4 Final Decomposition344// calcF4E(data, i, nstep, 1, w);345calcF4IE(fftFrameSize, data, i, nstep, w);346return;347}348int jmax = nstep;349int nnstep = nstep << 1;350if (nnstep == fftFrameSize2) {351// Factor-4 Decomposition not possible352calcF2E(fftFrameSize, data, i, nstep, w);353return;354}355nstep <<= 2;356int ii = i + jmax;357int iii = i + w_len;358{359i += 2;360ii += 2;361iii += 2;362363for (int n = 0; n < fftFrameSize2; n += nstep) {364int m = n + jmax;365366double datam1_r = data[m];367double datam1_i = data[m + 1];368double datan1_r = data[n];369double datan1_i = data[n + 1];370371n += nnstep;372m += nnstep;373double datam2_r = data[m];374double datam2_i = data[m + 1];375double datan2_r = data[n];376double datan2_i = data[n + 1];377378double tempr = datam1_r;379double tempi = datam1_i;380381datam1_r = datan1_r - tempr;382datam1_i = datan1_i - tempi;383datan1_r = datan1_r + tempr;384datan1_i = datan1_i + tempi;385386double n2w1r = datan2_r;387double n2w1i = datan2_i;388double m2ww1r = datam2_r;389double m2ww1i = datam2_i;390391tempr = n2w1r - m2ww1r;392tempi = n2w1i - m2ww1i;393394datam2_r = datam1_r + tempi;395datam2_i = datam1_i - tempr;396datam1_r = datam1_r - tempi;397datam1_i = datam1_i + tempr;398399tempr = n2w1r + m2ww1r;400tempi = n2w1i + m2ww1i;401402datan2_r = datan1_r - tempr;403datan2_i = datan1_i - tempi;404datan1_r = datan1_r + tempr;405datan1_i = datan1_i + tempi;406407data[m] = datam2_r;408data[m + 1] = datam2_i;409data[n] = datan2_r;410data[n + 1] = datan2_i;411412n -= nnstep;413m -= nnstep;414data[m] = datam1_r;415data[m + 1] = datam1_i;416data[n] = datan1_r;417data[n + 1] = datan1_i;418419}420421}422for (int j = 2; j < jmax; j += 2) {423double wr = w[i++];424double wi = w[i++];425double wr1 = w[ii++];426double wi1 = w[ii++];427double wwr1 = w[iii++];428double wwi1 = w[iii++];429// double wwr1 = wr * wr1 - wi * wi1; // these numbers can be430// precomputed!!!431// double wwi1 = wr * wi1 + wi * wr1;432433for (int n = j; n < fftFrameSize2; n += nstep) {434int m = n + jmax;435436double datam1_r = data[m];437double datam1_i = data[m + 1];438double datan1_r = data[n];439double datan1_i = data[n + 1];440441n += nnstep;442m += nnstep;443double datam2_r = data[m];444double datam2_i = data[m + 1];445double datan2_r = data[n];446double datan2_i = data[n + 1];447448double tempr = datam1_r * wr - datam1_i * wi;449double tempi = datam1_r * wi + datam1_i * wr;450451datam1_r = datan1_r - tempr;452datam1_i = datan1_i - tempi;453datan1_r = datan1_r + tempr;454datan1_i = datan1_i + tempi;455456double n2w1r = datan2_r * wr1 - datan2_i * wi1;457double n2w1i = datan2_r * wi1 + datan2_i * wr1;458double m2ww1r = datam2_r * wwr1 - datam2_i * wwi1;459double m2ww1i = datam2_r * wwi1 + datam2_i * wwr1;460461tempr = n2w1r - m2ww1r;462tempi = n2w1i - m2ww1i;463464datam2_r = datam1_r + tempi;465datam2_i = datam1_i - tempr;466datam1_r = datam1_r - tempi;467datam1_i = datam1_i + tempr;468469tempr = n2w1r + m2ww1r;470tempi = n2w1i + m2ww1i;471472datan2_r = datan1_r - tempr;473datan2_i = datan1_i - tempi;474datan1_r = datan1_r + tempr;475datan1_i = datan1_i + tempi;476477data[m] = datam2_r;478data[m + 1] = datam2_i;479data[n] = datan2_r;480data[n + 1] = datan2_i;481482n -= nnstep;483m -= nnstep;484data[m] = datam1_r;485data[m + 1] = datam1_i;486data[n] = datan1_r;487data[n + 1] = datan1_i;488489}490}491492i += jmax << 1;493494}495496calcF2E(fftFrameSize, data, i, nstep, w);497498}499500// Perform Factor-4 Decomposition with 3 * complex operators and 8 +/-501// complex operators502private static void calcF4FE(int fftFrameSize, double[] data, int i,503int nstep, double[] w) {504final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize;505// Factor-4 Decomposition506507int w_len = w.length >> 1;508while (nstep < fftFrameSize2) {509510int jmax = nstep;511int nnstep = nstep << 1;512if (nnstep == fftFrameSize2) {513// Factor-4 Decomposition not possible514calcF2E(fftFrameSize, data, i, nstep, w);515return;516}517nstep <<= 2;518int ii = i + jmax;519int iii = i + w_len;520for (int n = 0; n < jmax; n += 2) {521double wr = w[i++];522double wi = w[i++];523double wr1 = w[ii++];524double wi1 = w[ii++];525double wwr1 = w[iii++];526double wwi1 = w[iii++];527// double wwr1 = wr * wr1 - wi * wi1; // these numbers can be528// precomputed!!!529// double wwi1 = wr * wi1 + wi * wr1;530531int m = n + jmax;532533double datam1_r = data[m];534double datam1_i = data[m + 1];535double datan1_r = data[n];536double datan1_i = data[n + 1];537538n += nnstep;539m += nnstep;540double datam2_r = data[m];541double datam2_i = data[m + 1];542double datan2_r = data[n];543double datan2_i = data[n + 1];544545double tempr = datam1_r * wr - datam1_i * wi;546double tempi = datam1_r * wi + datam1_i * wr;547548datam1_r = datan1_r - tempr;549datam1_i = datan1_i - tempi;550datan1_r = datan1_r + tempr;551datan1_i = datan1_i + tempi;552553double n2w1r = datan2_r * wr1 - datan2_i * wi1;554double n2w1i = datan2_r * wi1 + datan2_i * wr1;555double m2ww1r = datam2_r * wwr1 - datam2_i * wwi1;556double m2ww1i = datam2_r * wwi1 + datam2_i * wwr1;557558tempr = m2ww1r - n2w1r;559tempi = m2ww1i - n2w1i;560561datam2_r = datam1_r + tempi;562datam2_i = datam1_i - tempr;563datam1_r = datam1_r - tempi;564datam1_i = datam1_i + tempr;565566tempr = n2w1r + m2ww1r;567tempi = n2w1i + m2ww1i;568569datan2_r = datan1_r - tempr;570datan2_i = datan1_i - tempi;571datan1_r = datan1_r + tempr;572datan1_i = datan1_i + tempi;573574data[m] = datam2_r;575data[m + 1] = datam2_i;576data[n] = datan2_r;577data[n + 1] = datan2_i;578579n -= nnstep;580m -= nnstep;581data[m] = datam1_r;582data[m + 1] = datam1_i;583data[n] = datan1_r;584data[n + 1] = datan1_i;585586}587588i += jmax << 1;589590}591}592593// Perform Factor-4 Decomposition with 3 * complex operators and 8 +/-594// complex operators595private static void calcF4IE(int fftFrameSize, double[] data, int i,596int nstep, double[] w) {597final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize;598// Factor-4 Decomposition599600int w_len = w.length >> 1;601while (nstep < fftFrameSize2) {602603int jmax = nstep;604int nnstep = nstep << 1;605if (nnstep == fftFrameSize2) {606// Factor-4 Decomposition not possible607calcF2E(fftFrameSize, data, i, nstep, w);608return;609}610nstep <<= 2;611int ii = i + jmax;612int iii = i + w_len;613for (int n = 0; n < jmax; n += 2) {614double wr = w[i++];615double wi = w[i++];616double wr1 = w[ii++];617double wi1 = w[ii++];618double wwr1 = w[iii++];619double wwi1 = w[iii++];620// double wwr1 = wr * wr1 - wi * wi1; // these numbers can be621// precomputed!!!622// double wwi1 = wr * wi1 + wi * wr1;623624int m = n + jmax;625626double datam1_r = data[m];627double datam1_i = data[m + 1];628double datan1_r = data[n];629double datan1_i = data[n + 1];630631n += nnstep;632m += nnstep;633double datam2_r = data[m];634double datam2_i = data[m + 1];635double datan2_r = data[n];636double datan2_i = data[n + 1];637638double tempr = datam1_r * wr - datam1_i * wi;639double tempi = datam1_r * wi + datam1_i * wr;640641datam1_r = datan1_r - tempr;642datam1_i = datan1_i - tempi;643datan1_r = datan1_r + tempr;644datan1_i = datan1_i + tempi;645646double n2w1r = datan2_r * wr1 - datan2_i * wi1;647double n2w1i = datan2_r * wi1 + datan2_i * wr1;648double m2ww1r = datam2_r * wwr1 - datam2_i * wwi1;649double m2ww1i = datam2_r * wwi1 + datam2_i * wwr1;650651tempr = n2w1r - m2ww1r;652tempi = n2w1i - m2ww1i;653654datam2_r = datam1_r + tempi;655datam2_i = datam1_i - tempr;656datam1_r = datam1_r - tempi;657datam1_i = datam1_i + tempr;658659tempr = n2w1r + m2ww1r;660tempi = n2w1i + m2ww1i;661662datan2_r = datan1_r - tempr;663datan2_i = datan1_i - tempi;664datan1_r = datan1_r + tempr;665datan1_i = datan1_i + tempi;666667data[m] = datam2_r;668data[m + 1] = datam2_i;669data[n] = datan2_r;670data[n + 1] = datan2_i;671672n -= nnstep;673m -= nnstep;674data[m] = datam1_r;675data[m + 1] = datam1_i;676data[n] = datan1_r;677data[n + 1] = datan1_i;678679}680681i += jmax << 1;682683}684}685686private void bitreversal(double[] data) {687if (fftFrameSize < 4)688return;689690int inverse = fftFrameSize2 - 2;691for (int i = 0; i < fftFrameSize; i += 4) {692int j = bitm_array[i];693694// Performing Bit-Reversal, even v.s. even, O(2N)695if (i < j) {696697int n = i;698int m = j;699700// COMPLEX: SWAP(data[n], data[m])701// Real Part702double tempr = data[n];703data[n] = data[m];704data[m] = tempr;705// Imagery Part706n++;707m++;708double tempi = data[n];709data[n] = data[m];710data[m] = tempi;711712n = inverse - i;713m = inverse - j;714715// COMPLEX: SWAP(data[n], data[m])716// Real Part717tempr = data[n];718data[n] = data[m];719data[m] = tempr;720// Imagery Part721n++;722m++;723tempi = data[n];724data[n] = data[m];725data[m] = tempi;726}727728// Performing Bit-Reversal, odd v.s. even, O(N)729730int m = j + fftFrameSize; // bitm_array[i+2];731// COMPLEX: SWAP(data[n], data[m])732// Real Part733int n = i + 2;734double tempr = data[n];735data[n] = data[m];736data[m] = tempr;737// Imagery Part738n++;739m++;740double tempi = data[n];741data[n] = data[m];742data[m] = tempi;743}744}745}746747748