简体   繁体   中英

How to properly use a thread/run loop and play sounds with SoundPool?

I'm building an app that plays musical sequences at a chosen tempo (bpm). I'm currently using a thread to fire a function every beat which then plays sounds using SoundPool. However, the more sounds that play at once the slower the tempo becomes!

Is this because the time it takes to play a sound is added onto the time the playingThread sleeps?

Should soundPool.play be in a background thread rather than the UI thread?

I'm also getting sync issues where it speeds up randomly and slows down and if two sounds are played at the same time they don't always play at exactly the same time. It wasn't so bad with Android 2.3.4 but for some reason really bad with Android 4.2.2.

What's the best way to achieve a consistent tempo and sync?

Here is my thread:

public void playingThread()
{
    //Time interval in ms for thread sleep
    final long intervalInMs = (long) ((1 / (float) theBpm) * 60 * 250);

    Thread thread = new Thread() {
        @Override
        public void run() {
            while(playing == true) {
                beat();
                try {
                    Thread.sleep((long)(intervalInMs));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };
    thread.start();
}

Then it calls this function, which has a lot of additional logic to calculate which sounds to play and stop etc:

public void beat()
{
    currentBeat++;

    //Play click sound every four beats
    if(currentBeat % 4 == 0) {
        soundPool.play(clickSoundId, 0.5f, 0.5f, 1, 0, 1f);
    }

    //ADDITIONAL LOGIC TO DETERMINE WHICH SOUNDS TO PLAY...

    int streamId = soundPool.play(soundIds[i], 1f, 1f, 1, 0, 1f);
}

Thanks

Don't use a Thread, and never sleep the main application thread. Use a Handler. A Handler allows you to schedule something to happen in the future without sleeping the main thread. See my answer here

Music is always time-critical. SoundPool isn't designed for the level of precision demanded by music. SoundPool is designed to be reactive to input, generating sounds when triggers occur, sometimes often eg a game. When generating music often you know what sounds are going to occur when so you can schedule them better.

I'd suggest using AudioTrack and writing directly to the audio buffers. That's the only way to have full control over when the sounds are played in relation to each other. You're still at the mercy of the Android OS and the hardware implementation when it comes to latency, but at least each beat will be steady!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM