2

I'm using AudioTrack to play a PCM WAV sound file on Android (see also here). Streaming mode, worker thread. I'm wondering how do I detect the end of sound so that I can release and free the AudioTrack. The write() call, it seems, is blocking - but does it block until the playback of the provided data is complete? Not so sure.

Is it me, or the docs on this class are woefully inadequate? If you happen to have a link to a nice unofficial guide to AudioTrack, I'd be willing to see one.

sjngm
  • 12,423
  • 14
  • 84
  • 114
Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • I don't know of any guides, but you can always go straight to the source: https://github.com/android/platform_frameworks_base/blob/master/media/java/android/media/AudioTrack.java – JesusFreke Oct 04 '11 at 02:38
  • There's almost no Java logic there - it's all calls to native functions. – Seva Alekseyev Oct 04 '11 at 02:54
  • Right - but that's the starting point to figure out how it works. You can always go look at the native code as well. – JesusFreke Oct 04 '11 at 03:41
  • Which is at https://github.com/android/platform_frameworks_base/blob/master/media/libmedia/AudioTrack.cpp . Now let's see if I can figure out the logic, provided I don't know squat about the underlying API. – Seva Alekseyev Oct 04 '11 at 15:06

1 Answers1

12

From my experience, AudioTrack.write() call does block until the data is written into HW's audio buffer.

So after write() finishes, the audio is guranteed to be played. Basically it works well.

To detect the end of audio more precisely, use AudioTrack.setNotificationMarkerPosition() and AudioTrack.setPlaybackPositionUpdateListener(). Note setNotificationMarkerPosition() count the audio samples (not the bytes), so if your audio is 16-bit sample, the position will be dataSize/2.

There is an example in my project: https://github.com/mine260309/android-sexypsf-player/blob/psf2/src/com/mine/psf/sexypsf/MineSexyPsfPlayer.java

Mine
  • 4,123
  • 1
  • 25
  • 46
  • In most simple cases you are surely right, but your statements are wrong. write() does not always guarantee that it plays what it gets. See next comment. – Janos Vinceller Mar 24 '20 at 22:58
  • 1
    Read the doc: In streaming mode, the blocking behavior depends on the write mode. If the write mode is WRITE_BLOCKING, the write will normally block until all the data has been enqueued for playback, and will return a full transfer count. However, if the write mode is WRITE_NON_BLOCKING, or the track is stopped or paused on entry, or another thread interrupts the write by calling stop or pause, or an I/O error occurs during the write, then the write may return a short transfer count. – Janos Vinceller Mar 24 '20 at 22:58
  • 1
    Also the statement "so if your audio is 16-bit sample, the position will be dataSize/2" is not precise, it depends from more than one thing. Number of channels and bytes per data per channel. And this easy calculation works only for linear uncompressed audio, like PCM, see AudioFormat#getBytesPerSample(). – Janos Vinceller Mar 24 '20 at 23:01