【问题标题】:Calculate FFT from audio file从音频文件计算 FFT
【发布时间】:2013-07-08 01:34:40
【问题描述】:

之前,我问过关于Get frequency wav audio using FFT and Complex class的问题,

在那里,我需要从 AudioRecord 输入计算 FFT 值 --> 从麦克风,我设法得到了 FFT 值...

现在我需要从之前保存的 *.wav 音频文件中计算 FFT 值, 我将音频保存在项目中“res”文件夹内的“raw”文件夹中

我仍在使用相同的 FFT 类:http://www.cs.princeton.edu/introcs/97data/FFT.java

与之配套的复杂类:http://introcs.cs.princeton.edu/java/97data/Complex.java.html

我使用这个方法从我的原始文件夹中读取音频文件,然后我调用方法 calculateFFT 来处理它

private static final int RECORDER_BPP = 16;
  private static final int RECORDER_SAMPLERATE = 44100;
  private static final int RECORDER_CHANNELS = AudioFormat.CHANNEL_IN_STEREO;
  private static final int RECORDER_AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;


private void asli(){

            int counter = 0;
            int data;
            InputStream inputStream  = getResources().openRawResource(R.raw.b1);
            DataInputStream dataInputStream = new DataInputStream(inputStream);
            List<Integer> content = new ArrayList<Integer>(); 

            try {
                while ((data = dataInputStream.read()) != -1) {
                    content.add(data);
                    counter++; }
            } catch (IOException e) {
                e.printStackTrace();}

                int[] b = new int[content.size()];
                int cont = 0;
                byte[] audio = convertArray(b);
        }

转成字节的方法

public byte[] convertArray(int[] array) { 

            int minBufferSize = AudioTrack.getMinBufferSize(RECORDER_SAMPLERATE,RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING);
                AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,RECORDER_SAMPLERATE,RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING,minBufferSize, AudioTrack.MODE_STREAM);

        byte[] newarray = new byte[array.length];
        for (int i = 0; i < array.length; i++) {
        newarray[i] = (byte) ((array[i]) & 0xFF);       }

            absNormalizedSignal = calculateFFT(newarray);
            return newarray;
        }

这就是CalculateFFT方法

public double[] calculateFFT(byte[] signal)
        {           
            final int mNumberOfFFTPoints =1024;
            double mMaxFFTSample;
            double temp;
            Complex[] y;
            Complex[] complexSignal = new Complex[mNumberOfFFTPoints];
            double[] absSignal = new double[mNumberOfFFTPoints/2];

            for(int i = 0; i < mNumberOfFFTPoints; i++){
                temp = (double)((signal[2*i] & 0xFF) | (signal[2*i+1] << 8)) / 32768.0F;
                complexSignal[i] = new Complex(temp,0.0);
            }

            y = FFT.fft(complexSignal);

            mMaxFFTSample = 0.0;
            mPeakPos = 0;
            for(int i = 0; i < (mNumberOfFFTPoints/2); i++)
            {
                 absSignal[i] = Math.sqrt(Math.pow(y[i].re(), 2) + Math.pow(y[i].im(), 2));
                 if(absSignal[i] > mMaxFFTSample)
                 {
                     mMaxFFTSample = absSignal[i];
                     mPeakPos = i;
                 } 
            }

            return absSignal;

        }

我也使用这个 CalculateFFT 方法来处理来自 AudioRecorder 的音频 --> 之前有麦克风输入的那个...我设法从 AudioRecorder 中获得价值,但我未能从我的音频文件中获得价值...我'我不打算播放音频。我只需要用 FFT 处理它。

我的代码有什么问题吗? :o 似乎我无法从方法 Asli(); 中获取价值;但我不知道哪一部分错了..

任何帮助将不胜感激... :) 谢谢

