原文资源在此:http://www.ee.columbia.edu/~ronw/code/MEAPsoft/doc/html/files.html

等会我试试效果如何?与我想要的有没有差别。完全公开。良心博文。

00023 package com.meapsoft;
00024
00025
00033 public class FFT {
00034
00035   int n, m;
00036
00037   // Lookup tables.  Only need to recompute when size of FFT changes.
00038   double[] cos;
00039   double[] sin;
00040
00041   double[] window;
00042
00043   public FFT(int n) {
00044     this.n = n;
00045     this.m = (int)(Math.log(n) / Math.log(2));
00046
00047     // Make sure n is a power of 2
00048     if(n != (1<<m))
00049       throw new RuntimeException("FFT length must be power of 2");
00050
00051     // precompute tables
00052     cos = new double[n/2];
00053     sin = new double[n/2];
00054
00055 //     for(int i=0; i<n/4; i++) {
00056 //       cos[i] = Math.cos(-2*Math.PI*i/n);
00057 //       sin[n/4-i] = cos[i];
00058 //       cos[n/2-i] = -cos[i];
00059 //       sin[n/4+i] = cos[i];
00060 //       cos[n/2+i] = -cos[i];
00061 //       sin[n*3/4-i] = -cos[i];
00062 //       cos[n-i]   = cos[i];
00063 //       sin[n*3/4+i] = -cos[i];
00064 //     }
00065
00066     for(int i=0; i<n/2; i++) {
00067       cos[i] = Math.cos(-2*Math.PI*i/n);
00068       sin[i] = Math.sin(-2*Math.PI*i/n);
00069     }
00070
00071     makeWindow();
00072   }
00073
00074   protected void makeWindow() {
00075     // Make a blackman window:
00076     // w(n)=0.42-0.5cos{(2*PI*n)/(N-1)}+0.08cos{(4*PI*n)/(N-1)};
00077     window = new double[n];
00078     for(int i = 0; i < window.length; i++)
00079       window[i] = 0.42 - 0.5 * Math.cos(2*Math.PI*i/(n-1))
00080         + 0.08 * Math.cos(4*Math.PI*i/(n-1));
00081   }
00082
00083   public double[] getWindow() {
00084     return window;
00085   }
00086
00087
00088   /***************************************************************
00089   * fft.c
00090   * Douglas L. Jones
00091   * University of Illinois at Urbana-Champaign
00092   * January 19, 1992
00093   * http://cnx.rice.edu/content/m12016/latest/
00094   *
00095   *   fft: in-place radix-2 DIT DFT of a complex input
00096   *
00097   *   input:
00098   * n: length of FFT: must be a power of two
00099   * m: n = 2**m
00100   *   input/output
00101   * x: double array of length n with real part of data
00102   * y: double array of length n with imag part of data
00103   *
00104   *   Permission to copy and use this program is granted
00105   *   as long as this header is included.
00106   ****************************************************************/
00107   public void fft(double[] x, double[] y)
00108   {
00109     int i,j,k,n1,n2,a;
00110     double c,s,e,t1,t2;
00111
00112
00113     // Bit-reverse
00114     j = 0;
00115     n2 = n/2;
00116     for (i=1; i < n - 1; i++) {
00117       n1 = n2;
00118       while ( j >= n1 ) {
00119         j = j - n1;
00120         n1 = n1/2;
00121       }
00122       j = j + n1;
00123
00124       if (i < j) {
00125         t1 = x[i];
00126         x[i] = x[j];
00127         x[j] = t1;
00128         t1 = y[i];
00129         y[i] = y[j];
00130         y[j] = t1;
00131       }
00132     }
00133
00134     // FFT
00135     n1 = 0;
00136     n2 = 1;
00137
00138     for (i=0; i < m; i++) {
00139       n1 = n2;
00140       n2 = n2 + n2;
00141       a = 0;
00142
00143       for (j=0; j < n1; j++) {
00144         c = cos[a];
00145         s = sin[a];
00146         a +=  1 << (m-i-1);
00147
00148         for (k=j; k < n; k=k+n2) {
00149           t1 = c*x[k+n1] - s*y[k+n1];
00150           t2 = s*x[k+n1] + c*y[k+n1];
00151           x[k+n1] = x[k] - t1;
00152           y[k+n1] = y[k] - t2;
00153           x[k] = x[k] + t1;
00154           y[k] = y[k] + t2;
00155         }
00156       }
00157     }
00158   }
00159
00160
00161
00162
00163   // Test the FFT to make sure it's working
00164   public static void main(String[] args) {
00165     int N = 8;
00166
00167     FFT fft = new FFT(N);
00168
00169     double[] window = fft.getWindow();
00170     double[] re = new double[N];
00171     double[] im = new double[N];
00172
00173     // Impulse
00174     re[0] = 1; im[0] = 0;
00175     for(int i=1; i<N; i++)
00176       re[i] = im[i] = 0;
00177     beforeAfter(fft, re, im);
00178
00179     // Nyquist
00180     for(int i=0; i<N; i++) {
00181       re[i] = Math.pow(-1, i);
00182       im[i] = 0;
00183     }
00184     beforeAfter(fft, re, im);
00185
00186     // Single sin
00187     for(int i=0; i<N; i++) {
00188       re[i] = Math.cos(2*Math.PI*i / N);
00189       im[i] = 0;
00190     }
00191     beforeAfter(fft, re, im);
00192
00193     // Ramp
00194     for(int i=0; i<N; i++) {
00195       re[i] = i;
00196       im[i] = 0;
00197     }
00198     beforeAfter(fft, re, im);
00199
00200     long time = System.currentTimeMillis();
00201     double iter = 30000;
00202     for(int i=0; i<iter; i++)
00203       fft.fft(re,im);
00204     time = System.currentTimeMillis() - time;
00205     System.out.println("Averaged " + (time/iter) + "ms per iteration");
00206   }
00207
00208   protected static void beforeAfter(FFT fft, double[] re, double[] im) {
00209     System.out.println("Before: ");
00210     printReIm(re, im);
00211     fft.fft(re, im);
00212     System.out.println("After: ");
00213     printReIm(re, im);
00214   }
00215
00216   protected static void printReIm(double[] re, double[] im) {
00217     System.out.print("Re: [");
00218     for(int i=0; i<re.length; i++)
00219       System.out.print(((int)(re[i]*1000)/1000.0) + " ");
00220
00221     System.out.print("]\nIm: [");
00222     for(int i=0; i<im.length; i++)
00223       System.out.print(((int)(im[i]*1000)/1000.0) + " ");
00224
00225     System.out.println("]");
00226   }
00227 }

