BASS for Android

Started by Ian @ un4seen,

bjadams

#25
There is a LIB folder in the APK.
libbass.so is actually inside this directory.

raczynski


Ian @ un4seen

Quote from: bjadamsThere is a LIB folder in the APK.
libbass.so is actually inside this directory.

Yes, that's fine. The problem is that the OS can't find the LIBBASS.SO file because the LIB folder isn't in the library search path. Note, unlike Windows, Android (and other Unix-like OS) won't automatically look in the executable's folder for libraries. So you need to be able to either modify the library search path or provide the library's full path. The SONAME tweak/hack I mentioned achieves the latter. Another option is to dynamically load the library, rather than linking with it. To do that, you would remove the "LOCAL_SHARED_LIBRARIES := bass" build rule and add "-ldl" to the "LOCAL_LDLIBS" rule, and do something like this in your code...

#include <dlfcn.h>
#define BASSDEF(f) (*f) // define the BASS functions as pointers
#include "bass.h"

...

BOOL LoadBASS()
{
// load the BASS library and get the needed functions
void *basslib=dlopen("/data/data/<packagename>/lib/libbass.so", RTLD_LAZY);
if (!basslib) return FALSE; // failed
#define LOADBASSFUNCTION(f) *((void**)&f)=dlsym(basslib, #f)
LOADBASSFUNCTION(BASS_ErrorGetCode);
LOADBASSFUNCTION(BASS_Init);
...
}

bjadams

