从音频文件计算FFT

rai*_*sa_ 7 java audio fft audiotrack

之前,我问过使用FFT和Complex类获取频率wav音频的问题,

在那里,我需要从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);
        }
Run Code Online (Sandbox Code Playgroud)

转换为字节的方法

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;
        }
Run Code Online (Sandbox Code Playgroud)

这是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;

        }
Run Code Online (Sandbox Code Playgroud)

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

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

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

Nic*_*zza 6

我花了一个较大的时间来编写一个解决方案,使用我发现的一些FFT java片段......然后我偶然发现了这个令人惊讶的google代码项目,它有一堆用于执行信号处理任务的util类在WAV和MP3文件上都一样.

https://github.com/Uriopass/audio-analysis 以前在这里使用Google代码进行SVN导出:https://storage.googleapis.com/google-code-archive-source/v2/code.google.com/audio-分析/ source-archive.zip

它现在变得很容易:

WaveDecoder decoder = new WaveDecoder(new FileInputStream(wavFile));
FFT fft = new FFT(1024, wavFileObj.getSampleRate());
Run Code Online (Sandbox Code Playgroud)

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

    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);
    }
Run Code Online (Sandbox Code Playgroud)

我的公司需要一种方法让我分析一些音频,看看是否有一些预期的音乐发生了.所以首先我为一个有保持音乐的例子生成了一个WAV文件.然后我捕获了一些没有保持音乐的例子的音频.现在剩下的就是平均wav的光谱通量并且我设置了.

注意:我不能简单地采取振幅......但傅立叶变换具有我可以正确用于进行比较的频率.

我爱数学.

  • 你从哪里得到`wavFileObj`?你从哪里得到`WaveDecoder`?你写了一些代码和平但没用.请解释更多...... (2认同)