RNBO C++ export running natively on Android

StuartM's icon

I've had an itch to really explore what is possible with the C++ export functionality provided by RNBO and what its limitations are...

While it seemed to work pretty flawlessly in desktop applications I thought about the many years of using UDP to send signals from my phone to Max MSP over networks and wondered whether it would be finally possible to have everything packaged up as an Android app.

After a few brain-scratching days, I've come up with a slightly hacky solution - fixing problems as they arise in the exported RNBO library code. It's early days but I've put up a Git repository which I'll keep updating as I make the process a little more stable.

StuartM's icon

One of the first issues that arises when trying to include the RNBO files in an Android project is that the "RNBO_PlatformInterface" class produces a "SIGSEGV" error - a segmentation error when a function is retrieved via "Platform::get()-> ..." . This works fine when building for desktop (using MSVC 14.34.31933) but doesn't with Clang (Android Studio's compiler of choice). I assume the issue lies with LLVM libc++. I'll do some more digging.

By converting all Platform::get()-> calls to their counterpart stdlib calls (and just including the stdlib platforminterface to cover the "toString()" call) the library builds properly and runs!

void setName(const char *name) {
            if (_name) Platform::get()->free(_name);
            size_t len = Platform::get()->strlen(name);
            _name = static_cast<char *>(Platform::get()->malloc((len + 1) * sizeof(char)));
            Platform::get()->strcpy(_name, name);
        }
StuartM's icon

In terms of actually getting sound out, the Oboe library (which polyfills AAaudio configurations for older versions of Android) provides a useful custom callback to call the rnbo process function.


oboe::DataCallbackResult
SimpleNoiseMaker::onAudioReady(oboe::AudioStream *oboeStream, void *audioData, int32_t numFrames) {
    rnboObject.process(nullptr, 0, pMyCustomData->outputs,1, numFrames);
    float* fOutput = (float*)audioData;

    float temp = 0;

    for(unsigned int i = 0; i < numFrames; i++) {

        *fOutput++ = (float) (pMyCustomData->outputs[0][i]);
    }

    return DataCallbackResult::Continue;
}
👽'tW∆s ∆lienz👽's icon

(Just wanted to give a quick: "Thank You" for documenting your process here 💜)

Alex Norman's icon

STUARTM,

Have you tried explicitly setting a platform interface before running the RNBO code?

I *think* the stdlib one should work but maybe there is some issue with static initialization since you're building RNBO as a library?

StuartM's icon

Yes! This was going to be my next step.
The sigsegv fault is pretty tedious to navigate during debug. I'll post an update once I get round to it.

Pedro Nonino's icon

Wow thats really cool! Didn't tested yet but that was exactly what I was looking for :), thank you!!

StuartM's icon

That's it! I think I had some issues with the "build.gradle" project configuration that have been resolved by starting afresh and using the latest NDK - it runs with or without the platform interface being explicitly set.

It's now working with automatically generated UI sliders and is available at: https://github.com/StuartMellor/Max-MSP-RNBO-CPP-Native-Android

Alex Norman's icon

STUARTM,
Do you mean that you no longer have to alter the generated code?

StuartM's icon

That's right! I'll compare the versions to see what was different in each and post here.

Alex Norman's icon

Happy to hear that!