AudioTrack - how to know when a sound begins/ends?

mikemeli picture mikemeli · Sep 7, 2012 · Viewed 8k times · Source

I am using Audio track to play a different sounds, in stream mode. I would like to know if there is a way to know when each sound beings/ends playing.

I create the audio track like this:

AudioTrack tmpAudioTrack = new AudioTrack(
        STREAM_TYPE, 
        SAMPLE_RATE, 
        CHANNEL_CONFIG_TYPE, 
            AUDIO_FORMAT_TYPE, 
        getOptimalBufferSize(), 
        AUDIO_TRACK_MODE);'

And start it in a background thread:

backround_thread = new Thread(new MyRunnable(aTrack));
    backround_thread.start();   

I write each sound like this inside the runnable:

byte generatedSnd[] = new byte[2 * beepSamples];
<code for filling the buffer with sound here>
int bytesWritten = track.write(generatedSnd, 0, generatedSnd.length);

It is possible to use any of the AudioTrack APIs such setNotificationMarkerPosition, or setLoopPoints, or setPositionNotificationPeriod to accomplish this? and how do they work?

Each sound can be different duration of time. I think this is key.

I don't fully understand the documentation for these APIs. Is each frame the same as a sample? How do I specify a marker for where each sound begin/end?

Thanks,

Answer

mikemeli picture mikemeli · Sep 12, 2012

This is what I have found out:

To me, frames are samples -- the duration of the sound multiplied times the sample rate.

To use AudioTrack.setPositionNotificationPeriod, you pass an amount of samples. Meaning if you pass 200 samples, the callback will be called every 200 samples, recurrent.

tmpAudioTrack.setPositionNotificationPeriod(duration * sampleRate);

To use .setNotificationMarkerPosition, you also pass an amount of samples. However, this is absolute and not relative like for the period API. So if you want to determine when a sound ends, you pass the sample amount (total sound track duration * sampleRate).

tmpAudioTrack.setNotificationMarkerPosition(duration * sampleRate);

But, if you are already playing, in the middle of your sound track, and want to add a marker so you will get called back let's say 3 seconds from now, then you would need to add the current playhead of the audio track, like this: (where your duration is 3 seconds)

tmpAudioTrack.setNotificationMarkerPosition(tmpAudioTrack.getPlaybackHeadPosition() + (duration * sampleRate));

And this is how you get registered for the period and marker notifications:

tmpAudioTrack.setPlaybackPositionUpdateListener(new OnPlaybackPositionUpdateListener(){

    @Override
    public void onMarkerReached(AudioTrack arg0) {

    }

    @Override
    public void onPeriodicNotification(AudioTrack arg0) {

    }

});