# Tritonus FAQ

## General

### configure fails. What should I do?

After configure run, there is a file 'config.log in the directory where you run configure. It contains detailed information on failed tests If you want to ask on a mailing list, include the content of this file. (Matthias)

#### I can't get the ALSA mixer.

There are three possibilities:

- Use a jdk1.3.

- Use an older jdk (e.g. jdk1.2.2) and install JMF 2.0 performance pack.

- Use an older jdk and install an alternative Java Sound implementation (e.g. jdk1.2.2 and Tritonus).

(Matthias)

##### I am new to Java Sound and want to program a telephony application. Is this possible, and if yes, how do I do that?

It is possible. We cannot provide all concepts of digital audio in this FAQ. There are many good books on this subject. I recommend "the computer music tutorial" from Curtis Roads, from MIT press. For simple examples how to do streaming audio with Java Sound, see Matthias' Java Sound Examples. (Florian)

###### How is the JMF related to Java Sound?

JMF is a high-level API, designed mainly for easy playback of multimedia files, video as well as audio. Java Sound, on the other hand, is a rather low-level API, designed for detailed control of the audio hardware. (Matthias)

###### I want a specific feature in future versions of the Java Sound API

You can make specification requests to Sun. To read how to do that, go to http://java.sun.com/aboutJava/communityprocess/submit.html. You may want to discuss the feature before hand on the mailing list. (Florian)

###### The Java Sound API seems fine to me, but many things do not seem to be implemented.

This is a matter of time. Sun will improve the Java Sound implementation (and also the API). Other people will provide service providers to extend Java Sound. The Tritonus team will release parts of Tritonus as service providers so that everybody can take advantage of Tritonus' achievements. A native port of Tritonus to Windows is planned, too. (Florian)

###### I discovered a bug in a Java Sound implementation

For the Sun implementation, you can submit it as a bug on http://java.sun.com/cgi-bin/bugreport.cgi (needs a registration to the developer connection). For Tritonus, use their bug reporting system on http://sourceforge.net/bugs/?group_id=1390. (Florian)

###### Audio Programming

###### I want to convert a byte[] array to short samples or vice versa.

Look at the Tritonus source code, class org.tritonus.sampled.TConversionTool. You have to look it up in the cvs repository in the subdirectory src/org/tritonus/sampled. For that, go to http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/tritonus/src/org/tritonus/sampled/?cvsroot=tritonus and click on the version number of "TConversionTool.java". It contains many methods for converting byte arrays. (Florian)

###### Playback of audio data with Java Sound is significantly quieter than with a compared player on the native OS.

There was the issue that Sun's implementation of Java Sound (at least up to version 0.99) lowers the level of output in order to avoid clippings when several lines are mixed. Probably this "feature" is the problem.

I find this "feature" quite doubtful. A Java Sound programmer should use GainControls attached to single lines to lower the volume, if wanted. Many applications won't profit of this "feature": e.g. they only play one line at a time. Or the mixed sounds don't create clippings. This is not unusual, as even "normalized" sounds leave most of the time enough room - there must coincide peaks to create a clipping. The case that the soft synth AND audio are playing simultaneously can be expected in "quality" programs which provide a way to lower the gain of the lines - or do the gain decrease automatically.

As Java Sound is supposed to be a low-level engine, such an approach would not be suitable. The problem of the feature is a general decrease of signal-to-noise ratio of all Java Sound programs. Automatic lowering of volume prevents the use in "serious" or professional environments... (Florian)

###### I cannot retrieve any Port instances

It seems that no implementation of Java Sound provides Port instances, yet. (Florian)

###### I want to save audio data to a file, like wav or aiff

Have look at Matthias' Java Sound Examples. (todo: link - maybe put them, too, on tritonus.org)

###### I want to be notified when data is available for write/read in a SourceDataLine/TargetDataLine

You have to use SourceDataLine/TargetDataLine.available(). The usual implementation for streaming audio (in Java Sound) is a dedicated thread for that - look at the Java Sound demo which you can download from sun or at Matthias' JS examples. (Florian)

###### I want to do some processing on an alaw stream (like amplifing it)

It is much easier to change gain with linear encoding (PCM). I would strongly suggest that - especially when you have the data in linear format at first. You'd have to convert it back to alaw after processing. (Florian)

###### I want to implement a real-time AudioInputStream, but cannot give a length for it, as it is not known in advance

