AudioTrack in streaming mode MODE_STREAMING

16,743

Here is short example that works for me:

public class Internal extends Activity
{   
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);              
    }

    public void onPlayClicked(View v)
    {
        start();    
    }

    public void onStopClicked(View v)
    {
        stop();
    }

    boolean m_stop = false;
    AudioTrack m_audioTrack;
    Thread m_noiseThread;

    Runnable m_noiseGenerator = new Runnable()
    {       
        public void run()
        {
            Thread.currentThread().setPriority(Thread.MIN_PRIORITY);

            /* 8000 bytes per second, 1000 bytes = 125 ms */
            byte [] noiseData = new byte[1000];
            Random rnd = new Random();

            while(!m_stop)
            {           
                rnd.nextBytes(noiseData);   
                m_audioTrack.write(noiseData, 0, noiseData.length);                 
            }
        }
    };

    void start()
    {
        m_stop = false;

        /* 8000 bytes per second*/
        m_audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_OUT_MONO,
                                        AudioFormat.ENCODING_PCM_8BIT, 8000 /* 1 second buffer */,
                                        AudioTrack.MODE_STREAM);            

        m_audioTrack.play();        


        m_noiseThread = new Thread(m_noiseGenerator);
        m_noiseThread.start();
    }

    void stop()
    {
        m_stop = true;          
        m_audioTrack.stop();
    }   
}
Share:
16,743
Raffaele
Author by

Raffaele

"Always be the worst guy in every band you’re in" "Eventually you realize you have no idea what you are doing and you do what you should have done in the 1st place - read papers" "...because Jon Skeet doesn't achieve badges, badges achieve Jon Skeet"

Updated on July 18, 2022

Comments

  • Raffaele
    Raffaele almost 2 years

    I need to stream PCM data generated at runtime. So I have a thread with a loop

    public void run() {
      while(...) {
        mAudioTrack.write(getPCM(), ...);
      }
    }
    

    Unfortunately this doesn't work. It seems it doesn't depend on AudioTrack buffer size. I want it to be very small to simulate sort of low latency behaviour (150 ms) so the user can dinamically change the PCM picked by getPCM()

    int bufferSize = 0.150 * sampleRate * channels * bitsPerSample / 8;
    

    However, I tried to increase the buffer size up to 100k with no result

  • Raffaele
    Raffaele almost 13 years
    Don't know what you mean. I cannot hear anything
  • inazaruk
    inazaruk almost 13 years
    This code works on two devices (both Samsung though). Check your LogCat logs, it should print all the details about AudioTrack.
  • Raffaele
    Raffaele almost 13 years
    Sure, I had to add a call to start() upon activity creation. Then it's a mistery it doesn't work with actual PCM data. Now I'm going to test with a machine-generated A 440hz sound
  • Raffaele
    Raffaele almost 13 years
    Sure, your code definetly solves the problem (in theory). Now I have to understand what's wrong with my code
  • Raffaele
    Raffaele almost 13 years
    @inazaruk How would you measure the average write delay? I modified your code a bit to play a fixed sound, and configured AudioTrack with a small buffer, so you can hear the underrunning. Here you are the code and the eclipse proj
  • inazaruk
    inazaruk almost 13 years
    I'm not sure I understood your question. What do you mean under write delay? How long it takes to play your buffer of X bytes?
  • inazaruk
    inazaruk almost 13 years
    Oh, I got it. You do not need to put Thread.Sleep in writer AudioTrack thread. The AudioTracker.write is blocking. It will only return, when there is free space in its buffer (size of which is specified in its constructor). So you shouldn't worry about buffer overflow and just remove Sleep method from writer thread.