Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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,

like image 780
mikemeli Avatar asked Sep 07 '12 18:09

mikemeli


1 Answers

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) {

    }

});
like image 179
mikemeli Avatar answered Sep 24 '22 21:09

mikemeli