My attempt to build SuperCollider on Termux/Android

Note – I (Brian Heim) am posting this on behalf of Tim Weber (@scy, https://gist.github.com/scy). Apparently new users aren’t able to post more than 2 links in a single post. Everything below the dotted line is his.


This is supposed to be posted on the SC forums at scsynth.org, but I ran into the spam filter and want to go to bed right now. Saving it as a Gist in the meantime.

I’ve been thinking about using SuperCollider on my phone. There’s glastonbridge/SuperCollider-Android which hasn’t been touched since 2014, so I thought I’ll try to build a current version from source, based on the guide for Linux. Also, since Termux provides a great Linux CLI environment, including build toolchains, directly on the device, I wanted to try building SC under Termux.

Spoiler alert: I didn’t manage to do it. The main problem is not having an audio driver, since the Linux build requires libjack, and neither Android nor Termux provide it. (Termux has the libpulseaudio package, but that won’t help us here.) After asking around in Slack I was asked to note down what I did and how far I got here in the forums, maybe somebody else wants to pick up. I probably won’t find the time in the next couple of weeks, and even after that it’s unlikely.

I should point out that there is nine years old code that introduced an Android driver to SuperCollider, but according to Brian Heim “it doesn’t work and hasn’t worked for years” and “we don’t make any effort to support it”. Also, as far as I understand the code, it’s meant for running SuperCollider inside a normal Java-based Android app.

Nevertheless, if you install Termux and get the necessary build tools …

pkg install build-essential cmake fftw git libsndfile

… clone the project and create a build dir …

git clone --recurse-submodules https://github.com/SuperCollider/SuperCollider.git \
&& mkdir SuperCollider/build \
&& cd SuperCollider/build

… and then try to build with …

cmake -DCMAKE_INSTALL_PREFIX=~/sc -DAUDIOAPI=coreaudio -DSC_QT=OFF -DSC_HIDAPI=OFF -DNO_X11=ON -DSC_ABLETON_LINK=OFF ..
make -j3

… you can actually get quite far. (I’ve also added add_definitions(-DSC_ANDROID) to CMakeLists.txt, but I’m not sure anymore whether that was required.)

Of course, -DAUDIOAPI=coreaudio (the macOS/iOS audio API) is wrong, but if you don’t provide -DAUDIOAPI, it will default to Jack and instantly fail because it can’t find it. By using coreaudio, your build should at least get up to the point where the linker fails, telling you that -f may not be used without -shared. I believe that’s because when building for coreaudio, SC uses a -framework flag in its linker call that’s probably supported on Apple devices, but the Termux linker interprets it as -f with a bunch of additional stuff and gets confused.

Maybe making it work would be as simple as allowing a new AUDIOAPI value like android that would then set the -DSC_ANDROID C macro, which in turn uses the old Android driver, but I doubt it.

Instead, my approach would be to look at termux/play-audio’s code as an example of modern, high performance OpenSL ES Android audio output under Termux and then write a new SuperCollider driver based on it. That’s possibly all there’s missing.

If somebody wants to continue based on what I’ve found out: go for it! :slight_smile: Let us know how it worked out. Termux would surely be happy about a supercollider package, and me too. :wink:

5 Likes

Thanks very much, Brian!

@scy
I’m giving this a shot with -DAUDIOAPI=portaudio

SPOILER: with some adjustments, it compiles. But then:

$ sclang 
Segmentation fault
$ scsynth -u 57110
Segmentation fault

Here is what I’ve done:

  1. patch /usr/include/strings.h on android: comment out the (deprecated) definition of bcopy, because it conflicts with something in sclang
  2. clone sc repo and install build-essentials
  3. mkdir build; cd build;
  4. some adjustments to CMakeFiles to link libandroid-glob (otherwise linker errors with missing DSO) and add -fPIC (because otherwise you get CANNOT LINK EXECUTABLE "sclang": "/data/data/com.termux/files/usr/lib/libscsynth.so.1.0.0" has text relocations) .
    I uploaded my patch here

Then:
cmake -DCMAKE_BUILD_TYPE=Release -DNATIVE=ON -DCMAKE_INSTALL_PREFIX="${PREFIX}" -DAUDIOAPI=portaudio -DSC_HIDAPI=OFF -DSC_QT=OFF -DNO_X11=ON -DSC_ABLETON_LINK=OFF ..

Finally:
make -j5 install

And then on to immediate segmentation faults upon running… I’m installing gdb and rebuilding with debug symbols then…

2 Likes

See SuperCollider Add PulseAudio backend to SuperCollider RFC and Add PulseAudio backend for SuperCollider on Linux.

It compiled for me today, with -DAUDIOAPI=portaudio and following the other steps by @elgiano, plus disabling Supernova with -DSUPERNOVA=OFF and not enabling native, which I don’t know what it is.

sclang runs, gives the prompt and responds correctly to "hello world".postln. However scsynth fails with “No such file or directory” from World_New. Stepping through with GDB it is maybe related to creating a temporary file in /tmp for interprocess communication, but I might be mistaken as I am out of my waters.

hey @mace
great to hear you tried it out too, and amazing it runs! Got my attention on this again, so… have you tried chrooting?
From https://wiki.termux.com/wiki/Differences_from_Linux

If you still need a classical Linux file system layout for some reason, you may try to use termux-chroot from package ‘proot’:

$ pkg install proot
$ termux-chroot
$ ls /usr
bin  doc  etc  include	lib  libexec  share  tmp  var

Utility termux-chroot may be very helpful if you use a custom software that require standard paths like /tmp, /etc, /usr to be available.

I would try it myself, but I get segfaults with NATIVE=ON, and linker errors (about atomic_fetch among others) without it… I’m now rebuilding with -latomic and NATIVE=OFF… let’s see!

1 Like

Uuh, thank you @elgiano! Within chroot scsynth boots the server, then dies like so, in a new and interesting way

$ sc/bin/scsynth -u 57110
Device options:
  - PulseAudio : Dummy Output   (device #0 with 0 ins 2 outs)
  - PulseAudio : Monitor of Dummy Output   (device #1 with 2 ins 0 outs)

Requested devices:
  In:
    - (default)
  Out:
    - (default)

Selecting default system input/output devices

Booting with:
  In: PulseAudio : Monitor of Dummy Output
  Out: PulseAudio : Dummy Output
  Sample rate: 44100.000
  Latency (in/out): 0.000 / 0.001 sec
  SC_AudioDriver: sample rate = 44100.000000, driver's block size = 64
SuperCollider 3 server ready (debug build).
Segmentation fault
$

Above it has no access to an audio device from within chroot, but making Pulseaudio listen to TCP connections and directing audio clients with environment variable PULSE_SERVER works; I can hear audio using SoX’s play from within chroot.

Now, again trying to investigate what scsynth segfaults on with GDB isn’t very meaningful (to me, like said I’m out of my waters):

$ PULSE_SERVER=127.0.0.1 gdb --args sc/bin/scsynth -u 57110
[...standard GDB output omitted]
Reading symbols from sc/bin/scsynth...
(gdb) run
Starting program: /home/sc/bin/scsynth -u 57110
[New LWP 27200]
[New LWP 27218]
[New LWP 27219]

Device options:
  - PulseAudio : OpenSL ES Output   (device #0 with 0 ins 2 outs)
  - PulseAudio : Monitor of OpenSL ES Output   (device #1 with 2 ins 0 outs)

Requested devices:
  In:
  - (default)
  Out:
  - (default)

Selecting default system input/output devices

Booting with:
  In: PulseAudio : Monitor of OpenSL ES Output
  Out: PulseAudio : OpenSL ES Output
  Sample rate: 44100.000
  Latency (in/out): 0.000 / 0.001 sec
SC_AudioDriver: sample rate = 44100.000000, driver's block size = 64
[New LWP 27220]
SuperCollider 3 server ready (debug build).

Thread 3 "threaded-ml" received signal SIGSEGV, Segmentation fault.
[Switching to LWP 27218]
0x0000007fb6d94dc4 in ?? () from /usr/lib/libportaudio.so
(gdb) where
#0  0x0000007fb6d94dc4 in ?? () from /usr/lib/libportaudio.so
#1  0x00000000ac6320b8 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb)

Definitely progress :muscle: but not there yet. I do not feel confident I can do a lot if the issues are down at the portaudio layer, but I want to try! My dream is pairing up my Teenage Engineering OP-Z with SuperCollider running on Android for livecoding SynthDefs and controlling them over MIDI for fun on the go :slight_smile: Additional dream is also to be useful for other people to get SuperCollider on their Androids.

1 Like