0
我正在使用FFT來實時分析進入麥克風的音頻,而這隻在使用asyntask時才起作用。我還需要在後臺運行另一個線程。這兩個項目只需要運行3秒鐘。Asynctask和Handler線程在同一時間?
如果我嘗試做這兩個,ANR超時。有沒有辦法讓這些一起工作?
我不需要FFT在asynctask中,因爲我只寫入文件而不是顯示。但是,當我從asynctask中拉出FFT時,我的toTransform數組出現錯誤。
任何幫助表示讚賞。
public class SoundRecord extends Activity implements OnClickListener {
boolean started = false;
int sampleRate = 8000;
// originally from http://marblemice.blogspot.com/2010/04/generate-and-play-tone-in-android.html
// and modified by Steve Pomeroy <[email protected]>
private final int duration = 3; // seconds
private final int numSamples = duration * sampleRate;
private final double sample[] = new double[numSamples];
private final double freqOfTone = 1500; // hz
private final byte generatedSnd[] = new byte[2 * numSamples];
Handler handler = new Handler();
Timer timer = new Timer();
public int channelConfiguration = AudioFormat.CHANNEL_IN_MONO;
public int audioEncoding = AudioFormat.ENCODING_PCM_16BIT;
//FFT
private RealDoubleFFT transformer;
int blockSize = 256;
Button startStopButton;
int frequency = 8000;
double freq;
String freqValue;
int bufferSize = AudioRecord.getMinBufferSize(frequency,
channelConfiguration, audioEncoding);
AudioRecord audioRecord = new AudioRecord(
MediaRecorder.AudioSource.MIC, frequency,
channelConfiguration, audioEncoding, bufferSize);
GetFrequency recordTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_SoundRecord);
Button button = (Button) findViewById(R.id.start);
button.setOnClickListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.SoundRecord, menu);
return true;
}
@Override
public void onClick(View v) {
if (started) {
started = false;
recordTask.cancel(true);
} else {
final Thread soundout = new Thread(new Runnable() {
public void run() {
genTone();
handler.post(new Runnable() {
public void run() {
playSound();
}
});
}
});
soundout.start();
//Analyze frequency
recordTask = new GetFrequency();
try {
recordTask.get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
void genTone(){
// fill out the array
for (int i = 0; i < numSamples; ++i) {
sample[i] = Math.sin(2 * Math.PI * i/(sampleRate/freqOfTone));
}
// convert to 16 bit pcm sound array
// assumes the sample buffer is normalised.
int idx = 0;
for (final double dVal : sample) {
// scale to maximum amplitude
final short val = (short) ((dVal * 32767));
// in 16 bit wav PCM, first byte is the low order byte
generatedSnd[idx++] = (byte) (val & 0x00ff);
generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);
}
}
void playSound(){
final AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
sampleRate, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, numSamples,
AudioTrack.MODE_STATIC);
audioTrack.write(generatedSnd, 0, generatedSnd.length);
audioTrack.play();
}
private class GetFrequency extends AsyncTask<Void, double[], Void> {
@Override
protected Void doInBackground(Void... params) {
try {
short[] buffer = new short[blockSize];
double[] toTransform = new double[blockSize];
audioRecord.startRecording();
while (started) {
int bufferReadResult = audioRecord.read(buffer, 0, blockSize);
for (int i = 0; i < blockSize && i < bufferReadResult; i++) {
toTransform[i] = (double) buffer[i]/32768.0; // signed // 16 // bit
}
transformer.ft(toTransform);
publishProgress(toTransform);
timer.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
audioRecord.stop();
}
});
}
}, 3000); //Stop after 3 seconds
}
} catch (Throwable t) {
Log.e("AudioRecord", "Recording Failed");
}
return null;
}
protected void onProgressUpdate(double[]... toTransform) {
File freqFile = new File("/mnt/sdcard/Test APKs/frequency.file");
File magFile = new File("/mnt/sdcard/Test APKs/magnitude.file");
int blockSize = 256;
double[] audioDataDoubles = new double[(blockSize*2)];
String mydate = java.text.DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());
if (!freqFile.exists())
{
try {
freqFile.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (!magFile.exists())
{
try {
magFile.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for (int x = 0; x < toTransform[0].length; x++) {
audioDataDoubles[2*x] = toTransform[0][x];
audioDataDoubles[(2*x)+1] = 0.0;
}
double[] re = new double[blockSize];
double[] im = new double[blockSize];
double[] magnitude = new double[blockSize];
// Calculate the Real and imaginary and Magnitude.
for(int i = 0; i < blockSize; i++){
// real is stored in first part of array
re[i] = audioDataDoubles[i*2];
// imaginary is stored in the sequential part
im[i] = audioDataDoubles[(2*i)+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];
String magValue = String.valueOf(peak);
try {
BufferedWriter buf = new BufferedWriter(new FileWriter(magFile, true));
buf.append(mydate + " - " + magValue);
buf.newLine();
buf.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// calculated the frequency
freq = (frequency * peak)/blockSize;
freqValue = String.valueOf(freq);
//Toast.makeText(Main.this, freqValue, Toast.LENGTH_SHORT).show();
try {
BufferedWriter buf = new BufferedWriter(new FileWriter(freqFile, true));
buf.append(mydate + " - " + freqValue);
buf.newLine();
buf.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
您在'onProgressUpdate'上做了太多工作 – Eugene
>我不需要FFT來處理asyncTask,因爲我只寫入文件而不是顯示器 'AsyncTask'是從UI線程中卸載任務的幾種方法之一。寫入文件也可能很長。 – Eugene
看起來像是在上一次寫入操作未結束時,您試圖在文件中寫入文件。我建議你把你的邏輯分成'一個文件=一個線程'。另外我建議把這個動作組織到'Queue'或'ExecutorService'中 – 2013-10-31 14:30:03