With all the prerequisites for OpenSL support in place, the last step was to make the new functionality accessible in a way that’s transparent to existing Android projects. After giving the matter much thought, I settled on the following solution: Extend the existing Java API with native methods for controlling OpenSL; provide two different native binaries, one implementing the new methods for Android 2.3 or later, and one leaving them as no-ops for Android 2.2 or earlier.
The new methods are quite simple. First, there is a method that indicates whether the new methods provide meaningful functionality:
boolean implementsAudio() If this method returns false, Pd for Android falls back on the old Java components for audio. Second, there is a pair of methods for creating and destroying the audio components:
int openAudio(int inputChannels, int outputChannels, int sampleRate) and
void closeAudio(). The
openAudio method was actually there before, but the original version only set the audio parameters of Pd; the new version creates the corresponding OpenSL objects as well. Third, there are the usual transport methods:
int pauseAudio(), and
None of these new methods will actually concern developers who build apps on top of Pd for Android; just like the audio processing methods that existed before, they will only be called by the
PdAudio class that hides all technicalities of the audio setup.
PdAudio now supports both the old and the new audio components, but its public API remains unchanged. It also automatically polls the message queue, so that the new take on receiving messages from Pd will also be transparent to developers.
When I started contemplating OpenSL support for libpd, I didn’t even see how this could possibly work without without breaking existing projects. With the joy of hindsight, however, all the changes seem perfectly straightforward, maybe even obvious. This gives me a good feeling, about the new additions as well as the original design.
The one (very minor) drawback is that this change requires a slight change to the way non-Android applications use the Java bindings because developers will have to remember to poll the message queue if they want to receive messages from Pd, but I believe that the improved performance of the audio processing methods will more than make up for this inconvenience.
Moreover, although it wasn’t the goal, it turns out that this revision opens up a number of exciting new possibilities for non-Android uses of the Java components. To wit, there’s no reason why this technique, swapping out audio binaries underneath the same Java API, should be limited to Android. There’s no reason why we can’t have binaries that implement audio with JACK or PulseAudio for Linux, CoreAudio for Macs, or ASIO for Windows. Alternatively, one might just implement it once, using PortAudio, and compile it for all major platforms. (I already have a PortAudio prototype that seems to work nicely.) The Processing branch might also benefit from this.