2014-01-02 4 views
1

Я хочу воспроизвести тональный импульс, повторяемый с определенной скоростью, например. 3 раза в секунду. Он работает примерно 20 раз, а затем падает, как показано ниже.Воспроизведение повторяющегося AudioTrack в активности Android

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

В asynctask Я запускаю непрерывный цикл, который проверяет время и вызывает playSound при необходимости. Он работает в течение нескольких секунд, а затем получает эту ошибку,

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

, хотя дорожка инициализируется каждый раз.

Любое указание на то, что я делаю неправильно? Или может быть лучше?

Вот код:

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

А вот полная ошибка:

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 
+0

возможно дубликат [неинициализированного исключением AudioTrack, когда я пытаюсь генерировать сигнал на 22-й раз] (http://stackoverflow.com/questions/7497598/uninitialized-audiotrack -exception-when-i-try-to-generate-tone-on-22nd-time) – KickAss

ответ

1

Вы бежите из аудиотреков, 20 в вашем случае, 30 на моем Nexus4, что дает мне:

175-5975/? E/AudioFlinger﹕ no more track names available 

решение - использовать глобальный объект аудиодорожки, что у вас уже есть, и обнулить его и создать в каждой игре:

void playSound() { 
    System.out.println("+++ PLAY "); 

    //if audioTrack has been initialised, first, release any resources 
    //then null it 
    if (audioTrack != null) { 
     audioTrack.release(); 
     audioTrack = null; 
    } 

    //now create it again, note: use global audioTrack, 
    //that means remove "final AudioTrack" here 
    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(); 
} 
+1

Спасибо, это сработало. Хотя на самом деле я хотел повторить один и тот же трек. Я попытался создать только один раз, но потом он играл только один раз. Мне не хватало stop() и reloadStaticData(), поэтому теперь я создаю один раз, и он воспроизводит один и тот же трек. – PerceptualRobotics

+0

Добро пожаловать. Рад, что он работает на вас. – Melquiades

0

Ваш AudioTrack создается более 20 раз. Каждое устройство имеет максимальное количество разрешенных аудиодорожек. Так просто использовать один и initiliaze его globaly так:

final AudioTrack audioTrack = null; 
void playSound() { 
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(); 
} 
+2

Вы не можете изменить окончательную переменную, я полагаю. – PerceptualRobotics