If I remove "LOCAL_SHARED_LIBRARIES := bass" then libbass.so is not included in the .apk in LIB :(

Bass4Android

Hi!

Actually i am trying to make my Android App gapless playback friendly. I found here an example on this forum, but it crashes my VM (on Emulator,, didn't try this code on my phone). I have uploaded the logcat as an image cause eclipse doesn't export it to the Log.txt.



if(BASS.BASS_Init(-1, 44100, BASS.BASS_DEVICE_DEFAULT)) {
    BASS.STREAMPROC sp = new STREAMPROC() {
        public int STREAMPROC(int handle, ByteBuffer buffer, int length, Object user) {
            // This code is incomplete, only one Return for Testing...
            return BASS.BASS_ChannelGetData(stream1, buffer, length);
        }
    }

    this.stream1 = BASSWV.BASS_WV_StreamCreateFile(file, 0, 0, BASS.BASS_STREAM_DECODE);

    BASS.BASS_CHANNELINFO info = new BASS_CHANNELINFO();
    BASS.BASS_ChannelGetInfo(this.stream1, info);

    stream = BASS.BASS_StreamCreate(info.freq,info.chans,0,sp,0);
   
    // This one causes the error, in the example is BASS_StreamPlay() used, but this method doesen't here?
    BASS.BASS_ChannelPlay(this.stream, false);
}

Thank you! :)

Ian @ un4seen

Quote from: bjadamsIf I remove "LOCAL_SHARED_LIBRARIES := bass" then libbass.so is not included in the .apk in LIB :(

That's strange. Did you still keep the BASS library rule block? "LOCAL_MODULE := bass", etc.

Quote from: Bass4AndroidActually i am trying to make my Android App gapless playback friendly. I found here an example on this forum, but it crashes my VM (on Emulator,, didn't try this code on my phone). I have uploaded the logcat as an image cause eclipse doesn't export it to the Log.txt.

Ah yes, there was a problem in the Java STREAMPROC callback handler. An update to correct that is now up in the package (in the 1st post). Let me know if you still have any trouble with it.

Bass4Android

Hi,

thx 4 update, seems to work now. But i don't hear any sound. Is there something wrong in my code?

Thank you

bjadams

Yes, "LOCAL_MODULE := bass" is still there.

If you have some time, can you maybe test with the project files I uploaded on the ftp?

Thanks a lot.

Ian @ un4seen

Quote from: Bass4Androidthx 4 update, seems to work now. But i don't hear any sound. Is there something wrong in my code?

Oops! There was still a problem in the Java STREAMPROC callback handler (it was ignoring the return value). Another update to correct that is up now (in the 1st post).

Quote from: bjadamsIf you have some time, can you maybe test with the project files I uploaded on the ftp?

Ah, I see what you mean. Removing the "APP_MODULES" line from your Application.mk file (or else adding "bass" to it) should sort that.


Ian @ un4seen

An Android version of the BASSMIDI add-on is now available (see the 1st post), along with a port of the MIDITEST example.

fulbert

#36
Hi,

Does the current BASS for Android support pushing data to stream [STREAMPROC_PUSH] as the enumeration for this does not seem to exist?

Edit: Nmind what I said above, rather how do I create a stream for push?

Ian @ un4seen

The Java class was missing the required BASS_StreamCreate overload for dummy/push stream support. An update to address that is up now (in the 1st post). Using that, you can create a push stream like this...

stream=BASS.BASS_StreamCreate(freq, chans, flags, BASS.STREAMPROC_PUSH, null);

fulbert

Thanks! I will give it a go when I am back in office. Merry Christmas!

fulbert

Yup the push stream is working. Thanks!

Will BASS_FX be available for Android as well and if so is there an estimate on when it will be available?

Ian @ un4seen

There are plans for an Android version of BASS_FX, but it's at an early stage, so it's hard to say when it may become available at this point.

Mike

#41
This may be a daft question because I'm a newbie to Java, Android and Eclipse (I come from a C++/VS background), but I'm having difficulty getting the BASS MIDI test app to link against the libraries. I've copied the libs folder into the miditest folder (i.e. alongside assets, bin etc.), which I believe to be correct, but as soon as the app tries to call BASS.BASS_Init(-1, 44100, 0), it throws an 'UnsatisfiedLinkError' exception and dies.

In case it's of any relevance, I'm trying to run the app on the Samsung Galaxy Tab.

Any help or suggestions greatly appreciated!

Michael

P.S. My stupid mistake, which I pretty much expected would be the case! I'd somehow managed to stomp over the BASS .so files with the BASS MIDI ones, so they went missing from the libs folder.

Ian @ un4seen

That looks like the BASS library is missing from the "libs" folder. Did you copy the contents of both the root and BASSMIDI "libs" folders into your "libs" folder? The folder's contents should look like this...

   armeabi
      libbass.so
      libbassmidi.so
   armeabi-v7a
      libbass.so
      libbassmidi.so

Note after making a change to the "libs" folder, you may need to "Refresh" it in Eclipse.

helri

Hi,

I'm using BASS for android and it's working perfectly in an Android device with API version 2.3.1.

But, in a device using 2.1 version i'm getting an error calling the method BASS.BASS_Init(-1, 44100, 0). The error is 39 which I think means BASS_ERROR_DX.

How can I bypass this error? should I use any flags in BASS_init? I only need audio, don't need any video capabilities, at least for now.

Thank you and good work!

Ian @ un4seen

On the Android platform, the BASS_ERROR_DX error code indicates that OpenSL ES is unavailable, which is the native audio API that BASS uses (like DirectSound on Windows). Unfortunately, it was only introduced in Android 2.3, so playback/recording isn't supported with earlier Android versions. The "no sound" device is still available though, so it is possible to use "decoding channels" with that, eg. they could be fed into the older AudioTrack system.

helri

#45
Quote from: Ian @ un4seenOn the Android platform, the BASS_ERROR_DX error code indicates that OpenSL ES is unavailable, which is the native audio API that BASS uses (like DirectSound on Windows). Unfortunately, it was only introduced in Android 2.3, so playback/recording isn't supported with earlier Android versions. The "no sound" device is still available though, so it is possible to use "decoding channels" with that, eg. they could be fed into the older AudioTrack system.

Thank you Ian.

It seems trickier then :)

Let me see if I understood correctly:
  - I should use BASS_Init with device 0.
  - then in the BASS_StreamCreateURL (which i'm using to play the track in 2.3) I use the flag BASS_STREAM_DECODE
  - then I should pass the decoded bytes to AudioTrack? To access to the decoded bytes from BASS should I use SYNCPROC?

Thank you!

Ian @ un4seen

That is pretty much the right idea, but to access the decoded data, you would use BASS_ChannelGetData rather than a SYNCPROC. The code might look something like this...

BASS.BASS_Init(0, 44100, 0); // initialize "no sound" device
decoder=BASS.BASS_StreamCreateURL(url, 0, BASS.BASS_STREAM_DECODE, null, null); // create a "decoding channel" from a URL
buffer=ByteBuffer.allocate(20000); // allocate buffer for decoded data

...

int res=BASS.BASS_ChannelGetData(decoder, buffer, buffer.capacity()); // decode some data
if (res>0) audiotrack.write(buffer.array(), 0, res); // feed it to AudioTrack

You can use BASS_ChannelGetInfo to get the stream's sample format to initialize the AudioTrack output with.

helri

Quote from: Ian @ un4seenThat is pretty much the right idea, but to access the decoded data, you would use BASS_ChannelGetData rather than a SYNCPROC. The code might look something like this...

BASS.BASS_Init(0, 44100, 0); // initialize "no sound" device
decoder=BASS.BASS_StreamCreateURL(url, 0, BASS.BASS_STREAM_DECODE, null, null); // create a "decoding channel" from a URL
buffer=ByteBuffer.allocate(20000); // allocate buffer for decoded data

...

int res=BASS.BASS_ChannelGetData(decoder, buffer, buffer.capacity()); // decode some data
if (res>0) audiotrack.write(buffer.array(), 0, res); // feed it to AudioTrack

You can use BASS_ChannelGetInfo to get the stream's sample format to initialize the AudioTrack output with.

Thank you! I'm working on it!

helri

#48
Ian, it is working but only for a few seconds. The music starts playing but after some seconds the app crashes with a SIGBUS in libbass.so:
01-03 16:19:55.304: I/DEBUG(25736): signal 7 (SIGBUS), fault addr 00000000
01-03 16:19:55.308: I/DEBUG(25736):  scr 20000012
01-03 16:19:55.359: I/DEBUG(25736):          #00  pc 0000adfc  /data/data/com.example.miditest/lib/libbass.so
01-03 16:19:55.362: I/DEBUG(25736):          #01  pc 00017f46  /data/data/com.example.miditest/lib/libbass.so
01-03 16:19:55.362: I/DEBUG(25736):          #02  pc 00019260  /data/data/com.example.miditest/lib/libbass.so

the code that i'm using is the following:

chan=BASS.BASS_StreamCreateURL(url, 0, BASS.BASS_STREAM_DECODE, null, null)
track = new AudioTrack( AudioManager.STREAM_MUSIC, 44100,
    AudioFormat.CHANNEL_CONFIGURATION_STEREO, AudioFormat.ENCODING_PCM_16BIT,
    AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_CONFIGURATION_STEREO, AudioFormat.ENCODING_PCM_16BIT), AudioTrack.MODE_STREAM);


track.play();

new Thread(new Runnable(){
public void run() {
ByteBuffer buffer = ByteBuffer.allocate(20000); // allocate buffer for decoded data
int res=BASS.BASS_ChannelGetData(chan, buffer, buffer.capacity()); // decode some data

while (res>0){
track.write(buffer.array(), 0, res); // feed it to AudioTrack
res=BASS.BASS_ChannelGetData(chan, buffer, buffer.capacity()); // decode some data
}
}
}).start();

The idea with the thread is to feed the audioTrack while there's data to decode...

do you have any idea why i'm getting the SIGBUS error inside libbass.so?




Ian @ un4seen

That's strange; I gave your code a try, and it seems to be working fine. Is the crash happening with a particular URL, and is it happening in the BASS_ChannelGetData call or is it in another thread? Perhaps your thread has already exited before the crash occurred? Note BASS_ChannelGetData won't wait for data to become available (it will return 0 if there is no data currently available), so your "while" loop could exit earlier than expected. To leave on an error, you could modify it like this...

while (res!=-1){
if (res>0) track.write(buffer.array(), 0, res); // feed it to AudioTrack
else Thread.sleep(50); // wait a bit for more data to arrive
res=BASS.BASS_ChannelGetData(chan, buffer, buffer.capacity()); // decode some data
}