I\'m trying to figure how I would use a buffer with AudioTrack to effectively stream music. I know you can queue audio using the write method but once the audio is queued how do
*This code will help to play audio with buffer*
private void PlayShortAudioFileViaAudioTrack(String filePath) throws IOException
{
// We keep temporarily filePath globally as we have only two sample sounds now..
if (filePath==null)
return;
//Reading the file..
byte[] byteData = null;
File file = null;
file = new File(filePath);
// for ex. path= "/sdcard/samplesound.pcm" or "/sdcard/samplesound.wav"
byteData = new byte[(int) file.length()];
FileInputStream in = null;
try {
in = new FileInputStream( file );
in.read( byteData );
in.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// Set and push to audio track..
int intSize = android.media.AudioTrack.getMinBufferSize(8000, AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_8BIT);
AudioTrack at = new AudioTrack(AudioManager.STREAM_MUSIC, 8000, AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_8BIT, intSize, AudioTrack.MODE_STREAM);
if (at!=null) {
at.play();
// Write the byte array to the track
at.write(byteData, 0, byteData.length);
at.stop();
at.release();
}
else
Log.d("TCAudio", "audio track is not initialised ");
}
AudioTrack.write() returns "number of bytes written" as an int, and you specify the number of bytes in the buffer when constructing the AudioTrack.
Therefore, to track how much buffer space remains, you could keep an accumulator variable so you know how many bytes have been written in total, and set this variable to zero whenever you call AudioTrack.flush(). However, the linked documentation states "it is typical to use chunks of 1/2 of the total size to permit double-buffering", so it might be simple enough to simply remember if you've written zero, once or twice since calling flush.
To tell how much of the buffer has been played, use AudioTrack.getPlaybackHeadPosition() which returns the number of frames that have been played of the current buffer (i.e. reset to zero on stop, flush or reload) as signed 32-bit integer but to be interpreted as an unsigned 32-bit integer. All this really means is that you assign it to an int as follows.
int bufferPlaybackFrame = myAudioTrack.getPlaybackHeadPosition() & 0xFF;
You can think of frames as equivalent to samples. i.e. You can work out from the AudioFormat used to construct the AudioTrack how many bits (and hence bytes) are being used per sample.
Finally, in case someone was wondering, you'll never be able to tell how much of the source file or stream is left to play through this object (one reason being it's designed to work with permanent 24/7 streams, with no ending), so if you wanted to make a calculation like you see on some video playing websites, that pause the stream until enough id buffered to see the whole video at your current download rate, you'll have to pass that information in some other way.