You should use "AudioSystem.NOT_SPECIFIED" as length. This approach seems logical to me and it works fine in my program. (Florian)

###### I want to add special chunks to wave or aiff files (like for a descriptive text or copyright)

The Java Sound API does not support this currently. Future versions are likely to, because this is indeed quite important. For the moment, you will need to implement your own class for writing wave or aiff files. Or make meaningful filenames... (Florian)

###### It fails to open any line with 16KHz sample rate

Apparently, most Java Sound implementations do not provide that, even if the sound card supports it. Future implementations will support that. (Florian)

###### I have a byte array and want to write these data to an audio file.

Create a ByteArrayInputStream object from the byte array, create an AudioInputStream from it, then call AudioSystem.write(...). [TODO: code example, alternative approach via AudioOutputStream] (Matthias)

###### I want to get a SourceDataLine or TargetDataLine in µ-law format

TargetDataLines are supposed to act as a "direct" way to communicate with the audio hardware device, i.e. your soundcard. When your soundcard does not support ulaw directly, the TargetDataLine won't either.

The way to go is to open a TargetDataLine in pcm format and route it through a format converter. See doc of AudioSystem to get converted Streams. The converted stream you get provides ulaw samples then.

There is no drawback in this approach: all PC soundcards that I know of deliver only PCM, so it has to be rendered to ulaw anyway in software. Whether in the soundcard's driver, the operating system layer or in the application (your java program) doesn't matter. You get maximum portability when only using pcm for TargetDataLines. (Florian)

###### Simultaneous recording and playback only works when first opening the playback line (SourceDataLine)

This depends on the soundcard and its driver to the native operating system. E.g. Soundblaster 16 or 64 do not provide real full duplex, only a kind of pseudo full duplex. I experienced under Windows that you can only use this pseudo full duplex when you have a certain order in opening record/playback lines. (Florian)

###### I want to detect the level of sound while I am recording it

First of all, you should have the data in PCM format (preferable in signed PCM). Then you can look at the samples to detect the amplitude (level). Some statistics are suitable, too, like taking the average of the absolute values or RMS. (Florian)

###### I want to use multi-channel sound.

This is currently not possible. It will be supported in Tritonus in the future. (Matthias)

###### I'm trying to do sample rate conversion with Java Sound, but it doesn't work.

Currently, no Java Sound implementation supports this. Tritonus will do so in the near future, and this will be made available as a plug-in for other Java Sound implementations. Also, JMF supports sample rate conversion. (Matthias)

###### I want to do equalizing/noise reduction/fft/... with Java Sound.

Java Sound is an API concerned with basic sound input and output. It does not contain digital signal processing algorithms. Nevertheless, you can do this with Java; you just have to code it on your own. The book "Digital Audio with Java" by Craig Lindley contains some DSP algorithm. Also, it is often easy to transform C or C++ code found on the net to Java.

For code that does fft, have a look at the Peruna Project. (Matthias)

###### I do recording with a TargetDataLine and I want a volume control for it.

The obvious solution would be to get a Control object of type VOLUME or GAIN for the TargetDataLine and manipulate the volume via this object. However, this is not possible, since neither the Sun jdk1.3 nor Tritonus implement any controls for TargetDataLines.

What you can do is to use the system mixer to control the recording volume---it affects hardware settings in the soundcard. There is an API to manipulate the system mixer from java: the mysterious Ports. But again, this is not implemented in any known Java Sound implementation (it is planned to implement Ports in future versions of Tritonus).

The remaining possibility is to implement a volume control digitally: multiplying each single sample of the sound data with a certain value that lowers or raises the level proportionally. (Matthias)

###### I want to use an audio clip on a 5 MB audio file, but I get an out of memory exception.

For files of this size, you should stream the audio. Like that you treat buffers of small size and feed them successively into the the audio device. Look at Matthias' Java Sound examples, there are some streaming audio players to take as a start. Java Sound Examples: http://rupert.informatik.uni-stuttgart.de/~pfistere/jsexamples/. (Florian)

###### I want to calculate the number of bytes to skip from the length in seconds.

Use one of the following formulas: bytes = seconds * sample rate * channels * (bits per sample / 8) or bytes = seconds * sample rate * frame size. You can get the sample rate, number of channels, bits per sample and frame size from an AudioFormat object. (Matthias)

###### Encodings and file types

###### I want to play back mp3 files

