android Ton-Frequenzen in Echtzeit?
Habe ich mich bemüht, um die sound-Frequenz(Anzahl) in Echtzeit unter Verwendung von fft-und ich bin mit Laufzeit-Fehler. kann einer helfen?
package com.example.recordsound;
import edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D;
import ca.uol.aig.fftpack.RealDoubleFFT;
public class MainActivity extends Activity implements OnClickListener{
int audioSource = MediaRecorder.AudioSource.MIC; //Audio source is the device MIC
int channelConfig = AudioFormat.CHANNEL_IN_MONO; //Recording in mono
int audioEncoding = AudioFormat.ENCODING_PCM_16BIT; //Records in 16bit
private DoubleFFT_1D fft; //The fft double array
private RealDoubleFFT transformer;
int blockSize = 256; //deal with this many samples at a time
int sampleRate = 8000; //Sample rate in Hz
public double frequency = 0.0; //the frequency given
RecordAudio recordTask; //Creates a Record Audio command
TextView tv; //Creates a text view for the frequency
boolean started = false;
Button startStopButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView)findViewById(R.id.textView1);
startStopButton= (Button)findViewById(R.id.button1);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
private class RecordAudio extends AsyncTask<Void, Double, Void>{
@Override
protected Void doInBackground(Void... params){
/*Calculates the fft and frequency of the input*/
//try{
int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioEncoding); //Gets the minimum buffer needed
AudioRecord audioRecord = new AudioRecord(audioSource, sampleRate, channelConfig, audioEncoding, bufferSize); //The RAW PCM sample recording
short[] buffer = new short[blockSize]; //Save the raw PCM samples as short bytes
// double[] audioDataDoubles = new double[(blockSize*2)]; //Same values as above, as doubles
// -----------------------------------------------
double[] re = new double[blockSize];
double[] im = new double[blockSize];
double[] magnitude = new double[blockSize];
// ----------------------------------------------------
double[] toTransform = new double[blockSize];
tv.setText("Hello");
//fft = new DoubleFFT_1D(blockSize);
try{
audioRecord.startRecording(); //Start
}catch(Throwable t){
Log.e("AudioRecord", "Recording Failed");
}
while(started){
/* Reads the data from the microphone. it takes in data
* to the size of the window "blockSize". The data is then
* given in to audioRecord. The int returned is the number
* of bytes that were read*/
int bufferReadResult = audioRecord.read(buffer, 0, blockSize);
//Read in the data from the mic to the array
for(int i = 0; i < blockSize && i < bufferReadResult; i++) {
/* dividing the short by 32768.0 gives us the
* result in a range -1.0 to 1.0.
* Data for the compextForward is given back
* as two numbers in sequence. Therefore audioDataDoubles
* needs to be twice as large*/
//audioDataDoubles[2*i] = (double) buffer[i]/32768.0; //signed 16 bit
//audioDataDoubles[(2*i)+1] = 0.0;
toTransform[i] = (double) buffer[i] / 32768.0; //signed 16 bit
}
//audiodataDoubles now holds data to work with
//fft.complexForward(audioDataDoubles);
transformer.ft(toTransform);
//------------------------------------------------------------------------------------------
//Calculate the Real and imaginary and Magnitude.
for(int i = 0; i < blockSize; i++){
//real is stored in first part of array
re[i] = toTransform[i*2];
//imaginary is stored in the sequential part
im[i] = toTransform[(i*2)+1];
//magnitude is calculated by the square root of (imaginary^2 + real^2)
magnitude[i] = Math.sqrt((re[i] * re[i]) + (im[i]*im[i]));
}
double peak = -1.0;
//Get the largest magnitude peak
for(int i = 0; i < blockSize; i++){
if(peak < magnitude[i])
peak = magnitude[i];
}
//calculated the frequency
frequency = (sampleRate * peak)/blockSize;
//----------------------------------------------------------------------------------------------
/* calls onProgressUpdate
* publishes the frequency
*/
publishProgress(frequency);
try{
audioRecord.stop();
}
catch(IllegalStateException e){
Log.e("Stop failed", e.toString());
}
}
// }
return null;
}
protected void onProgressUpdate(Double... frequencies){
//print the frequency
String info = Double.toString(frequencies[0]);
tv.setText(info);
}
}
@Override
public void onClick(View v) {
//TODO Auto-generated method stub
if(started){
started = false;
startStopButton.setText("Start");
recordTask.cancel(true);
} else {
started = true;
startStopButton.setText("Stop");
recordTask = new RecordAudio();
recordTask.execute();
}
}
}
Sobald ich das Programm mit dem OnClick-es stürzt ab
Ich habe versucht, zwei Bibliotheken für die fft aber lief zu einem Zeitpunkt zu sehen, ob die Bibliothek funktioniert oder nicht
Sobald es erreicht die Zeile, wo ich weisen Sie die Blockgröße der FFT-Objekt stürzt es ab
kann einer helfen
- Ich werde versuchen, die Frequenz-Werte und nicht die Grafik
- Können Sie eine logcat Erfassung der Absturz? Ein stack-trace wäre hilfreich. In dieser form sehe ich einen möglichen Absturz, weil
transformer
wird nie initialisiert, so dass, sobald Sie an die Linietransformer.ft(toTransform)
Absturz wird einNullPointerException
.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Versuchen, diese FFT:
Es ansprechen sollte, was Sie im Sinn haben. Wenn Sie sich entschieden, wieder zu verwenden, geben Sie den richtigen Kredit zu the Autor.
Quelle/Autor: EricLarch
Wenn Sie wirklich wollen, führen Sie eine real-time audio-Analyse, eine auf Java basierende Ansatz nicht aus. Ich hatte eine ähnliche Aufgabe in Q4 2013 für meine Firma, und wir beschlossen, Kiss FFT (vielleicht die einfache FFT-Bibliothek mit einer BSD-Lizenz), zusammengestellt für Android mit dem NDK.
Einer nativen C/C++ - Ansatz ist Tonnen mal schneller als Ihre Java-Pendants. Mit dem ehemaligen konnten wir durchführen Echtzeit-audio-Dekodierung und audio-Funktionen Analyse auf fast jedem mid-und high-end-Gerät, etwas, das war offensichtlich unmöglich, mit der letzteren.
Ich stark schlage vor, Sie zu prüfen, den einheitlichen Ansatz, um die beste option, um diese Aufgabe zu erfüllen. Kiss FFT ist eine wirklich einfache Bibliothek (wörtlich steht für
Keep It Simple FFT
), und Sie finden nicht viel Probleme bei der Erstellung und Nutzung auf Android. Sie werden nicht enttäuscht sein von der performance-Ergebnisse.Hast du das problem gelöst? Der Andrang ist aufgetreten, weil der ArrayIndexOutOfBoundsException.
So, den code so ändern :