问题描述
我有一个球在屏幕上运行的应用程序.当球到达一半时,应用程序会记录一些音频、计算 FFT 并进行一些额外的分析.
I have an app that has a ball running across the screen. When the ball is halfway the application records some audio, computes the FFT and does some extra analysis.
这是由 Asynctask 处理的,但是动画仍然有短暂的卡顿.
This is handled by Asynctask, however the animation still briefly stutters.
有人对如何让它运行更顺畅有任何建议吗?
Does anyone have any suggestions on how to make it run smoother?
谢谢
代码如下:
import com.ben.applicationLayer.GameView;
import dataObjectLayer.Sprite;
import dataObjectLayer.MusicalNote;
import android.media.AudioRecord;
import android.media.MediaRecorder.AudioSource;
import android.media.AudioFormat;
import android.os.AsyncTask;
public class recorderThread extends AsyncTask<Sprite, Void, Integer> {
short[] audioData;
int bufferSize;
Sprite ballComp;
@Override
protected Integer doInBackground(Sprite... ball) {
MusicalNote note = ball[0].expectedNote;
ballComp = ball[0];
boolean recorded = false;
double frequency;
int sampleRate = 8192;
AudioRecord recorder = instatiateRecorder(sampleRate);
double[] magnitude = new double[1024];
double[] audioDataDoubles = new double[2048];
while (!recorded) { //loop until recording is running
if (recorder.getState()==android.media.AudioRecord.STATE_INITIALIZED)
// check to see if the recorder has initialized yet.
{
if (recorder.getRecordingState()==android.media.AudioRecord.RECORDSTATE_STOPPED)
recorder.startRecording();
//check to see if the Recorder has stopped or is not recording, and make it record.
else {
double max_index;
recorder.read(audioData,0,bufferSize);
//read the PCM audio data into the audioData array
computeFFT(audioDataDoubles, magnitude);
max_index = getLargestPeakIndex(magnitude);
frequency = getFrequencyFromIndex(max_index, sampleRate);
//checks if correct frequency, assigns number
int correctNo = correctNumber(frequency, note);
checkIfMultipleNotes(correctNo, max_index, frequency, sampleRate, magnitude, note);
if (audioDataIsNotEmpty())
recorded = true;
if (correctNo!=1)
return correctNo;
}
}
else
{
recorded = false;
recorder = instatiateRecorder(sampleRate);
}
}
if (recorder.getState()==android.media.AudioRecord.RECORDSTATE_RECORDING)
{
killRecorder(recorder);
}
return 1;
}
private void killRecorder(AudioRecord recorder) {
recorder.stop(); //stop the recorder before ending the thread
recorder.release(); //release the recorders resources
recorder=null; //set the recorder to be garbage collected
}
@Override
protected void onPostExecute(Integer result) {
(result == 2)
GameView.score++;
}
private AudioRecord instatiateRecorder(int sampleRate) {
bufferSize= AudioRecord.getMinBufferSize(sampleRate,AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT)*2;
//get the buffer size to use with this audio record
AudioRecord recorder = new AudioRecord (AudioSource.MIC,sampleRate, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT,bufferSize); //instantiate the AudioRecorder
audioData = new short [bufferSize]; //short array that pcm data is put into.
return recorder;
}
}
推荐答案
使用 Asynctask 符合您的要求.但是,我建议使用线程池.然后,您可以将您的动画作为一项任务,将您的录音作为一项任务,将 FFT 作为另一项任务,并将您的附加分析作为一项任务.
Using an Asynctask is along the lines of what you want to do. However, I would suggest using a thread-pool. You can then put your animation in as a task, add your audio recording as a task, the FFT as another task, and your additional analysis as a task.
短暂的卡顿很可能是动画线程中为录制分配资源的结果.使用池意味着您在创建线程来运行音频任务时不必暂停.显然,一些代码可以方便地完全理解您的问题.
The brief stutter is likely the result of allocating resources for the recording in the animation thread. Using a pool means you won't have to pause while creating the thread to run your audio tasks. Obviously, some code would be handy to fully understand your problem.
看看:
调度线程池执行器http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html
或
线程池执行器http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html
您可能想要做的一个非常简单的例子:
A very simple example of what you might want to do:
在您的活动中,您可以定义它来启动任务
In your activity you can define this to start up the tasks
ExecutorService threadPool = new ScheduledThreadPoolExecutor(2);
Recording record = new Recording();
Ball ball = new Ball(threadPool, record);
threadPool.submit(ball);
Ball.java
import java.util.concurrent.ExecutorService;
public class Ball implements Runnable {
private final Recording record;
private final ExecutorService threadPool;
private boolean condition;
private boolean active;
public Ball(ExecutorService threadPool, Recording record) {
this.record = record;
this.threadPool = threadPool;
this.active = true;
}
@Override public void run() {
while (this.active) {
moveBall();
if (isBallHalfway()) {
threadPool.submit(record);
}
}
}
private boolean isBallHalfway() {
return condition; // Condition for determining when ball is halfway
}
private void moveBall() {
// Code to move the ball
}
}
Recording.java
Recording.java
public class Recording implements Runnable {
@Override public void run() {
// Do recording tasks here
}
}
这篇关于如何让我的动画更流畅 Android的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!