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

10
我正在尝试使用AudioTrack类。基本上,我的应用程序必须在用户触摸屏幕上的特定对象时生成声音。我已经使用这个示例作为指南。
我的应用程序似乎按照预期工作,但通常在触摸屏幕约一分钟后它会崩溃:
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(); 取消注释 - Jack Satriano
抱歉,我是说取消注释。 - droid8421
你成功地解决了这个异常吗?你是怎么做到的?我还是遇到了同样的错误。 - Rahul Baradia
3个回答

4

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

你只能创建32个AudioTrack。如果你需要更多,应该调用release()方法。


1

我认为你需要在调用write()之前先调用play()

但是,我也注意到,当您创建大量的AudioTrack实例时,即使您认为已经清除了所有内容,有时play()失败无法工作,而该轨道未初始化。

您需要尝试...捕获此IllegalStateException,并避免在play()可以正常工作而不抛出异常之前调用write()


0

对于我的情况,不知何故我调用了 -

audioTrack.release(); 

在调用.play()之前,我将其删除后,它按预期工作了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接