I've been delving into Android AudioTrack against my better interest. I am trying to seamlessly transition between two AudioTrack's playback, that is, one should pause and the other should start and there should be no gap between the two.
This works okay, but I have noticed that when calling the .pause() method on AudioTrack, it will 'pop' or 'crackle' when stopping playback of the sound. This is unsurprising, as suddenly stopping the playback of a sound in this manner (especially if it is at a high point) is bound to create these kinds of artifacts.
However, if I could fade out the playback of the AudioTrack when pause is called, this would be a non-issue. This is easier said than done, however, because it appears Android AudioTracks cannot be modified in place. I also can't use .setVolume() because I am targeting API 17 as my minimum so Android 4.0 users can still use my app.
Is there any way of doing this? My immediate thoughts were to create a new pause(AudioTrack at) method that would modify the AudioTrack buffer and allow it to quickly fade out, and then calling pause once it had faded. It isn't a huge deal for me if the pause occurs a few frames late if it means the popping sound will be gone. Unfortunately I don't see an easy way to do this.
Here's what I have so far:
if(event.getAction() == MotionEvent.ACTION_DOWN) {
audioTracks[noteToPlay].release();
audioTracks[noteToPlay] = new AudioTrack(AudioManager.STREAM_MUSIC,
sr, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, BUFFSIZE,
AudioTrack.MODE_STATIC);
writeSample(noteToPlay);
audioTracks[noteToPlay].play();
}
else if (event.getAction() == MotionEvent.ACTION_UP) {
short[] release = makeReleaseSample(noteToPlay);
AudioTrack releaseTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
sr, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, BUFFSIZE,
AudioTrack.MODE_STATIC);
releaseTrack.write(release, 0, release.length);
audioTracks[noteToPlay].pause();
releaseTrack.play();
}
As you can see, within the ACTION_UP handler I pause the audioTracks[noteToPlay] track and play the release track right after. The pop occurs on the pause, because the audioTracks[noteToPlay] contains a sine wave and pause is not pausing at the low point so it is creating artifacts.
Something to note is that the last frame of audioTrack and the first frame of release contain the same frame, so I know it's not a case of jumping from the point in the first audioTrack to the point in the second -- I am fairly certain it is due to the sudden cut-off of the first audioTrack.
Any ideas?