Using libpd with Android Studio

Looking for an audio synthesis library

I was starting a new Android App project using some fancy sonification. Searching for an audio synthesis library was not too easy. The usual suspects like the Beads Project or jSyn do not support Android natively. There are some first steps, but Android does not support JavaSound, because instead it implements its own AndroidSound interface. After a long time of searching I could track down PureData, more precisely the wrapper project libpd (pd-for-android). It is a profound library redeploying every feature from PureData (Vanilla not Extended!) without writing any line of audio synthesis code in Java. It is also possible to build externals from PD-Extended. So you can abstract the audio synthesis to PureData, designing your sonification there and then import it into your Android project.

From Eclipse to Android Studio using libpd

I started using Eclipse because Android Studio was not final at that time. Setting up Eclipse with libpd was not challenging using the tutorials from the internet and from the book Making Musical Apps by Peter Brinkmann.
However, before you could turn round, there was the news that Android Studio was released in Version 1.0 and Google would drop the ADT and SDK Plugin support for Eclipse. Because I could not find any instructions to get libpd working with Android Studio, I figured it out myself and would like to share the lesson I have learned.

Update: New Solution without the NDK

Here you can find a updated solution without using the NDK: Update: Using libpd with Android Studio without the NDK

Update: Sample Project

I created a sample project for sharing. You can find all relevant information about it here: Sample Project for using libpd with Android Studio

Get prepared

  1. Get the latest Android Studio
  2. Get the latest SDK (if not installed with Android Studio)
  3. Get the latest NDK
  4. Get the latest pd-for-android from GitHub

Get it running

First of all create a new Android Studio project. For simplicity I recommend that you orientate yourself towards the GuitarTuner project from the book that I mentioned earlier (GitHub project).

Import pd-for-android

The problem is: Android Studio does not know about pd-for-android and you will get some error messages regarding the PD classes. To fix this you need to import the PDCore and AndroidMidi folder as Module into your Android Studio Project [1]. You can find the AndroidMidi folder inside midi/. 
You also need to add the module :AndroidMidi as dependeny for :PDCore  and :PDCore as dependency to your app (core) module.
After you imported the new modules and added the dependencies, Gradle will build the project. In my case I got the build-error:

Error:The SDK Build Tools revision (17.0.0) is too low for project ':PdCore'. Minimum required is 19.1.0

I fixed this error by changing the build.gradle of the :PDCore and :AndroidMidi modules. They used 17 as buildToolsVersion and I updated them to the newest version 21.1.2 and that solved my problem.

NDK Build pd-for-android

Now Android Studio should find the PD libraries and you can import them into your code. If you try to deploy your app now, Gradle will build the project correctly, all libraries will be included but the execution will be interrupted by throwing a new error message:

java.lang.UnsatisfiedLinkError: Couldn't load pd from loader dalvik.system.PathClassLoader ... : findLibrary returned null
at java.lang.Runtime.loadLibrary(Runtime.java:358)

Now things are getting tricky. We need to tell Gradle to include the *.so files as dependency into the project. To get these files we need to compile the PdCore project with the NDK .

  1. Make sure that there is a jni/ folder inside your PDCore module folder. There have to be two files named Android.mk and Application.mk, as well. If these files are missing try to get a fresh copy of pd-for-android.
  2. To prevent an error we need to replace some files inside the jniopensl_stream folder. Get the files from this GitHub location and put them into the corresponding folder.
  3. Open your console and navigate to the PDCore folder using cd <projectpath>.
  4. Execute the ndk-build command <ndk>/ndk-build  where <ndk-path> is the path to your NDK folder.
  5. Things should go on by themselves now.
  6. After the build ist ready you can find the *.so files inside the libs/ folder.

Add dependencies

Finally we need to add the files to our gradle.build file. To include native libraries we create a jar archive file with a special structure containing ".so" files and then we include them into the dependencies list.

dependencies {
compile project(':AndroidMidi')
compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')
}

task nativeLibsToJar(type: Zip, description: 'create a jar archive of the native libs') {
destinationDir file("$buildDir/native-libs")
baseName 'native-libs'
extension 'jar'
from fileTree(dir: 'libs', include: '**/*.so')
into 'lib/'
}

tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn(nativeLibsToJar)
}

Test and Run

The app should be running now and you should be able to generate some dynamic sound on your phone.