AudioTrack: play() вызывается на неинициализированный 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;
    }

Любые идеи, почему это происходит?

2 8

2 ответа:

Я бы подумал, что вам нужно позвонить play(), прежде чем звонить write().

Но я также заметил, что когда вы создаете много экземпляров AudioTrack, даже если вы думаете, что вы все убираете, иногда play() не работает, и трек неинициализирован.

Вы захотите попробовать...поймайте этот IllegalStateException и избегайте вызова write(), пока play() не сработает без создания исключения.

Почему вы прокомментировали свой метод stopPlaying ()?

Можно создать только 32 аудиотрека. Если вы хотите больше, вы должны вызвать метод release ().