Best way to stream Ogg Vorbis on Android

2.8k Views Asked by At

There seem to be several ways to play an Ogg Vorbis audio stream on Android, but so far I'm having various issues with all of them. There doesn't really seem to be much information on the net about the "right" way to do this.

First my requirements: Stream music from Ogg files, stored in my res/raw directory. I have two files, intro.ogg and loop.ogg. Intro should play first, followed by loop, which should then be repeated as long as the music keeps playing. There should be absolutely no gap between the streams, and I want to support older versions of Android - at least as old as 4.0, or 2.x if possible.

I've found three ways to do this:

1) MediaPlayer. The most often recommended way. Issues: To queue two streams, I have to use setNextMediaPlayer(), which was only introduced in API level 16. Also, there's a small but noticeable gap between the streams (at least on my N4 running 4.3). When trying to replace setNextMediaPlayer() with a custom completion listener, I can't seem to get gapless playback either.

2) AudioTrack, MediaExtractor and MediaCodec. Seems to be pretty much what MediaPlayer does internally. Issues: Only available starting with API level 16. Also, at the moment I'm getting small gaps between streams. Since #3 below works gaplessly, I suppose I should be able of getting rid of that though (documentation seems to be very thin here).

3) AudioTrack and custom Ogg decoding. The jogg/jorbis JARs work fine for this purpose. Playback and queuing are gapless. Issue: It's slow. On my old N1, it causes enough slowdown to affect the frame rate slightly and the input responsiveness strongly.

I suppose #1 and #2 take advantage of any hardware decoding support the device may have, whereas #3 obviously runs purely in software. MediaPlayer doesn't seem to cause performance issues when playing an Ogg stream on my N1, but I can't get queuing because of the lower API level.

Is there any way around this problem? Or am I stuck with skipping the intro cue and trying to do a crude fade in on the loop cue for older devices?

(Also, if anyone can could confirm that I should be able to achieve real gapless playback with MediaExtractor & MediaCodec, or point me to a good howto, that would be helpful)

1

There are 1 best solutions below

0
On

My suggestion would be to use the NDK to get a vorbis decoder running natively (perhaps Tremor), and then utilize that MUCH FASTER native decoder from your app instead of using the much slower jogg/jorbis java decoder. (It will probably be at least an order of magnitude faster than the java decoder)

You can then use the AudioTrack class to take the native decoded PCM and write it out to the audio device.

I would be surprised if someone hasn't already done this, so google around first!