4

I try to play a short .mp3 sound (beep) continuously, 100 times a minute. It plays around 30-45 times correctly (more on newer devices), then it stops for some time (~30 seconds), and then plays again (~10 times only).

I tried both SoundPool (playBeepSound1) and MediaPlayer (playBeepSound2) so maybe I'm using Handler wrong.

    private val delay: Float = 60.0F / 100.0F * 1000.0F // 100 times per minute

    private var handler: Handler? = null
    private var soundPool: SoundPool? = null
    private var mediaPlayer: MediaPlayer? = null

    override fun onResume() {
        super.onResume()
        startBeeping()
    }

    private fun startBeeping() {
        handler = Handler()
        handler?.postDelayed(object : Runnable {
            override fun run() {
                handler?.postDelayed(this, delay.toLong())
                playBeepSound1() // SoundPool
//                playBeepSound2() // MediaPlayer
            }
        }, delay.toLong())
    }

    private fun playBeepSound1() {
        val attributes = AudioAttributes.Builder()
            .setUsage(AudioAttributes.USAGE_GAME)
            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
            .build()

        soundPool = SoundPool.Builder()
            .setAudioAttributes(attributes)
            .build()

        soundPool?.setOnLoadCompleteListener { soundPool, soundId, _ ->
            soundPool.play(soundId, 1.0f, 1.0f, 0, 0, 1.0f);
        }
        soundPool?.load(baseContext, R.raw.beep_sound, 1)
    }

    private fun playBeepSound2() {
        mediaPlayer = MediaPlayer.create(this, R.raw.beep_sound)
        mediaPlayer?.start()
    }

    override fun onPause() {
        super.onPause()
        stopBeeping()
    }

    private fun stopBeeping() {
        handler?.removeCallbacks(this)
        handler = null

        soundPool?.release()
        soundPool = null

        mediaPlayer?.release()
        mediaPlayer = null
    }

Any ideas about how can I play a short sound in a loop?

Update:

I tested it on different devices with different OS version (Android 6, Android 9, also emulators) and the result is almost the same. The only difference is the time after it stops beeping.

The mp3 file has a size of 5KB.

KlimczakM
  • 12,576
  • 11
  • 64
  • 83
  • 1
    In both cases, you're creating new instances each time you play, and never releasing the old ones. Instead, create one instance, and just replay it over and over. – Mike M. Apr 25 '20 at 20:06
  • @MikeM. you were right! After creating one instance, MediaPool `start()` works correctly, but SoundPool `play()` doesn't play any sound... – KlimczakM Apr 30 '20 at 06:13

1 Answers1

0

I don't know kotlin, but this is how I would do in Java with MediaPlayer.

MediaPlayer player=MediaPlayer.create(MainActivity.this,R.raw.beep_sound);
for(int i=0;i<45;i++){
    //the for loop will make it run 45 times
    player.start();
    //wait for 600 milliseconds because it's 100 times a minute
    Thread.sleep(600);
}
//stop for 30 seconds
Thread.sleep(30000);
//then this time play 10 times only
for(int i=0;i<10;i++){
    player.start();
    Thread.sleep(600);
}
Robotic Reaper
  • 417
  • 1
  • 4
  • 15
  • Thank you for the answer, but 1) 30s pause was a bug, not a requirement 2) I prefer handlers over calling sleep function. – KlimczakM May 02 '20 at 19:44