AudioTrack-IllegalStateException:在未初始化的AudioTrack上调用play()

时间:2019-04-15 15:10:33

标签: java android multithreading audiotrack

我有一个带有AudioTrack的线程,我想在按钮DOWN上调用,在按钮UP上我想停止音频。到目前为止,一切都很好。我的应用程序具有活动A和活动B。活动A是我从中启动活动B的某个菜单,活动B是我称为AudioTrack的主要活动,依此类推。问题是,一切正常,直到我第三次参加活动B,然后这才发生。

E/AudioTrack: AudioFlinger could not create track, status: -12
E/AudioTrack-JNI: Error -12 initializing AudioTrack
E/android.media.AudioTrack: Error code -20 when initializing AudioTrack.
java.lang.IllegalStateException: play() called on uninitialized AudioTrack.

对于第1次和第2次,我什至不必调用播放,只需输入活动B,但是当我想第3次调用播放时,就会发生此错误。为什么?

活动B看起来像这样

Activity B playTune(){
    if(tuneThread == null){
        tuneThread = new startSI();
        //    tuneThread.setTuneFreq(tuneFreq);
        tuneThread.start();
    }
    return this;
}

void setTuneFreq(double tuneFreq) {
    this.tuneFreq = tuneFreq;
    if(tuneThread != null){
        tuneThread.setTuneFreq(tuneFreq);
    }
}

void stopTune(){
    if(tuneThread != null){
        tuneThread.stopTune();
        tuneThread = null;
    }
}

protected void onPause() {
    stopTune();
    super.onPause();
}

protected void onStop() {
    stopTune();
    super.onStop();

这就是我调用和/或停止线程的方式

setTuneFreq(double);

我之所以调用OnSenzorChanged(事件监听器),是因为我需要基于陀螺仪数据的频率。

playTune();

在按下按钮之后,在ACTION_DOWN之后我在OnTouchListener中调用,并且只要按下它,AudioTrack就会生成信号(直到ACTION_UP),然后我调用

stopTune();

AudioTrack线程看起来像这样

public class startSI extends Thread {

    private boolean isRunning;
    private double tuneFreqSI;


    private int sr = 44100;
    private int sibuffsize = AudioTrack.getMinBufferSize(sr,
            AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
    private AudioTrack siaudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
            sr, AudioFormat.CHANNEL_OUT_MONO,
            AudioFormat.ENCODING_PCM_16BIT, sibuffsize,
            AudioTrack.MODE_STREAM);


    @Override
    public void run() {

        super.run();
        isRunning = true;


        short samples[] = new short[sibuffsize];
        int amp = 32767;
        double twopi = 8. * Math.atan(1.);
        double ph = 0.0;

        try {

        siaudioTrack.play();

        } catch(IllegalStateException e) {
            System.out.println("error play "+e);   
        }

        while (isRunning) {

            double fr = tuneFreqSI;
            double fLFO = frLFO;
            for (int i = 0; i < sibuffsize; i++) {
                samples[i] = (short) (amp * Math.sin(ph));
                ph += twopi * fr / sr;               
            }
            siaudioTrack.write(samples, 0, sibuffsize);       

        }
        try {
        siaudioTrack.stop();
        siaudioTrack.release();

        }catch(IllegalStateException e) {
            System.out.println("error stop "+e);
        }

    }

    public void setTuneFreq(double tuneFreq, double frLFO, double ampLFO) {

        this.tuneFreqSI = tuneFreq;
        this.frLFO = frLFO;
        this.ampLFO = ampLFO;
    }


    public void stopTune() {
        isRunning = false;

        try {
            this.join();
            this.interrupt();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

即使我第三次打开活动B,也需要启动此线程。

我在做什么错了?

1 个答案:

答案 0 :(得分:-1)

我认为,您的音频轨道同时已被垃圾收集器破坏。因此,我建议您使用此行在run()方法开始时重新初始化siaudioTrack。

this.siaudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sr, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, sibuffsize, AudioTrack.MODE_STREAM);