Cabbage Logo
Back to Cabbage Site

Cabbage FMOD Android .so support

First of all, I’m pretty convinced that finding Cabbage and csound as a whole made my life better and a more complete person in general. It’s amazing how I can make all the things now in FMOD without going into the depths of c++.
The problem is, that I’m developping for the Quest which needs the plugins of course as shared objects instead of dll.
I’ve seen another topic where you discuss implementing csound unity in android, but this isn’t helping me I believe.
Are you having any plans to be able to compile to .so files for the FMOD plugins and effects?
I have no idea how complicated that is to implement.

Thanks a lot!

Hi @JFuellem, welcome to the forum. I’m afraid I have no time to invest into this, although it would be pretty useful. I’m pretty sure it’s doable, and I assume one could use most of the existing code. Not only am I short on time, I’m also lacking a decent Android developer environment.

Have you tried building the sample Android plugins that ship with the FMOD API? If you were able to get them building and working on your Quest then we would at least have a good starting point. I’d be happy to work on it together. I just can’t give 100% to it at the moment.

Hi @rorywalsh, thanks for your reply. I’d love to dig deeper and find a solution as I could learn quite a lot along the way.
I tried building the sample plugins with Android Studio, but where I haven’t succeeded yet to make it properly work. I’ll update when I managed to do this step. Or maybe there’s another way apart from android studio. I haven’t found out yet.

I think you need to build them using cmake. But you will need Android Studio and the android ndk installed in order to build it. If you can get the samepl plugin building and working ok we might just be able to swap out the source. As with everything on Android, it will probably be quite a lot of work, but once it’s done it’s done.

After a few days of trying a bit from time to time I now could successfully build for Android and have it run on the Quest.
It’s indeed a bit of an efford. There is an extension from NVIDIA called Nvidia Tegra for Visual Studio. With that it’s really simple. (After having found that you either have to statically link or exclude the c++_shared library which threw me some errors).
Are you creating a .cpp file and then compile to the .dll through some functionality of juce or another external builder?
For now, it would be super helpful to just get those c++ files, so I could build the android versions for those plugins which I’m using for my current project. But of course it would be also great to have this natively in cabbage built in and I’d be happy to help out with what I have or can.

This is the .cpp file for the synth type plugin. And this is for the FX plugin type. If you can add those to the sample package that might do. But you’ll have to provide paths to the Csound headers, which comes with a Csound install. And you will need to link to the Csound Android .so, this part is likely to be much tricker. You can get the Csound android libs here. It might take some work to get everything going, but the source files list above should compile Ok once you have all the linker stuff set up. Keep us posted of your progress!

Thanks for presenting everything like that! Unfortunately I’m even struggling with the headers, so this might take a while…
There is no csound header required though or it did it automatically. But there’s corefoundation, which is part of the apple source code? I downloaded that and linked it but that throws thousands of other errors, welp.
If you have a tip concerning this, I would greatly appreaciate a hint, if you have time.

Are you on Windows or MacOS? You said you were using Visual Studio so I assumed you were on Windows. On Mac, the Csound headers are inside the CsoundLib64.framework. This is the path:

/Library/Frameworks/CsoundLib64.framework/Headers

You’ll definitely need the Csound headers.

I’m not sure why this is needed for an Android library? Where did you see that you needed this?

Sorry for the confusion. I’m on windows that’s right.
Your script has it as include, so I thought it might be needed, but most likely not.
The csound headers I found, even though I redownloaded the sources from the website and took those.

All I would do at this point is take the sample project and replace the .cpp code with the CsoundFMOD source. Then add the path to the Csound headers and hit build. Nothing more than that for now. You will get error, but they should only be linker errors. You can copy and paste the compiler output if you want.

As soon as I add the csound headers, it complains about a few other headers and there is also an iteration function which cannot be accessed.

Can you copy and paste the header section of the Android example .cpp file? Including the standard Win32 headers is probably going to cause error…

Sorry if I’m a bit slow, but which example do you mean?
The other plugin I successfully built also has this in the header and it made no problems…

#ifdef WIN32
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <math.h>
#include <stdio.h>
#include <string.h>

#include "fmod.hpp"

I’ll look into this a bit further.

The iterator-error happens here:

That will need work any way because as far as I know, we won’t be able to dynamically load files in this way on Android. For now you can comment out that entire function body except for the return s

Right! So there are just those 5 headers left. But ignoring them and building gives now indeed those linker errors:

