2012-01-23 14 views
3

私は画面上にボールが走っているアプリを持っています。ボールが途中であるときに、アプリケーションは何らかのオーディオを記録し、FFTを計算し、いくつかの余分な分析を行います。アニメーションをスムーズにするにはどうすればいいですか?

これはAsynctaskによって処理されますが、アニメーションはまだまだ短くなります。

誰もそれをよりスムーズにする方法について提案はありますか?以下

おかげ

コード:

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; 
} 

} 
+0

ここに問題がないため、このAsyncTaskを呼び出すコードを示してください。 AsyncTaskは別のスレッドでそのジョブを実行するので、アニメーションに影響を与えてはいけません(概念的にはこれが極端であるかもしれませんが)。とにかく、私たちにアニメーションコードと、このAsyncTaskと呼ぶ場所を教えてください –

答えて

0

コードなしには最適化することができますと推測するのは難しいだろうが、私はロードに100万人以上の操作で何をしたかを教えてくれます。.. •パフォーマンスに問題がある場合は、以下を試してみてください。 変数のデータ型を1回チェックし、変数がより多くのバイトを必要としない場合、つまりintの代わりに短いサイズの変数を低く設定します。

コードを2回チェックして、次回の起動時にすべての結果を保存して、それらを再度計算する代わりに次回に呼び出すことができます。

•しかし、アニメーションが遅く、メモリに問題がない場合は、アニメーションの期間を短縮したり、ムーブメントの単位を増やしたりしてみてください。

どうやってアニメーションを実装しますか?フレームごとのアニメーション、またはレイアウトアニメーション、またはアニメーションを表示できますか?

+1

速度を最適化するなら、#1は実際には悪い考えです! JVMは、算術演算を実行する前に、バイト、short、charsをintに変換します。 shortsは最高で同じで、intを使うよりも最悪です。 – vaughandroid

+0

あなたは正しいですし、私も...私はストレージの効率性について言及していましたが、あなたはランタイムパフォーマンスについて話しています。だから私たちの仲間Ben Taliadorosの場合のように、私はあなたに同意するだろう:-)あなたの下位データ型に大きな問題はない...あなたのコメントにBaquetaとthnx –

+0

ありがとう面白い。私はあなたの質問に答えるために、モハメッドをフレームごとに表示するために、私のコードをここに含めました。何か案は? –

3

Asynctaskを使用することは、あなたがしたい行に沿っています。しかし、私はスレッドプールを使用することをお勧めします。その後、アニメーションをタスクとして配置し、オーディオレコーディングをタスクとして追加し、FFTを別のタスクとして追加し、追加の分析をタスクとして追加することができます。

アニメーションスレッドで録画用のリソースを割り当てた結果、簡単な突然の結果が得られる可能性があります。プールを使用すると、オーディオタスクを実行するためにスレッドを作成中に一時停止する必要がなくなります。明らかに、いくつかのコードは、あなたの問題を完全に理解するのに便利です。あなたに

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ThreadPoolExecutor.html

ThreadPoolExecutor

のScheduledThreadPoolExecutor http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html

または

あなたがしたいかもしれないものの非常に簡単な例を:

は見てみましょうあなたができることができる活動このタスクを起動する

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

public class Recording implements Runnable { 
    @Override public void run() { 
     // Do recording tasks here 
    } 
} 
+0

私はあなたの応答のために、コードを含めました。コードを見れば、どのような種類のスレッディングが一番良いと思いますか? –

+0

遅れて申し訳ありませんが、ThreadPoolを使用して問題にアプローチする方法を示すコードをいくつか追加しました。これはあなたにアイデアを与えるはずです、あなたがそれをさらに説明する必要がある場合は、さらに質問をしてください。 :) – Jyro117

1

モハメッドが言うように、それは問題は見ないかもしれないものを推測するのは難しいですコード。それを念頭に置いて...

AsyncTaskは他のスレッドの実行をブロックしている可能性があります。 Thread.sleep()への呼び出しがあることを確認して、スケジューラーがUIスレッドに切り替える機会を与えるようにしてください(Thread.yield()もオプションですが、利回りのある問題があることに注意してください)。

+0

私は今どこに睡眠方法を含めると、コードが含まれていますか?私は収穫を気にする必要がありますか? –

+0

あなたが何をしているのかわからない場合は、 'yield'を避けるのが最善です。これらのメソッド呼び出しがどれぐらいかかるかわからなければ、私は推測する必要がありますが、 'sleep 'への呼び出しを行う場所の良い候補はwhileループの終わりにあると言います。 'computeFFT()'関数が遅い場合( '高速'かもしれませんが、FFTにはまだまだ多くの作業が含まれています)、その中に 'sleep()'を呼び出すこともできます。 – vaughandroid

関連する問題