AudioTrack.play()中的IllegalStateException

时间:2013-12-28 10:40:42

标签: android illegalstateexception audiotrack

我正在使用一个应用程序,用户可以触摸屏幕并根据他/她接触某个音调的位置进行播放。为此,我有以下代码:

@Override
public boolean onTouchEvent(MotionEvent event) {

    // Calculate the frequency that should be played
    final double frequency = (event.getX()/mScreenWidth)*450 + 450;

    // Use a new tread as this can take a while
    mThread = new Thread(new Runnable() {
        public void run() {
            generateTone(frequency);
            mHandler.post(new Runnable() {
                public void run() {
                    playSound();
                }
            });
        }
    });
    mThread.start();

    return true;
}

void generateTone(double frequency) {
    // Fill out the array
    for (int i = 0; i < NUM_SAMPLES; ++i) SAMPLE_ARRAY[i] = Math.sin(2 * Math.PI * i / (SAMPLE_RATE/frequency));

    // Convert to 16 bit PCM sound array
    // Assumes the sample buffer is normalized.
    int idx = 0;
    for (final double dVal : SAMPLE_ARRAY) {
        // Scale to maximum amplitude
        final short val = (short) ((dVal * 32767));
        // In 16 bit WAV PCM, first byte is the low order byte
        GENERATE_SND[idx++] = (byte) (val & 0x00ff);
        GENERATE_SND[idx++] = (byte) ((val & 0xff00) >>> 8);

    }
}

void playSound(){
    final AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, GENERATE_SND.length, AudioTrack.MODE_STATIC);
    audioTrack.write(GENERATE_SND, 0, GENERATE_SND.length);
    try {
        audioTrack.play();
    } catch(IllegalStateException exception) {
        Log.d("My App", "Tried to play sound, but audio track is not ready yet");
    }
}

这种方法很有效,但当用户将手指移到屏幕上时,我得到以下错误:

12-28 11:19:14.928: E/AndroidRuntime(10433): FATAL EXCEPTION: main
12-28 11:19:14.928: E/AndroidRuntime(10433): java.lang.IllegalStateException: play() called on uninitialized AudioTrack.
12-28 11:19:14.928: E/AndroidRuntime(10433):    at android.media.AudioTrack.play(AudioTrack.java:899)
12-28 11:19:14.928: E/AndroidRuntime(10433):    at com.mynamespace.projectone.Main.playSound(Main.java:77)
12-28 11:19:14.928: E/AndroidRuntime(10433):    at com.mynamespace.projectone.Main$1$1.run(Main.java:47)
12-28 11:19:14.928: E/AndroidRuntime(10433):    at android.os.Handler.handleCallback(Handler.java:615)
12-28 11:19:14.928: E/AndroidRuntime(10433):    at android.os.Handler.dispatchMessage(Handler.java:92)
12-28 11:19:14.928: E/AndroidRuntime(10433):    at android.os.Looper.loop(Looper.java:137)
12-28 11:19:14.928: E/AndroidRuntime(10433):    at android.app.ActivityThread.main(ActivityThread.java:4931)
12-28 11:19:14.928: E/AndroidRuntime(10433):    at java.lang.reflect.Method.invokeNative(Native Method)
12-28 11:19:14.928: E/AndroidRuntime(10433):    at java.lang.reflect.Method.invoke(Method.java:511)
12-28 11:19:14.928: E/AndroidRuntime(10433):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
12-28 11:19:14.928: E/AndroidRuntime(10433):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:558)
12-28 11:19:14.928: E/AndroidRuntime(10433):    at dalvik.system.NativeStart.main(Native Method)

目前我在audioTrack.play()周围使用try / catch构造捕获此错误,因此应用程序不会崩溃。这不是解决方案,因为声音仍然停止播放并且不会重新开始。有任何想法如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

如果模式是静态的,那么你需要在调用play()之前调用write()。

如果模式是流媒体,那么它并不重要。您可以选择在调用write()之前使用play()来填充数据,或者可以写()然后play()。无论哪种方式,它都是合法的。