Holen Sie sich Frequenz-WAV-Audio mit FFT und Complex-Klasse

Es wurde oft nachgefragt, aber ich bin immer noch bei der Implementierung der FFT-Klasse auf Android geblieben. Ich muss meine Audiodaten mit FFT verarbeiten ...

Die fast gleiche Frage habe ich hier schon gelesenWie kann ich mit FFT Frequenzdaten von PCM abrufen? und hierWie erhalte ich die Frequenz aus dem FFT-Ergebnis? und noch mehr Fragen, aber ich finde immer noch keine Antwort, selbst nachdem ich die gegebenen Antworten ausprobiert habe ...

FFT-Klasse, die ich benutze:http://www.cs.princeton.edu/introcs/97data/FFT.java

Die komplexe Klasse dazu:http://introcs.cs.princeton.edu/java/97data/Complex.java.html

Hier ist mein Code

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;

public class Latihan extends Activity{
        private static final int RECORDER_BPP = 16;
        private static final String AUDIO_RECORDER_FILE_EXT_WAV = ".wav";
        private static final String AUDIO_RECORDER_FOLDER = "AudioRecorder";
        private static final String AUDIO_RECORDER_TEMP_FILE = "record_temp.raw";
        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;
        short[] audioData;

        private AudioRecord recorder = null;
        private int bufferSize = 0;
        private Thread recordingThread = null;
        private boolean isRecording = false;
        Complex[] fftTempArray;
        Complex[] fftArray;
        int[] bufferData;
        int bytesRecorded;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.p1);

        setButtonHandlers();
        enableButtons(false);

        bufferSize = AudioRecord.getMinBufferSize
                (RECORDER_SAMPLERATE,RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING)*3;

        audioData = new short [bufferSize]; //short array that pcm data is put into.

        }


    private void setButtonHandlers() {
        ((Button)findViewById(R.id.btStart)).setOnClickListener(btnClick);
        ((Button)findViewById(R.id.btStop)).setOnClickListener(btnClick);
        }


        private void enableButton(int id,boolean isEnable){
                ((Button)findViewById(id)).setEnabled(isEnable);
        }

        private void enableButtons(boolean isRecording) {
                enableButton(R.id.btStart,!isRecording);
                enableButton(R.id.btStop,isRecording);
        }

        private String getFilename(){
                String filepath = Environment.getExternalStorageDirectory().getPath();
                File file = new File(filepath,AUDIO_RECORDER_FOLDER);

                if(!file.exists()){
                        file.mkdirs();
                }

                return (file.getAbsolutePath() + "/" + System.currentTimeMillis() + AUDIO_RECORDER_FILE_EXT_WAV);
        }


        public void convert(){



        }

        public void calculate(){
            Complex[] fftTempArray = new Complex[bufferSize];
            for (int i=0; i<bufferSize; i++)
            {
                fftTempArray[i] = new Complex(audioData[i], 0);
            }
            Complex[] fftArray = FFT.fft(fftTempArray);

            double[] micBufferData = new double[bufferSize];
            final int bytesPerSample = 2; 
            final double amplification = 100.0; 
            for (int index = 0, floatIndex = 0; index < bytesRecorded - bytesPerSample + 1; index += bytesPerSample, floatIndex++) {
                double sample = 0;
                for (int b = 0; b < bytesPerSample; b++) {
                    int v = bufferData[index + b];
                    if (b < bytesPerSample - 1 || bytesPerSample == 1) {
                        v &= 0xFF;
                    }
                    sample += v << (b * 8);
                }
                double sample32 = amplification * (sample / 32768.0);
                micBufferData[floatIndex] = sample32;
            }


     }


        private String getTempFilename(){
                String filepath = Environment.getExternalStorageDirectory().getPath();
                File file = new File(filepath,AUDIO_RECORDER_FOLDER);

                if(!file.exists()){
                        file.mkdirs();
                }

                File tempFile = new File(filepath,AUDIO_RECORDER_TEMP_FILE);

                if(tempFile.exists())
                        tempFile.delete();

                return (file.getAbsolutePath() + "/" + AUDIO_RECORDER_TEMP_FILE);
        }

        private void startRecording(){
            recorder = new AudioRecord(MediaRecorder.AudioSource.MIC,
                                                RECORDER_SAMPLERATE, RECORDER_CHANNELS,RECORDER_AUDIO_ENCODING, bufferSize);

                recorder.startRecording();

                isRecording = true;

                recordingThread = new Thread(new Runnable() {

                        public void run() {
                                writeAudioDataToFile();
                        }
                },"AudioRecorder Thread");

                recordingThread.start();
        }

        private void writeAudioDataToFile(){
                byte data[] = new byte[bufferSize];
                String filename = getTempFilename();
                FileOutputStream os = null;

                try {
                        os = new FileOutputStream(filename);
                } catch (FileNotFoundException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }

                int read = 0;

                if(null != os){
                        while(isRecording){
                                read = recorder.read(data, 0, bufferSize);

                                if(AudioRecord.ERROR_INVALID_OPERATION != read){
                                        try {
                                                os.write(data);
                                        } catch (IOException e) {
                                                e.printStackTrace();
                                        }
                                }
                        }

                        try {
                                os.close();
                        } catch (IOException e) {
                                e.printStackTrace();
                        }
                }
        }

        private void stopRecording(){
                if(null != recorder){
                        isRecording = false;

                        recorder.stop();
                        recorder.release();

                        recorder = null;
                        recordingThread = null;
                }

                copyWaveFile(getTempFilename(),getFilename());
               // deleteTempFile();
        }

        private void deleteTempFile() {
                File file = new File(getTempFilename());
                file.delete();
        }

        private void copyWaveFile(String inFilename,String outFilename){
                FileInputStream in = null;
                FileOutputStream out = null;
                long totalAudioLen = 0;
                long totalDataLen = totalAudioLen + 36;
                long longSampleRate = RECORDER_SAMPLERATE;
                int channels = 2;
                long byteRate = RECORDER_BPP * RECORDER_SAMPLERATE * channels/8;

                byte[] data = new byte[bufferSize];

                try {
                        in = new FileInputStream(inFilename);
                        out = new FileOutputStream(outFilename);
                        totalAudioLen = in.getChannel().size();
                        totalDataLen = totalAudioLen + 36;

                        AppLog.logString("File size: " + totalDataLen);

                        WriteWaveFileHeader(out, totalAudioLen, totalDataLen,
                                        longSampleRate, channels, byteRate);

                        while(in.read(data) != -1){
                                out.write(data);
                        }

                        in.close();
                        out.close();
                } catch (FileNotFoundException e) {
                        e.printStackTrace();
                } catch (IOException e) {
                        e.printStackTrace();
                }
        }

        private void WriteWaveFileHeader(
                        FileOutputStream out, long totalAudioLen,
                        long totalDataLen, long longSampleRate, int channels,
                        long byteRate) throws IOException {
            //another code    

        }

        private View.OnClickListener btnClick = new View.OnClickListener() {
                public void onClick(View v) {
                     switch(v.getId()){
                              case R.id.btStart:{
                                        AppLog.logString("Start Recording");
                                        enableButtons(true);
                                        startRecording();
                                        break;
                                }
                                case R.id.btStop:{
                                    AppLog.logString("Stop Recording");
                                        enableButtons(false);
                                        stopRecording();
                                        calculate();
                                        break;

                                }
                        }
                }
        }; 
}

Ich gehe davon aus, dass das audioData-Array die unformatierten Audiodaten enthält, aber mein Code erkennt die Ausnahme und gibt "N ist keine Potenz von 2" zurück.

Stimmt etwas mit meinem Code nicht? Wie gebe ich es an die FFT.java-Klasse weiter und erhalte das fftResult?

Oder gibt es eine andere Möglichkeit, Zeitbereichsdaten einfacher in Frequenzdaten umzuwandeln?

Es ist ein paar Monate her, seit ich damit festgefahren bin ... Mein Projekt vergleicht auch 2 Audiodateien von * .wav-Dateien. Jede Hilfe wäre willkommen ... :)

Antworten auf die Frage(2)

Ihre Antwort auf die Frage