RNBO C++ export running natively on Android
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.
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);
}
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;
}
(Just wanted to give a quick: "Thank You" for documenting your process here 💜)
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?
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.
Wow thats really cool! Didn't tested yet but that was exactly what I was looking for :), thank you!!
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
STUARTM,
Do you mean that you no longer have to alter the generated code?
That's right! I'll compare the versions to see what was different in each and post here.
Happy to hear that!