Java Sound & Music Software for Linux, Part 1
I've wanted to write this article for quite a while. Over the years I've noted that Java-based music and sound applications have increased in number and quality, yet no comprehensive list or summaries have covered these advances. And so at long last I present this survey of music and sound applications that require Java. The presentation follows no particular order, but in this first part I'll begin by questioning the use of Java in sound and music applications development, followed by a brief look at Java's internal audio and MIDI capabilities.
Why Java ?
Out of the many programming languages available to sound and music software developers, why choose Java ? Here is a short list of reasons that occur to me :
Java is a cross-platform solution - The "write once, run anywhere" mantra originated with Java, and as long as a JVM (Java virtual machine) exists for the platform the language lives up to the creed. I've run jar files on Linux that were intended for Windows, sometimes with perfect results. Mileage will vary with the number and type of platform-specific components required (e.g. a Windows-only MIDI driver for Java).
Java has an internal audio/MIDI API - The Java Sound API provides a built-in mechanism for handling audio and MIDI events, files, and streams. The applications programmer can write to the API instead of the machine-specific hardware and/or its audio subsystem.
Java has its own GUI components - While the default look & feel isn't exactly awe-inspiring the Java GUI toolkit can be coaxed into looking very fine indeed (see Figure 1).
Java is an object-oriented language - If I learned anything while studying the Lisp-based Common Music I learned that object-oriented languages are Da Bomb when it comes to music composition software. Part 2 of this article shows off the variety of Java music and sound applications, and that list includes some very powerful software for creating and transforming musical events and patterns.
Java is widely deployed - Java is available for the major computing platforms, it has a long and strong track record of use in many computing scenarios, and it has the force of a major business (Sun Microsystems) behind it.
Java is now FOSS - At long last Sun saw the light and GPL'd Java. Hallelujah !
The language does have its shortcomings, and I address some of those deficiencies in this article. However, as I researched this material I discovered that Java has quietly "caught on" with a great number of programmers in the sound and music domains. The quality of their work speaks for itself, but it also speaks for Java's utility and appeal. We'll begin our examination of this appeal by taking a brief look at the Java Sound API.
Java Sound has been a standard component in Sun's Java from version 1.3 onwards. The API supports common audio operations such as playback, recording, and mixing, and its MIDI capabilities include support for MIDI event sequencing and MIDI synthesis. Java Sound targets the normal user's typical desktop sound requirements, such as media playback and relatively lightweight production capabilities. Synchronization methods such as SMPTE or MTC are not supported, nor is JACK, but these factors are limiting only if the target application requires them.
Java supports the OSS /dev/dsp device as its default audio device. Java also supports the ALSA sound system, but that support comes with a caution. I was mystified when an application appeared to be working perfectly, yet no sound came out of my speakers. With help from members of the Linux Audio Developers list I discovered that Java didn't like my primary ALSA audio device, an M-Audio Delta 66, so it rolled over to the next available card, an SBLive. However, I don't use that card for audio, I only need its hardware MIDI ports, so I was stumped and soundless until I realized my mistake and hooked some speakers to the Live's audio output.
Apparently Java finds no suitable mixer device for the Delta 66 (a pro-audio card), so it selects the next device until it finds one that does have such a mixer. Clearly this behavior is intended, but in this regard Java needs to deepen its support for all devices supported by ALSA. Better yet, Java should provided complete support for JACK. Alas, it seems that direct support for JACK is not coming soon, according to this comment from the Miscellaneous FAQ page on the Java Sound Resources site :
3.4. Why is there no artsd/esd support in Java Sound?
In Florian's and my opinion, mixing daemons like artsd, esd, JACK, rplay, NAS, yiff, ... are hacks that work around a shortcoming of the device drivers. We feel that mixing should be done either by the soundcard hardware or in software by the device driver. For Windows (DirectSound) and Solaris, this is self-evident, while Linux is lagging behind. The OSS driver model is obsolete technology anyway, and ALSA can do mixing in software with the dmix plug-in. With this state of affairs, all these discussions about mixing daemons could be settled once for all. Never again would a sound program have to reinvent the wheel with output plugins for /dev/dsp, ALSA, esd, arts, [you name it]. This would be a very efficient solution in terms of using (vs. wasting) programmer time. It would even enable the coexistence of several mixing daemons for backward compatibility. So why not do the obvious, elegant, technically clean, (human) resource saving?
Similar remarks regarding ASIO lead me to believe that Java sound development should consider the requirements of professional-grade audio production. These days, those requirements certainly include ASIO for Windows and JACK for Linux and OSX. Without this support Java sound applications may be useful in many regards, but their value will be much reduced in settings that require low-latency and free connectivity.
Despite that lapse re: JACK and ASIO the Java Sound Resources site is still the definitive resource for Java Sound as implemented through Java 1.5. Check it out for code examples, applets and applications, and a very comprehensive set of FAQ pages.
The Java Sound API also provides an interface to an internal MIDI-controlled synthesizer. This synth renders a set of General MIDI instruments contained in a soundbank found at $JAVA_HOME/jre/lib/audio. Many Java audio applications use the internal synthesizer, but the default bank has a rather mediocre sound quality. I suggest replacing it with the deluxe set available from the Java Sound API: Soundbanks page, the quality is much better. To further improve this support Sun has developed a new internal synthesis engine, known as the Gervill synthesizer (Figure 2), and it recently reached its 1.0 release stage. Gervill's features include support for DSL and SoundFont2 sound sources, the General MIDI patch map, and the MIDI tuning standard. I tested the synth in its standalone version, it worked well, and I think it will be an improvement for the system. (Aside to the developers: It would be even better with JACK support.)
The Tritonus project is a clean-room implementation of the Java Sound API, originally written to provide an open-source audio programming interface for Java. Tritonus enhances and extends the original API with a plugin system that adds amenities such as a CD audio ripper, an OGG decoder, support for GNOME's esd sound daemon, and support for ALSA's mixer and sequencer. Project development has been slow for a long time, and Sun's decision to open-source Java has effectively negated the need for Tritonus. However, the Tritonus plugins are still useful and should work with the Java Sound API through Java 1.5.
Jens Gulden's JJack unites the Java sound system with the JACK audio server. The package provides four methods for this unification, including a native Java Sound driver for JACK, a shell environment for JJack clients, a provision for designing Java Beans with JJack, and the use of the JJack library when compiling standalone applications.
I compiled and tested JJack on both machines here at Studio Dave, using only the first method. I installed jjack.jar and jjack-clients.jar in $JAVA_HOME/jre/lib/ext and copied libjjack.so to /usr/lib. According to the package instructions JJack would be recognized and started automatically. Both systems indicated that it started all right, but alas, JJack instantly zombifies on my JAD 1.0 system (Java 1.5). I'm pursuing some possible resolutions on that machine. JJack appeared to be much happier on my 64 Studio box, but only after I switched JACK's configuration from my Delta 66 (hw:0) to the machine's second card, a SoundBlaster PCI128 (hw:1). Alas, QJackCtl reported a steady stream of xruns until I remembered that the PCI128 performed much better in simplex mode. I switched modes, the xruns diminished significantly, and they were reduced even further when I raised the JACK buffer from 512 to 1024 samples.
I thought I had resolved all problems with JJack, but when I tried recording from the JJack port into ecasound I created only empty files. Using strace I looked further into the problem and discovered that Java was still not accessing the ALSA devices and was rolling back to use /dev/dsp. Thus, although JJack was running as advertised it was still not receiving the audio stream from Java's internal sound handlers. I've contacted the author and I plan to work with him to fix these issues, but again I say that it would be in Sun's greater interest to support JACK directly. As the second part of this article will show, Java sound and music programs are flourishing, and giving them the gift of JACK connectivity would enrich the entire Java community of audio/MIDI applications developers and users.