10

以前、 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);
        }

バイトに変換する方法

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(); からの値の取得に失敗したようです。でも、どこが悪いのかわからない…

助けていただければ幸いです... :)ありがとう

4

1 に答える 1

11

見つけたFFT Javaスニペットの断片を使用して、午前中の大部分をこのソリューションのコーディングに費やしました...しかし、信号処理タスクを実行するためのユーティリティクラスがたくさんあるこの驚くほど素晴らしいGoogleコードプロジェクトに出くわしました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 ファイルを生成しました。次に、ホールド ミュージックのない 3 つの例の 1 つのオーディオをキャプチャしました。あとは、wav のスペクトル フラックスを平均化するだけです。

注: 単純に振幅を取得することはできませんでした... しかし、フーリエ変換には、比較を行うために正しく使用できる周波数があります。

私は数学が大好きです。

于 2014-09-29T18:41:25.703 に答える