There is a pure Java decoder of the javazoom project. Tritonus, the open source implementation of Java Sound incorporates it. There is a plug in available which runs under any JVM. (Florian)

###### I want to encode mp3 files with my Java program

Java is free, this collides with the (enforced) licences for mp3 encoders. I have studied very carefully the mp3 licencing model and also asked at Fraunhofer (inventors of mp3) for additional information: it won't be possible to deliver a free mp3 encoder legally. (If anyone knows a "hole", please let me know. (not the available source code - this is not appropriate: the encoders available as source code - most of them based on the ISO reference implementation - create bad quality mp3's and the licence doesn't allow the use of such encoders!))

The Tritonus team is working on an interface to the open source encoder LAME. Like that people who do not fear licence problems can download LAME as a separate package and link it to Java Sound. (Florian)

###### I want to convert a PCM encoded byte[] to a uLaw byte[]

When you are processing streams, read the documentation of javax.sound.sampled.AudioSystem. There are functions like getAudioInputStream(AudioFormat, AudioInputStream) that do the conversion for you.

In case you absolutely want to do the conversion "by hand", look at how Tritonus is doing it: have a look at the file TConversionTool.java. (Florian)

###### Is there support for RealAudio in Java Sound?

There isn't, and it doesn't look like there will be in the near future. RealAudio is a proprietary format; there is no specification available to the public. Due to that, it's hard to implement support for it. If you want to change this situation, bug RealNetworks to publish specs (politely, please). (Matthias)

###### Is there support for GSM in Java Sound?

Yes, you can download a service provider plug-in for GSM from Java Sound Plugins. Since this implementation is pure-java, it can be used with any Java Sound implementation on any platform. For examples of using the GSM plug-in, see the section "dealing with encodings" in the Java Sound Examples. (Matthias)

###### Java Sound supports a format called RMF. Where can I get documentation about this format?

You can't. RMF (Rich Music Format) is a proprietary format designed by beatnik (www.beatnik.com). They don't release any specs to the public. By the way, it's not true for all Java Sound implementations to support RMF. Tritonus doesn't for the above reason. Instead, it will support MPEG-4 Structured Audio.

###### I want to read in a vox file and save it as wav file

Probably it's simplest to do all by yourself: use a RandomAccessFile or similar to open the vox file, parse the headers, etc. You need to know the vox file format, you can find many documents specifying it on the Internet. To create a wave file from that, create a AudioFileFormat instance with the format read from the vox-header and supply an InputStream with the audi data of the vox file. You can then use AudioSystem.write to write a wav file. (Florian)

###### MIDI

###### MIDI input seems not to work with the Sun jdk1.3.

The Sun jdk1.3 does not implement MIDI IN. Alternatives are:

- JavaMIDI by Robert Marsanyi

- Wire by Niels Gorisse

- MidiPort by Jörg Prante. [TODO: URL]

Each of this is a simple library written for Windows.

Tritonus has an almost complete MIDI implementation. If you are running Linux, just install Tritonus. I you are using Windows95/98, there is an experimental add-on to the Sun jdk1.3 that can be installed with the Sun jdk1.3. Download it. (Matthias)

###### I have unstable timing when playing back MIDI notes

Java Sounds synthesizer is a virtual synthesizer - it uses your soundcard's audio out and creates the sounds in software. That is why there is a delay: audio data is quite huge compared to midi data (e.g. 5 bytes compared to 88200 bytes for one note). Audio data is put in blocks of a number of samples to the soundcard. When the blocks are 23ms long, you have at least 23 ms delay. Another source of delay comes from moving these data to the soundcard. Better soundcards, and especially PCI soundcards can do the memory transfer very fast. There is also more software overhead for audio data - obviously it takes more time to calculate and treat audio data than MIDI data.

I cannot give an authoritative answer to the problem, why the delay changes. It may be due to a block-wise implementation of the internal Java Sound synthesizer: as the audio data is always pushed in blocks to the soundcard, it may be that MIDI events are always synthesized from the start of a block. (I just wrote (for testing purposes) a drum machine that works like this). This results in unequal delay. I am not sure about this "theory", as playing a midi file seems to have perfect timing (i.e. midi notes may start inside a block). Let's see whether the programmers of the synthesizer engine respond. (Florian)

###### Java Sound in Applets

###### I heared that signing applets is needed to record sound. Is this true?

Almost true.

###### Performance issues