1>CsoundFMOD.cpp
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(165,1): warning : control may reach end of non-void function [-Wreturn-type]
1>}
1>^
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(238,1): warning : control reaches end of non-void function [-Wreturn-type]
1>}
1>^
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(453,12): warning : ISO C++11 does not allow conversion from string literal to 'char *' [-Wwritable-strings]
1>        args[0] = "csound";
1>                  ^
1>3 warnings generated.
1>Tegra-Android/Debug/CsoundFMOD.o: In function `FMOD_Csound_dspprocess(FMOD_DSP_STATE*, unsigned int, FMOD_DSP_BUFFER_ARRAY const*, FMOD_DSP_BUFFER_ARRAY*, int, FMOD_DSP_PROCESS_OPERATION)':
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(550):  undefined reference to `csoundGetMessageCnt'
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(553):  undefined reference to `csoundGetFirstMessage'
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(554):  undefined reference to `csoundPopFirstMessage'
1>Tegra-Android/Debug/CsoundFMOD.o: In function `FMOD_Csound_dspsetparamfloat(FMOD_DSP_STATE*, int, float)':
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(569):  undefined reference to `csoundSetControlChannel'
1>Tegra-Android/Debug/CsoundFMOD.o: In function `FMOD_Csound_dspsetparamint(FMOD_DSP_STATE*, int, int)':
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(586):  undefined reference to `csoundSetControlChannel'
1>Tegra-Android/Debug/CsoundFMOD.o: In function `FMODCsound::CompileCsound(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> >)':
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(446):  undefined reference to `csoundInitialize'
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(448):  undefined reference to `csoundCreate'
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(449):  undefined reference to `csoundCreateMessageBuffer'
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(459):  undefined reference to `csoundCompile'
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(463):  undefined reference to `csoundGetKsmps'
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(464):  undefined reference to `csoundPerformKsmps'
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(465):  undefined reference to `csoundGet0dBFS'
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(466):  undefined reference to `csoundGetSpin'
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(467):  undefined reference to `csoundGetSpout'
1>Tegra-Android/Debug/CsoundFMOD.o: In function `FMODCsound::generate(float*, float*, unsigned int, int)':
1>C:\Users\User\source\repos\CsoundFMOD\CsoundFMOD\CsoundFMOD.cpp(489):  undefined reference to `csoundPerformKsmps'
1>clang++.exe : error : linker command failed with exit code 1 (use -v to see invocation)

Ok, now you need to link to the Csound Android .so files. You also need to link to the libsndfile library. I think in the end you will probably have to embed your Csound source code into the plugin binary data. This will be the simplest approach for now. But let’s see if you can get rid of those linker errors first.

I’ll update as soon as I have something, thank you!

1 Like

Success, it builds :grinning:
To further debug we probably have to switch to Unity, but this is probably getting a bit mor trickier… I still haven’t really understood, how the csd and plugin are interacting.

Great. Now you need to replace the call to csoundCompile with csoundCompileCsdText(). The CompileCsound() method can be updated. Something like this should work. It should compile that file and start playing a single sine tone when started. (untested code!)

int FMODCsound::CompileCsound(std::string csdFile)
{
    csoundInitialize(CSOUNDINIT_NO_ATEXIT);

    csound = csoundCreate(NULL);
    csoundCreateMessageBuffer(csound, 0);

    string csdText = "<CsoundSynthesizer>\n"
    "<CsOptions>\n"
    "csound -+rtaudio=jack -odac -B4096\n"
    "</CsOptions>\n"
    "<CsInstruments>\n"
    "sr = 44100\n"
    "ksmps = 64\n    "
    "nchnls = 2\n"
    "0dbfs = 1\n"
    "instr 1\n"
    "a1 oscili .3, 300, 1\n"
    "outs a1, a1\n"
    "endin\n"
    "</CsInstruments>\n"
    "<CsScore>\n"
    "f1 0 1024 10 1\n"
    "i1 0 1000\n"
    "</CsScore>\n"
    "</CsoundSynthesizer>\n";

    csoundReturnCode = csound->CompileCsdText(csdText.c_str());

    csound->Start();

    if (csoundReturnCode == 0)
    {
        ksmps = csoundGetKsmps(csound);
        csoundPerformKsmps(csound);
        cs_scale = csoundGet0dBFS(csound);
        csoundInput = csoundGetSpin(csound);
        csoundOutput = csoundGetSpout(csound);
    }
    else
    {
        // fmod doesn't allow logging but if it does in the future, this should print information to the user
        // about possible problems in their instruments
    }

    return csoundReturnCode;

}

Ah right, at the moment I have the FMOD_fx.cpp compiled as I’m using that for my project, but I’ll replace this for now with the other script.