javaandroidontouchlistenersoundpool

Why is my soundpool behaving differently in these 2 situations? (The value soundpool.play assigned to stream is never used)


I want to play a sound when the user touch the button and have the sound stop when the finger is lifted. This is my trial code which works as I wanted:

            public boolean onTouch(View view, MotionEvent motionEvent) {
                    switch (motionEvent.getAction()){
                        case MotionEvent.ACTION_DOWN:
                            // -1 so it keeps looping
                            fStream = soundPool.play(F4, 1, 1,0,-1,1);
                            return true;
                        case MotionEvent.ACTION_UP:
                            soundPool.stop(fStream);
                    }
                return false;
            }

This is the code I want to put in my app after I apply some conditions:

    int A4, A5, aStream; //global variable in MainActivity
            public boolean onTouch(View view, MotionEvent event) {
                switch (event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        if(up){
                            horizontal_method(A5, A5_sharp, aStream);
                        } else if(down){
                            horizontal_method(A4, A4_sharp, aStream);
                        }
                        return true;
                    case MotionEvent.ACTION_UP:
                        stop_audio_method(aStream);
                        //soundPool.stop(aStream);
                }
                return false;
            }
    public void horizontal_method(int note, int sharp, int stream){
        if(horizontal){ //if phone is moving
            loop_num = -1;
        } else { //if phone is not moving
            loop_num = 0;
        }
        rotate_method(note, sharp, stream, loop_num);
    }

    public void rotate_method(int note, int sharp, int stream, int loop_num){
        if(rotate){ //if it's sharp
            stream = soundPool.play(sharp, 1, 1,0,loop_num,1);
        } else { // if it's normal note
            stream = soundPool.play(note, 1, 1,0,loop_num,1);
        }
    }

    public void stop_audio_method(int stream){
        soundPool.stop(stream);
    }

The problem:

In the trial code, when I press and hold the button, the sound loops. When I lift my finger, it stops. But in my app, when I lift my finger, the sound doesn't immediately stop. It plays the whole audio instead, doesn't matter whether it's looping or not. (Now when it loops it never stops). I tried putting the soundpool.stop(aStream) directly in the MotionEvent.ACTION_UP but it's still the same.

In the rotate_method, the stream variable has an underline and it says "The value soundPool.play(sharp, 1, 1, 0, loop_num, 1) assigned to stream is never used." Like yeah it's not used, it's just for playing the audio.

The trial code doesn't have this 'disclaimer'.

What did I do wrong? Why is the soundpool behaving differently in the trial code and in my app?


Solution

  • SoundPool.play() returns a streamID that you need if you want to stop the playback.

    In your trial code you assign that value to some field fStream:

    fStream = soundPool.play(F4, 1, 1,0,-1,1);
    

    and use it to stop the playback when you want to stop it:

    soundPool.stop(fStream);
    

    In your "production" code you assign that value to a parameter:

    public void rotate_method(int note, int sharp, int stream, int loop_num){
        stream = soundPool.play(sharp, 1, 1,0,loop_num,1);
        // stream is a method parameter here and changes are lost!
    }
    

    You must instead store the returned value in some field - why not reuse the field from the previous sample:

    public void rotate_method(int note, int sharp, int stream, int loop_num){
        fStream = soundPool.play(sharp, 1, 1,0,loop_num,1);
    }
    

    And since you now no longer need the parameter you should remove it from the method:

    public void rotate_method(int note, int sharp, int loop_num){
        fStream = soundPool.play(sharp, 1, 1,0,loop_num,1);
    }
    

    This change will propagate back to the calling methods.