###### Is it possible to apply an FFT transform in real time under Java ?

At least for JIT compilers, Java is very fast (under certain conditions it reaches or tops C++ performance!) - and I think even on no-JIT compilers, FFT analysis is no problem in real time, of course depending on available processor power and resources. (Florian)

###### How do I reduce latency - or- I want to record sound and simultaneously play it back without delay

You'll never be able to completely remove latency. Digital audio on computers is processed in "chunks", i.e. a small number of samples. When recording, you have to wait until one chunk is filled, then it gets passed to your application. So there is a minimum delay of the time of a chunk latency for recording. For playback the same "problem": the soundcard gets chunks from the application, so when one chunk is passed, the soundcard starts playing with the first sample of the chunk and it takes the time of the chunk that the last samples has been played. So, for playback you'll get the same delay. Added to that, the software (i.e. the different hardware layers copying chunks, etc.) and the hardware (hardware latency) add to the total delay.

There are approaches like DirectSound, ASIO or Alsa that all try to minimize the software part's latency and to allow very small chunks. When used efficiently on high-quality soundcards, an audio loop is possible with a barely noticeable delay (e.g. 20ms).

Java Sound (and therefore also JMF) actually adds one layer to the software part, so latency is slightly increased compared to native audio applications. You control the chunk size with the buffer size argument when constructing a SourceDataLine or TargetDataLine in Java Sound. I don't know about JMF's concepts. I also experienced some problems with Java Sound recording when using small buffers (like 1024 samples at 44KHz). (Florian)

###### I want to provide successive multi track recording: I record new channels while playing back all previously recorded channels. However, I get synchronization problems, there are different delays

The delay, of when the data arrives regarded to when you started recording, should be quite fixed. However, recording and playback may have different delays. The delays depend on the soundcard, the operating system (including the sound card drivers) and the implementation of Java Sound you use (and also a bit on what JDK you use).

Also, the Java Sound API does not provide means for querying the device's latency. This would be quite difficult anyway for the Java Sound subsystem. However, normal soundcards have very little hardware delay (even the cheap ones), so once they receive the command to start recording, they really start it in a matter of some milliseconds - typically 20-30ms.

Using the soundcard via Java Sound, there are many layers until the data arrives in your program, so some delay is added. However, I haven't noticed a relevant delay when recording. I haven't tried to do your approach of measuring the delay, though.

So what you should is, is to call the start() method both on TargetDataLine and SourceDataLine "at once" with the minimum overhead possible. Notice that the buffers of the recording line arrive when they have been finished recording (i.e. when the amount of time has been elapsed), while playback lines need a buffer prior that they are played. This may not be obvious at first. So when you do record and playback at once, the first received block from the recording line corresponds in time to the first played buffer (which has been submitted right with "start").

For playback of the 2 files, you should not use 2 playback lines, but mix them from your program. Like that, you can at least control the exact sample-delay of the 2 playback lines and adjust it (probably only possible by ear).

These are handmade solutions. The "real" solution is to make use of Mixer.synchronize. This is the proposed solution to your problem from the Java Sound API. Like that you can synchronize the recording line and the playback line - or the 2 playback lines. However, it seems that it isn't implemented in current versions of Java Sound (although I haven't tested it). (Florian)

###### Other resources

###### I'm looking for books on Java Sound.

There are currently no books on Java Sound. There is a book covering some DSP algorithms in Java:

- 'Digital Audio with Java' by Craig A. Lindley

[TODO: JMF books] (Matthias)

###### Where can I find information on the Java Sound API?

Look at http://java.sun.com/products/java-media/sound/. (Matthias)

###### Where can I find information on JMF (the Java Media Framework)?

Look at http://java.sun.com/products/java-media/jmf. (Matthias)

###### What mail lists are relevent to Java Sound?

JAVASOUND-INTEREST@JAVA.SUN.COM To subscribe, send email to listserv@java.sun.com containing the following line in the message body (NOT in the subject line!): signon javasound-interest

###### What newsgroups are relevent to Java Sound?

There is no newsgroup devoted to Java Sound, but these might help:

- comp.lang.java

- comp.lang.java.programmer

- comp.music.midi

- comp.sys.ibm.pc.soundcard.music

- comp.sys.ibm.pc.soundcard.tech

- comp.sys.ibm.pc.soundcard.* where '*' is your favorite soundcard maker

###### Digital audio basics

###### What is endianess/big endian/little endian?