STFT在此:

00023 package com.meapsoft;
00024
00025 import java.io.IOException;
00026 import java.util.ArrayList;
00027 import java.util.Arrays;
00028
00029 import javax.sound.sampled.AudioFormat;
00030 import javax.sound.sampled.AudioInputStream;
00031
00039 public class STFT {
00040   AudioInputStream input;
00041   AudioFormat format;
00042   int bytesPerWavFrame, frameLen;
00043   ArrayList listeners = new ArrayList();
00044   double[] re, im, window;
00045   static double log10 = Math.log(10);
00046   static double epsilon = 1e-9;       // avoid log of zero
00047   RingMatrix freq, time;
00048   FFT fft;
00049
00050   static double rmsTarget = 0.08;
00051   static double rmsAlpha = 0.001;
00052   double rms = 1;
00053
00054   public float samplingRate;
00055   public int nhop;
00056
00057   // The line should be open, but not started yet.
00058   public STFT(AudioInputStream input, int frameLen, int hopsize, int history) {
00059     this(input, frameLen, history);
00060
00061     nhop = hopsize;
00062   }
00063
00064   // The line should be open, but not started yet.
00065   public STFT(AudioInputStream input, int frameLen, int history) {
00066     freq = new RingMatrix(frameLen/2+1, history);
00067     time = new RingMatrix(frameLen, history);
00068     this.frameLen = frameLen;
00069
00070     this.input = input;
00071     format = input.getFormat();
00072     bytesPerWavFrame = format.getFrameSize();
00073
00074     samplingRate = format.getSampleRate();
00075
00076     fft = new FFT(frameLen);
00077
00078     this.re = new double[frameLen];
00079     this.im = new double[frameLen];
00080     this.window = fft.getWindow();
00081     for(int i=0; i<im.length; i++)
00082       im[i] = 0;
00083
00084     nhop = frameLen;
00085
00086     samplingRate = input.getFormat().getSampleRate();
00087   }
00088
00089   // returns the total number of bytes read
00090   public long start() {
00091       byte[] b = new byte[bytesPerWavFrame * frameLen];
00092       Arrays.fill(b, (byte)0);
00093
00094       int noverlapBytes = (frameLen-nhop)*bytesPerWavFrame;
00095       int nhopBytes = nhop*bytesPerWavFrame;
00096
00097       int totalBytesRead = 0;
00098       int bytesRead = 22;
00099       while(bytesRead > 0) {
00100           if(nhop > 0)
00101           {
00102               // shift b so our overlap works out
00103               for(int x = 0; x < noverlapBytes; x++)
00104                   b[x] = b[x+nhopBytes];
00105           }
00106
00107           try {
00108               bytesRead = input.read(b, noverlapBytes, nhopBytes);
00109               totalBytesRead += bytesRead;
00110           } catch(IOException ioe) {
00111               ioe.printStackTrace();
00112               return totalBytesRead;
00113           }
00114
00115           // store the unwindowed waveform for getSamples function
00116           double[] wav = time.checkOutColumn();
00117           bytes2doubles(b, wav);
00118
00119           // Normalize rms using a moving average estimate of it
00120           // Calculate current rms
00121           double rmsCur = 0;
00122           for(int i=0; i<wav.length; i++)
00123               rmsCur += wav[i]*wav[i];
00124           rmsCur = Math.sqrt(rmsCur / wav.length);
00125
00126           // update moving average
00127           rms = rmsAlpha*rmsCur + (1-rmsAlpha)*rms;
00128
00129           // normalize by rms
00130           for(int i=0; i<wav.length; i++)
00131               wav[i] = wav[i] * rmsTarget / rms;
00132
00133           time.checkInColumn(wav);
00134
00135           // window waveform
00136           for(int i=0; i<wav.length; i++)
00137               re[i] = window[i] * wav[i];
00138
00139           // take fft
00140           fft.fft(re, im);
00141
00142           // Calculate magnitude
00143           double[] mag = freq.checkOutColumn();
00144           for(int i=0; i<mag.length; i++)
00145               mag[i] = 10*Math.log(re[i]*re[i] + im[i]*im[i] + epsilon) / log10;
00146
00147           // clear im[]
00148           Arrays.fill(im, 0);
00149
00150           // Tell everyone concerned that we've added another frame
00151           long frAddr = freq.checkInColumn(mag);
00152           notifyListeners(frAddr);
00153       }
00154
00155       // let the frame listeners know that we're done reading:
00156       notifyListeners(-1);
00157
00158       return totalBytesRead;
00159   }
00160
00161
00162   // Get the waveform samples from frames frStart to frEnd-1
00163   public double[] getSamples(long frStart, long frEnd) {
00164     long sampStart = fr2Samp(frStart);
00165     long sampEnd = fr2Samp(frEnd);
00166
00167     double[] x = new double[(int)(sampEnd - sampStart)];
00168
00169     for(int fr=0; fr < frEnd-frStart; fr++) {
00170         double[] frame = time.getColumn(frStart+fr);
00171         if(frame == null) continue;
00172         // only the first nhop samples of frame are valid
00173         for(int i=0; i<nhop; i++)
00174             x[(int)(fr2Samp(fr+frStart)-sampStart + i)] = frame[i];
00175     }
00176
00177     return x;
00178   }
00179
00180   // Convert an address in frames into an address in samples
00181   public long fr2Samp(long frAddr) {
00182     return nhop * frAddr;
00183   }
00184
00185   // Convert an address in samples into an address in frames
00186   public long samp2fr(long sampAddr) {
00187     return sampAddr/nhop;
00188   }
00189
00190   public double[] getFrame(long frAddr) { return freq.getColumn(frAddr); }
00191   public void setFrame(long frAddr, double[] dat) { freq.setColumn(frAddr, dat); }
00192   public int getColumns() { return freq.getColumns(); }
00193   public int getRows() { return freq.getRows(); }
00194
00195   // Dealing with FrameListeners
00196   public void addFrameListener(FrameListener fl) {
00197     listeners.add(fl);
00198   }
00199   public void removeFrameListener(FrameListener fl) {
00200     listeners.remove(fl);
00201   }
00202   public void notifyListeners(long frAddr) {
00203     for(int i=0; i<listeners.size(); i++) {
00204       FrameListener list = (FrameListener) listeners.get(i);
00205       list.newFrame(this, frAddr);
00206     }
00207   }
00208
00209
00210   // Convert a byte stream into a stream of doubles.  If it's stereo,
00211   // the channels will be interleaved with each other in the double
00212   // stream, as in the byte stream.
00213   public void bytes2doubles(byte[] audioBytes, double[] audioData) {
00214     if (format.getSampleSizeInBits() == 16) {
00215       if (format.isBigEndian()) {
00216         for (int i = 0; i < audioData.length; i++) {
00217           /* First byte is MSB (high order) */
00218           int MSB = (int) audioBytes[2*i];
00219           /* Second byte is LSB (low order) */
00220           int LSB = (int) audioBytes[2*i+1];
00221           audioData[i] = ((double)(MSB << 8 | (255 & LSB)))
00222             / 32768.0;
00223         }
00224       } else {
00225         for (int i = 0; i < audioData.length; i++) {
00226           /* First byte is LSB (low order) */
00227           int LSB = (int) audioBytes[2*i];
00228           /* Second byte is MSB (high order) */
00229           int MSB = (int) audioBytes[2*i+1];
00230           audioData[i] = ((double)(MSB << 8 | (255 & LSB)))
00231             / 32768.0;
00232         }
00233       }
00234     } else if (format.getSampleSizeInBits() == 8) {
00235       int nlengthInSamples = audioBytes.length;
00236       if (format.getEncoding().toString().startsWith("PCM_SIGN")) {
00237         for (int i = 0; i < audioBytes.length; i++) {
00238           audioData[i] = audioBytes[i] / 128.0;
00239         }
00240       } else {
00241         for (int i = 0; i < audioBytes.length; i++) {
00242           audioData[i] = (audioBytes[i] - 128) / 128.0;
00243         }
00244       }
00245     }
00246   }
00247
00248   // Convert an address in frames to an address in seconds
00249   public double fr2Seconds(long frAddr)
00250   {
00251       return(fr2Samp(frAddr)/samplingRate);
00252   }
00253
00254   // Convert an address in seconds to an address in frames
00255   public long seconds2fr(double sec)
00256   {
00257       return(samp2fr((long)(sec*samplingRate)));
00258   }
00259
00260
00264   public static RingMatrix getSTFT(double[] samples, int nfft)
00265   {
00266       return STFT.getSTFT(samples, nfft, nfft);
00267   }
00268
00272   public static RingMatrix getSTFT(double[] samples, int nfft, int nhop)
00273   {
00274       RingMatrix freq = new RingMatrix(nfft/2+1, samples.length/nhop);
00275
00276       FFT fft = new FFT(nfft);
00277       double[] window = fft.getWindow();
00278
00279       double[] wav = new double[nfft];
00280       double rms = 1;
00281       for(int currFrame = 0; currFrame < samples.length/nhop; currFrame++)
00282       {
00283           // zero pad if we run out of samples:
00284           int zeroPadLen = currFrame*nhop + wav.length - samples.length;
00285           if(zeroPadLen < 0)
00286               zeroPadLen = 0;
00287           int wavLen = wav.length - zeroPadLen;
00288
00289           //for(int i = 0; i<wav.length; i++)
00290           //    wav[i] = samples[currFrame*nhop + i];
00291           for(int i = 0; i < wavLen; i++)
00292               wav[i] = samples[currFrame*nhop + i];
00293           for(int i = wavLen; i < wav.length; i++)
00294               wav[i] = 0;
00295
00296           // Normalize rms using a moving average estimate of it
00297           // Calculate current rms
00298           double rmsCur = 0;
00299           for(int i=0; i<wav.length; i++)
00300               rmsCur += wav[i]*wav[i];
00301           rmsCur = Math.sqrt(rmsCur / wav.length);
00302
00303           // update moving average
00304           rms = rmsAlpha*rmsCur + (1-rmsAlpha)*rms;
00305
00306           // normalize by rms
00307           for(int i=0; i<wav.length; i++)
00308               wav[i] = wav[i] * rmsTarget / rms;
00309
00310           // window waveform
00311           double[] re = new double[wav.length];
00312           double[] im = new double[wav.length];
00313           for(int i=0; i<wav.length; i++)
00314           {
00315               re[i] = window[i] * wav[i];
00316               im[i] = 0;
00317           }
00318
00319           // take fft
00320           fft.fft(re, im);
00321
00322           // Calculate magnitude
00323           double[] mag = freq.checkOutColumn();
00324           for(int i=0; i<mag.length; i++)
00325               mag[i] = 10*Math.log(re[i]*re[i] + im[i]*im[i] + epsilon) / log10;
00326
00327           freq.checkInColumn(mag);
00328       }
00329
00330       return freq;
00331   }
00332
00333
00342   public int readFrames(long nframes)
00343   {
00344       byte[] b = new byte[bytesPerWavFrame * frameLen];
00345       Arrays.fill(b, (byte)0);
00346
00347       int noverlapBytes = (frameLen-nhop)*bytesPerWavFrame;
00348       int nhopBytes = nhop*bytesPerWavFrame;
00349
00350       int bytesRead = 22;
00351       int nFramesRead = 0;
00352       while(nFramesRead <= nframes)
00353       {
00354           if(nhop > 0)
00355           {
00356               // shift b so our overlap works out
00357               for(int x = 0; x < noverlapBytes; x++)
00358                   b[x] = b[x+nhopBytes];
00359           }
00360
00361           try
00362           {
00363               input.read(b, noverlapBytes, nhopBytes);
00364               nFramesRead++;
00365           }
00366           catch(IOException ioe)
00367           {
00368               ioe.printStackTrace();
00369               return nFramesRead;
00370           }
00371
00372           // store the unwindowed waveform for getSamples function
00373           double[] wav = time.checkOutColumn();
00374           bytes2doubles(b, wav);
00375
00376           // Normalize rms using a moving average estimate of it
00377           // Calculate current rms
00378           double rmsCur = 0;
00379           for(int i=0; i<wav.length; i++)
00380               rmsCur += wav[i]*wav[i];
00381           rmsCur = Math.sqrt(rmsCur / wav.length);
00382
00383           // update moving average
00384           rms = rmsAlpha*rmsCur + (1-rmsAlpha)*rms;
00385
00386           // normalize by rms
00387           for(int i=0; i<wav.length; i++)
00388               wav[i] = wav[i] * rmsTarget / rms;
00389
00390           time.checkInColumn(wav);
00391
00392           // window waveform
00393           for(int i=0; i<wav.length; i++)
00394               re[i] = window[i] * wav[i];
00395
00396           // take fft
00397           fft.fft(re, im);
00398
00399           // Calculate magnitude
00400           double[] mag = freq.checkOutColumn();
00401           for(int i=0; i<mag.length; i++)
00402               mag[i] = 10*Math.log(re[i]*re[i] + im[i]*im[i] + epsilon) / log10;
00403
00404           // clear im[]
00405           Arrays.fill(im, 0);
00406
00407           // Tell everyone concerned that we've added another frame
00408           long frAddr = freq.checkInColumn(mag);
00409           notifyListeners(frAddr);
00410       }
00411
00412       return nFramesRead;
00413   }
00414
00418   public long getLastFrameAddress()
00419   {
00420       return freq.nextFrAddr-1;
00421   }
00422
00423   public void stop() throws IOException
00424   {
00425       input.close();
00426   }
00427 }

