I'm in the process of wring a music player that can play SID tracks (music
from the Commodore 64), and everything is progressing nicely, except that I
sometimes get audio stuttering.
The stuttering only happens when the player is in the background, and
another application has focus. It's most noticeable when a cpu heavy app
(like Google Earth) is running in the foreground.

I have tried adjusting the priority of my thread and increasing
the AudioTrack buffer size, but nothing has solved the stuttering problem.

I believe the problem is that generating the audio takes quite a lot of
cycles (I'm at 15-30% cpu load), and that my audio thread is being starved
and cant keep up with AudioTrack's constant need for data.

I'm must be doing something wrong, I can't imagine that gui threads should
be able to starve a high priority audio thread.
I hope someone have some ideas on how to get my player stutter free, as I'm
at a loss :)

This is a small test function that kinda emulates what I'm doing, and also
have the same stuttering problem:
(full test project at http://github.com/jhansen/android_test_audio_stutter )

 private void play()
  {
    if(m_thread == null)
    {
      m_thread = new Thread(new Runnable()
      {
        public void run()
        {
          m_wakeLock.acquire();
          Process.setThreadPriority(Process.THREAD_PRIORITY_AUDIO);

          int minBufferSize = AudioTrack.getMinBufferSize(44100,
AudioFormat.ENCODING_PCM_16BIT, AudioFormat.CHANNEL_CONFIGURATION_MONO);
          AudioTrack audio = new AudioTrack(AudioManager.STREAM_MUSIC,
44100, AudioFormat.CHANNEL_CONFIGURATION_MONO ,
AudioFormat.ENCODING_PCM_16BIT, minBufferSize*4, AudioTrack.MODE_STREAM);
          audio.play();

          // generate sinus tone
          short[] audioBuffer = new short[1024];
          for(int i=0; i<audioBuffer.length; i++)
            audioBuffer[i] =
(short)(Math.sin(i*Math.PI/audioBuffer.length*64)*32765.0f);

          long sleepDuration = audioBuffer.length*1000000000l/44100/3;

          // find out how many cyces to waste to spend around 1/3 of the
total avilable time between AudioTrack writes
          // to increase the change of getting at least one uninterrupted
run, run the profile a few times:
          int loopsPerBuffer = 0;
          for(int j=0; j<10; j++)
          {
            long profileStart = System.nanoTime();
            for(int i=0; i<1000; i++)
              m_dummy += i; // to prevent the compiler from removing the
loop
            long profileDuration = System.nanoTime()-profileStart;
            if(loopsPerBuffer==0 ||
sleepDuration/profileDuration<loopsPerBuffer)
              loopsPerBuffer = (int)(sleepDuration/profileDuration);
          }
          Log.v("StutterTest", "loopsPerBuffer:"+loopsPerBuffer);

          while(!Thread.interrupted())
          {
            // to simulate expensive audio processing, burn about 1/3 of the
cycles between writes:
            for(int j=0; j<loopsPerBuffer; j++)
            {
              for(int i=0; i<1000; i++)
                m_dummy += i;
            }

            audio.write(audioBuffer, 0, audioBuffer.length);
          }

          audio.stop();
          audio.release();

          m_wakeLock.release();
        }
      });
      m_thread.start();
    }
  }

-- 
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

To unsubscribe, reply using "remove me" as the subject.

Reply via email to