Most common computers have their memory organized in units of 8 bits, called a byte. The bytes can be adressed by ordinal numbers, starting with zero. (The harware organization of the memory is often in rows of 16, 32, 64, 128 or even more bits. But the instruction set of the processor still gives you the view of the byte-organized memory.) If you want to store a value that needs more than 8 bits, the question arises how the bits of the value are divided in bytes and stored in memory. If you have have a value with 16 bits, there is not much discussion that it has to be divided into two groups: bit 0 to 7 and bits 8 to 15. But then, the fight starts. Some CPUs store the first group (bit 0 to 7) in the byte with the lower address and the second group (bits 8 to 15) in the byte with the higher address. This schema is called little-endian. As an example, all Intel CPUs are little-endian. Other types of CPUs do it the other way round, which is called big-endian. Sparc and PowerPC (Motorola) CPUs are big-endian. (Matthias)

###### Misc

###### My Java Sound program does not exit when leaving the main() method

By default, the java virtual machine terminates when all threads have terminated and the main function has also been exited. It seems that Java Sound's audio subsystem creates threads which remain, so you have to call explicitely System.exit(int). (Florian)

###### I installed Tritonus on a Sun jdk1.3.0 and I still get the behaviour of Sun's Java Sound implementation.

Using Tritonus under jdk1.3.0 is a bit tricky. The point is that by installing Tritonus you are just adding Tritonus' mixers, converters and other service providers to the ones of Sun's Java Sound implementation. Especially, Sun's mixing engine is still the default mixer. To use Tritonus' mixers, you have to select the mixer in your program manually: get the respective Mixer object from AudioSystem, and allocate the lines from this Mixer object. The same is true for MidiDevices. It's possible to use Tritonus' javax.sound.* classes by putting them into the boot classpath *before* rt.jar. But this still leaves you with Sun's service providers. Getting rid of them required to change the service provider configuration files inside rt.jar or other, even more fancy measures. The alternative way out of the hell is to use a jdk1.2.X, where Tritonus is the only Java Sound implementation. (Matthias)

###### I tried to compile AudioPlayer (or another program from the Java Sound Examples). I get errors about gnu.getopt.Getopt not being available.

Download GNU getopt and install it. Alternatively, there are simplified versions of some examples that do not use GNU getopt (For instance, SimpleAudioPlayer instead of AudioPlayer). (Matthias)

###### I want to have a simple test if Java Sound is available

Try that:

    public static boolean JavaSoundInstalled() {
        boolean result=false;
        try
     {
            result = javax.sound.sampled.AudioSystem.getMixerInfo().length > 0;
        } catch (Throwable t) {}
    }

(Florian)

###### I want to use com.sun.* classes. Is there any documentation ?

No, and it is strongly advised to not use them: these are internal classes of the specific implementation, and in other JVM's or even in future JVM's from Sun they may not be present. (Florian)

###### I want to play a wave file in an JDK1.1.x applet

First of all, JDK1.1 generally only provides µ-law, 8000Hz mono playback. It does not provide wave file playback directly. And for playback of audio data of the application, there are only the "unofficial" sun.audio.* classes. So you'd need to write your own classes that read in the wave files, convert the sound data to ulaw and then use the sun.audio.* classes to play them. For code that parses wav files and does ulaw conversion look at tritonus' source code: http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/tritonus/src/org/tritonus/sampled/file/?cvsroot=tritonus (WaveAudioFileReader.java) and http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/tritonus/src/org/tritonus/sampled/?cvsroot=tritonus (TConversionTool.java). Click on the version number to see the source code. Tritonus classes are under the LGPL licence.

Regarding sun.audio.* classes: it is discouraged to use them. I heard that they don't work anymore as expected in jdk1.3. My applets using them work well from jdk1.0 to jdk1.1 and in all browsers that I could put my hand on. (Florian)

###### When I call AudioSystem.getAudioFileTypes(), I receive an empty array. What's wrong?

This is a bug in the Sun jdk1.3.0. It always returns an empty array if there are no service provider plug-ins. If you have service provider plug-ins installed, it returns only the types supported by the plugins, not the "built-in" ones. The Tritonus implementation of this method works as expected. (Matthias)

###### I want to use Mixer.synchronize(), but it seems to have no effect.

Synchronization isn't implemented in any known Java Sound implementation. It is on my TODO list for Tritonus. (Matthias)