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

Posted

技术标签:

【中文标题】AudioTrack:在未初始化的 AudioTrack 上调用 play()【英文标题】:AudioTrack: play() called on uninitialized AudioTrack 【发布时间】:2012-07-02 18:13:11 【问题描述】:

我正在尝试使用 AudioTrack 类。基本上,当用户触摸屏幕上的特定对象时,我的应用程序必须产生声音。我使用this example 作为指导。 我的应用程序似乎可以正常工作,但通常在触摸屏幕大约一分钟后它会崩溃:

07-02 20:40:53.459: E/androidRuntime(11973): FATAL EXCEPTION: Thread-10
07-02 20:40:53.459: E/AndroidRuntime(11973): java.lang.IllegalStateException: play() called on uninitialized AudioTrack.
07-02 20:40:53.459: E/AndroidRuntime(11973):    at android.media.AudioTrack.play(AudioTrack.java:824)
07-02 20:40:53.459: E/AndroidRuntime(11973):    at com.mysounds_experimental.SoundThread.playSound(SoundThread.java:108)
07-02 20:40:53.459: E/AndroidRuntime(11973):    at com.mysounds_experimental.SoundThread.run(SoundThread.java:69)

类中产生声音的方法

public void initAudioTrack() 
        int bufferSize = AudioTrack.getMinBufferSize(sampleRate
                , AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);

        audioTrack = new AudioTrack(
                AudioManager.STREAM_MUSIC
                , sampleRate
                , AudioFormat.CHANNEL_CONFIGURATION_MONO
                , AudioFormat.ENCODING_PCM_16BIT
                , bufferSize
                , AudioTrack.MODE_STREAM);
    

   private void playSound()
            audioTrack.write(generatedSnd, 0, numSamples);
            audioTrack.play();
        

public void stopPlaying() 
    audioTrack.flush();
    audioTrack.stop(); 
    audioTrack.release();


@Override
    public void run() 
        while (mRun) 
            try
                Thread.sleep(200);
                while(soundCycle)
                    if(freqOfTone != -1f) 
                        generateTone();
                        playSound();
                        Thread.sleep(200);
                    
                
             catch(InterruptedException e)
                //              soundCycle = false;
                //              soundPool.stop(BEEP);
            
        
    

这是我的线程使用的自定义视图中的一种方法

@Override
    public boolean onTouchEvent(final MotionEvent ev) 
        int currentXPosition = (int) ev.getX();
        int currentYPosition = (int) ev.getY();

        if(ev.getX() < smBitmap.getWidth())
            if(ev.getY() < smBitmap.getHeight())
                tempCol = smBitmap.getPixel(currentXPosition, currentYPosition);
            

        final int action = ev.getAction();

        switch (action & MotionEvent.ACTION_MASK) 

        case MotionEvent.ACTION_DOWN: 

            sThread.freqOfTone = getFreqPreset(tempCol);
            if(col != tempCol)
//              sThread.initAudioTrack();
                sThread.interrupt();
                if(shouldInit) 
                   shouldInit = false;
                   sThread.initAudioTrack();
                
                sThread.soundCycle = true;
                col = tempCol; 
                invalidate();
            
            break;
        

        case MotionEvent.ACTION_MOVE: 
            sThread.freqOfTone = getFreqPreset(tempCol);

            if (tempCol == -1 || tempCol == 0) 
                sThread.soundCycle = false;
                shouldInit = true;
//              sThread.stopPlaying();
                sThread.interrupt();
                invalidate();
             else 
                if(col != tempCol)
                    sThread.interrupt();
                    col = tempCol;
                    invalidate();
                else 
                    sThread.soundCycle = true;
                    col = tempCol;
                    invalidate();
                
            
            break;
        // case ACTION_MOVE

        case MotionEvent.ACTION_UP: 
            sThread.soundCycle = false;
            shouldInit = true;
//          sThread.stopPlaying();
            sThread.interrupt();
            col = -1;
            mActivePointerId = INVALID_POINTER_ID;
            break;
        // case ACTION_UP

           

        return true;
    

任何想法为什么会发生这种情况?

【问题讨论】:

// sThread.initAudioTrack(); 取消注释 对不起,我的意思是取消注释。 你成功移除这个异常了吗??你是怎么做到的。我遇到了同样的错误。 【参考方案1】:

为什么你注释掉了你的 stopPlaying() 方法?

您只能创建 32 个音轨。如果你想要更多,你应该调用 release() 方法。

【讨论】:

【参考方案2】:

我认为您需要先致电play(),然后再致电write()

但我也注意到,当您创建大量 AudioTrack 实例时,即使您认为自己正在清理所有内容,有时 play() 也无法工作,并且轨道未初始化。

您会想尝试...捕获这个IllegalStateException,并避免调用write(),直到play() 正常工作而不会引发异常。

【讨论】:

以上是关于AudioTrack:在未初始化的 AudioTrack 上调用 play()的主要内容,如果未能解决你的问题,请参考以下文章

节拍器android应用AudioTrack releaseBuffer()错误

在未初始化的对象(空指针)上调用方法

在未正确分配函数中初始化的链表结构

AudioTrack 采样率不一致

AudioTrack:播放通过 WiFi 传入的声音

音视频 — AudioRecorder 和 AudioTrack