Reproduzindo AudioTrack repetido na atividade do Android

Quero tocar um pulso de tom repetido a uma taxa especificada, por exemplo 3 vezes por segundo. Funciona cerca de 20 vezes e depois falha como abaixo.

void playSound() {
    final AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length, AudioTrack.MODE_STATIC);
    audioTrack.write(generatedSnd, 0, generatedSnd.length);
    audioTrack.play();
}

Em uma assíncrona, eu corro um loop contínuo que verifica o tempo e chama playSound quando necessário. Funciona por alguns segundos e, em seguida, obtém este erro,

01-02 18:24:45.035: E/AndroidRuntime(6599): Caused by: java.lang.IllegalStateException: play() called on uninitialized AudioTrack.

mesmo que a faixa seja inicializada toda vez.

Alguma indicação do que estou fazendo de errado? Ou poderia fazer melhor?

Aqui está o código:

<, pré>public class DisplayBowieActivity extends Activity { private final int duration = 200; // seconds private final int sampleRate = 8000; private final int numSamples = duration * sampleRate / 1000; private double sample[];// =new double[numSamples]; private final double freqOfTone = 1440; // hz private int pulseLength; private byte generatedSnd[];// = new byte[2 * numSamples]; private int period = 4; // hz private AudioTrack audioTrack; Handler handler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_display_bowie); Intent intent = getIntent(); String smessage = intent.getStringExtra(MainActivity.SOUND_MESSAGE); period = Integer.parseInt(smessage); pulseLength = duration * sampleRate / 1000; System.out.print("+++ Period " + period); System.out.print("+++ Pulse " + pulseLength); genTone(); View view = this.getWindow().getDecorView(); view.setBackgroundColor(Color.parseColor("#8E8E38")); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.display_bowie, menu); return true; } @Override protected void onResume() { super.onResume(); new SoundGen().execute(period); } private class SoundGen extends AsyncTask<Integer, Void, Void> { @Override protected Void doInBackground(Integer... hz) { long mils = (int) (1000.0 / hz[0]); long start = System.currentTimeMillis(); long next = start + mils; while (true) { long now = System.currentTimeMillis(); if (now > next) { next = now + mils; playSound(); } } } } void genTone() { sample = new double[numSamples]; generatedSnd = new byte[2 * numSamples]; int rate = numSamples / period; for (int i = 0; i < numSamples; ++i) { if (i % rate == 0) { System.out.println("+++ Create tone " + i); int j = 0; for (j = 0; j < pulseLength; j++) { sample[i + j] = Math.sin(2 * Math.PI * (i + j) / (sampleRate / freqOfTone)); System.out.println("+++ SAMPLE " + (i + j) + " " + sample[i + j]); } i = i + j; } } // 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() { System.out.println("+++ PLAY " ); //audioTrack.stop(); //audioTrack.setPlaybackHeadPosition(0); final AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length, AudioTrack.MODE_STATIC); audioTrack.write(generatedSnd, 0, generatedSnd.length); audioTrack.play(); }

E aqui está o erro completo:

01-02 18:24:45.035: E/AndroidRuntime(6599): FATAL EXCEPTION: AsyncTask #1
01-02 18:24:45.035: E/AndroidRuntime(6599): java.lang.RuntimeException: An error occured while executing doInBackground()
01-02 18:24:45.035: E/AndroidRuntime(6599):     at android.os.AsyncTask$3.done(AsyncTask.java:200)
01-02 18:24:45.035: E/AndroidRuntime(6599):     at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
01-02 18:24:45.035: E/AndroidRuntime(6599):     at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
01-02 18:24:45.035: E/AndroidRuntime(6599):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
01-02 18:24:45.035: E/AndroidRuntime(6599):     at java.util.concurrent.FutureTask.run(FutureTask.java:138)
01-02 18:24:45.035: E/AndroidRuntime(6599):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
01-02 18:24:45.035: E/AndroidRuntime(6599):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
01-02 18:24:45.035: E/AndroidRuntime(6599):     at java.lang.Thread.run(Thread.java:1019)
01-02 18:24:45.035: E/AndroidRuntime(6599): Caused by: java.lang.IllegalStateException: play() called on uninitialized AudioTrack.
01-02 18:24:45.035: E/AndroidRuntime(6599):     at android.media.AudioTrack.play(AudioTrack.java:824)
01-02 18:24:45.035: E/AndroidRuntime(6599):     at uk.co.moonsit.signals.DisplayBowieActivity.playSound(DisplayBowieActivity.java:164)
01-02 18:24:45.035: E/AndroidRuntime(6599):     at uk.co.moonsit.signals.DisplayBowieActivity$SoundGen.doInBackground(DisplayBowieActivity.java:90)
01-02 18:24:45.035: E/AndroidRuntime(6599):     at uk.co.moonsit.signals.DisplayBowieActivity$SoundGen.doInBackground(DisplayBowieActivity.java:1)
01-02 18:24:45.035: E/AndroidRuntime(6599):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
01-02 18:24:45.035: E/AndroidRuntime(6599):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
01-02 18:24:45.035: E/AndroidRuntime(6599):     ... 4 more

questionAnswers(2)

yourAnswerToTheQuestion