【问题讨论】:

  • 您刚刚发布了很多代码,但是对于您的代码失败的原因以及您已经尝试解决的问题的描述非常不清楚。
  • @Marko 对此我很抱歉.. :( 由于我阅读了很多问题而没有通过正确的代码,所以人们投票否决了.. 我的代码失败的描述非常不清楚 --> 我已经写过我无法从我的音频文件中获取价值...用 FFT 处理它。我已经尝试过的是 --> 方法 asli() 我尝试使用 InputStream inputStream =getResources().openRawResource(R.raw .b1); DataInputStream dataInputStream = new DataInputStream(inputStream); 然后我用缓冲区大小读取数组数据,但我似乎失败了
  • RIFF/WAV 文件中的样本通常存储为 16 位 little-endian 有符号整数,而不是字节或双精度数。所以你可能会错过类型转换。
  • 我认为 hotpaw 是正确的。此外,我没有看到任何解析 wav 文件格式的代码。我可能误读了,但看起来您只是打开文件并将原始字节传递给 fft 函数。您可以阅读有关如何解析 wav 文件或使用 java 解析它们的信息。我相信这里有更多信息:jsresources.org
  • @hotpaw2 非常感谢您的更正.. :) ,所以现在我必须先解析它。我在这个音频处理方面真的很新……你的回答很有帮助。谢谢

标签: java audio fft audiotrack


【解决方案1】:

我花了一大半早上的时间使用我找到的 FFT java sn-ps 的零碎代码来编写解决方案……但后来我偶然发现了这个非常棒的谷歌代码项目,它有一堆实用程序类用于对 WAV 和 MP3 文件进行信号处理任务。

https://github.com/Uriopass/audio-analysis 以前 SVN 导出在 Google 代码上:https://storage.googleapis.com/google-code-archive-source/v2/code.google.com/audio-analysis/source-archive.zip

现在变得非常简单:

WaveDecoder decoder = new WaveDecoder(new FileInputStream(wavFile));
FFT fft = new FFT(1024, wavFileObj.getSampleRate());

现在您可以使用 fft 对象进行各种计算。他们有很多很好的例子,比如生成一个包含光谱通量的列表:

    float[] samples = new float[1024];
    float[] spectrum = new float[1024 / 2 + 1];
    float[] lastSpectrum = new float[1024 / 2 + 1];
    List<Float> spectralFlux = new ArrayList<Float>();

    while (decoder.readSamples(samples) > 0) {
        fft.forward(samples);
        System.arraycopy(spectrum, 0, lastSpectrum, 0, spectrum.length);
        System.arraycopy(fft.getSpectrum(), 0, spectrum, 0, spectrum.length);

        float flux = 0;
        for (int i = 0; i < spectrum.length; i++)
            flux += (spectrum[i] - lastSpectrum[i]);
        spectralFlux.add(flux);
    }

我的公司需要一种方法让我分析一些音频,看看是否发生了一些预期的保持音乐。所以首先我为一个确实有保持音乐的例子生成了一个 WAV 文件。然后我捕获了其中一个没有保持音乐的示例的一些音频。现在剩下的就是平均 wav 的光谱通量,我已经准备好了。

注意:我不能简单地获取幅度...但是傅立叶变换具有我可以正确使用的频率来进行比较。

我喜欢数学。

【讨论】:

  • 他们的结帐链接无效,即audio-analysis.googlecode.com/svn/trunk/…
  • 我是用git url克隆的,但是库里只有两个类:RealDoubleFFT.java和RealDoubleFFT_Mixed.java。找不到 WaveDecoder 类。
  • 对数学的热爱 +1 :D
  • 你从哪里得到wavFileObj?你从哪里得到WaveDecoder?您编写了一些代码,但没有用。请解释更多...
  • 为了将来参考,答案中的原始链接已经失效,因为谷歌关闭了几乎所有的谷歌代码项目。幸运的是,我克隆了这个库,然后它就在这里注定要失败:github.com/Uriopass/audio-analysis
猜你喜欢
  • 2013-04-10
  • 2011-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-09
  • 2011-02-05
相关资源
最近更新 更多