另外有相关问题可以加入QQ群讨论,不设微信群

QQ群:868373192

语音深度学习群

java版FFT/STFT——转载相关推荐

  1. 服务端工程师入门与进阶 Java 版

    前言 欢迎加入我们.这是一份针对实习生/毕业生的服务端开发入门与进阶指南.遇到问题及时问你的 mentor 或者直接问我. 建议: 尽量用google查找技术资料. 有问题在stackoverflow ...

  2. base64转码java版

    base64转码java版 package com.net.util;import java.io.FileInputStream; import java.io.FileOutputStream; ...

  3. Java版 QQ空间自动登录无需拷贝cookie一天抓取30WQQ说说数据流程分析【转】

    Java版 QQ空间自动登录无需拷贝cookie一天抓取30WQQ说说数据&流程分析 QQ空间说说抓取难度比较大,花了一个星期才研究清楚! 代码请移步到GitHub GitHub地址:http ...

  4. 线索二叉树原理及前序、中序线索化(Java版)

    转载 原文地址:https://blog.csdn.net/UncleMing5371/article/details/54176252 一.线索二叉树原理 前面介绍二叉树原理及特殊二叉树文章中提到, ...

  5. 【java项目实践】具体解释Ajax工作原理以及实现异步验证username是否存在+源代码下载(java版)...

    一年前,从不知道Ajax是什么,伴随着不断的积累,到如今常常使用,逐渐有了深入的认识. 今天,假设想开发一个更加人性化,友好,无刷新,交互性更强的网页,那您的目标一定是Ajax. 介绍 在具体讨论Aj ...

  6. JAVA版StarDict星际译王简单实现

    由胡正开发的星际译王是Linux平台上很强大的一个开源的翻译软件(也有Windows版本的)支持多种词库.多种语言版本.尤其词库设计比较合理.之前看到一篇博文<星际译王词库应用-自制英汉词典&g ...

  7. Java版世界时钟示例

    Java版世界时钟示例 这是一个Java版的世界时钟示例,移植自Gerrit创建的同名Swing应用(http://www.jug-muenster.de/swing-worldclock-427 ) ...

  8. 经典十大排序算法(含升序降序,基数排序含负数排序)【Java版完整代码】【建议收藏系列】

    经典十大排序算法[Java版完整代码] 写在前面的话 十大排序算法对比 冒泡排序 快速排序 直接选择排序 堆排序 归并排序 插入排序 希尔排序 计数排序 桶排序 基数排序 完整测试类 写在前面的话   ...

  9. 20165234 [第二届构建之法论坛] 预培训文档(Java版) 学习总结

    [第二届构建之法论坛] 预培训文档(Java版) 学习总结 我通读并学习了此文档,并且动手实践了一遍.以下是我学习过程的记录~ Part1.配置环境 配置JDK 原文中提到了2个容易被混淆的概念 JD ...

最新文章

  1. 万万没想到 I 这 7 件超酷的事情,让开发更有效率
  2. 箱线图怎么判断异常值_原创【六西格玛工具解读】02——箱线图(Boxplot)
  3. redis的观察者模式----------发布订阅功能
  4. 八大排序算法的 Python 实现
  5. Redis介绍及部署在CentOS7上(一) 1
  6. 所有特征在不同分类之间、 train和test之间的列分布差异(图形绘制)
  7. 第十节:进一步扩展两种安全校验方式
  8. linux mysql提示1045_linux mysql ERROR 1045
  9. 数据结构之线索二叉树
  10. DSO 中的Windowed Optimization
  11. idea之springboot端口被占用/跳转到login
  12. keras的训练引擎:train_array.py和train_generator.py
  13. CCF NOI1041 志愿者选拔
  14. MySQL 中文的乱码问题
  15. android下最强的3款pdf阅读器测评
  16. 01_测试基础知识---功能测试常用方法/正交表的使用
  17. 【重识云原生】第三章云存储第一节——分布式云存储总述
  18. 音视频中的语音信号处理技术
  19. 怎样把自己喜欢的微信表情包(动态)导出来,我三岁半的表弟都会...
  20. 国内硕士申请加拿大计算机博士难度,加拿大硕士和博士真的那么难申请吗?

热门文章

  1. 前端引入icon的方法(iconfont,fontawesome)
  2. vue H5页面调用手机相机拍照/图库上传
  3. 导师喜欢什么样的“真”研究生?(转科学网)
  4. EXCEL将一个单元格分成3个区域
  5. 【记录】前端知识点 - Vue
  6. IP伪装ddos攻击
  7. 企业抖音号怎么运营矩阵?运营有何技巧?
  8. 雪球产品,场外雪球结构介绍
  9. js阿拉伯数字转中文汉字小写 支持到12位
  10. C语言入门 | c语言基础知识