Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Streaming MP3 audio via socket communication using OpenSL ES on Android

I'm trying to stream an MP3 from an Android phone to another Android phone using WiFi via an access point. The problem is that OpenSL ES appears to only support PCM audio buffers as the source (unless using a URI). Rather than decoding a potentially huge file on the "Master" side before sending I would prefer to let the "Client" decode the MP3 into PCM. Keep in mind that this has to occur AS the file streams rather than simply sending the whole file and then decoding. Is there any way to accomplish this using OpenSL ES? AudioTrack? It seems like it would be a fairly common request.

like image 711
honeal Avatar asked Jan 30 '13 17:01

honeal


People also ask

What does enable OpenSL es mean?

OpenSL ES (Open Sound Library for Embedded Systems) is a royalty-free, cross-platform, hardware-accelerated, C-language audio API for 2D and 3D audio. It provides access to features such as 3D positional audio and MIDI playback.

What does OpenSL ES do?

OpenSL ES provides a C language interface as well as C++ bindings, allowing you to call the API from code written in either language. The OpenSL ES APIs are available to help you develop and improve your app's audio performance. The standard OpenSL ES headers <SLES/OpenSLES.


1 Answers

You are correct that opensl doesn't appear to take a simple buffer queue with mp3 source. That being said, you should be able to use an SLDataLocator_URI instead. Now, I understand that you don't have the full file available when you start (since you are streaming), but there is a way around this. If you create an empty file, and use it as the source for the opensl URI player everything should work. As you get data (bits of the mp3 file), just add this data to the empty file you created. You can have OpenSL start playing from this file before you are finished appending data to it.

Create an empty file with:

RandomAccessFile raf = new RandomAccessFile(new File(mFileUri), "rw");
raf.setLength(audioFileSize);

Create your audio source as:

SLDataLocator_URI loc_uri = {SL_DATALOCATOR_URI, (SLchar *) fileLoc};
SLDataFormat_MIME format_mime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
SLDataSource audioSrc = {&loc_uri, &format_mime};

Load buffers with:

for (int i = 0; i < BUFFER_COUNT; i++) {
    // get byte[] data from stream
    raf.seek(i*Constants.BUFFER_SIZE);
    raf.write(data);
}

Start playing audio at any time with OpenSL and then continue loading buffers. As long as you stay ahead of the curve in your streaming process, you should be fine.

like image 167
tboling1 Avatar answered Sep 29 '22 23:09

tboling1