简体   繁体   English

如何正确使用线程/运行循环并使用SoundPool播放声音?

[英]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). 我正在构建一个以选定速度(bpm)播放音乐序列的应用程序。 I'm currently using a thread to fire a function every beat which then plays sounds using SoundPool. 我目前正在使用一个线程在每个节拍上触发一个函数,然后使用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? 这是因为将播放声音所需的时间添加到了playingThread睡眠的时间上吗?

Should soundPool.play be in a background thread rather than the UI thread? soundPool.play应该在后台线程而不是UI线程中吗?

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. 对于Android 2.3.4来说还不错,但是由于某些原因,对于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并非为音乐所要求的精确度而设计。 SoundPool is designed to be reactive to input, generating sounds when triggers occur, sometimes often eg a game. SoundPool被设计为对输入具有反应性,当触发发生时(有时在例如游戏中)会生成声音。 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. 我建议使用AudioTrack并直接写入音频缓冲区。 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! 在延迟方面,您仍然受制于Android OS 硬件实现,但至少每个节拍都是稳定的!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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