Mailing Lists: Apple Mailing Lists
Image of Mac OS face in stamp
JavaSound and input latency
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

JavaSound and input latency

Does anyone know of any tricks for reducing the latency of reading from a TargetDataLine for Apple's "Built-in Input" mixer under JavaSound?

I have the simplest possible application I could write. I create a TargetDataLine (input) and SourceDataLine (output). I want to read data on the input line and immediately write it to the output line with the minimal amount of delay. I have tried all combinations of the AudioFormat, and the best latency I can get is about 10.5 milliseconds on the read. Ordinarily that would not be bad, but for audio it is not good. I'm trying to play a musical instrument and hear it in real- time, and that 10 milliseconds is noticeable. If I can just get it to 5 milliseconds, I will live with that.

Here's the inner loop of my app:

format = createAudioFormat();
SourceDataLine outputLine = createSourceDataLine(); //these both use BUFFER_SIZE for the DataLine.Info and when opening the line
TargetDataLine inputLine = createTargetDataLine();

       byte[] buffer = new byte[BUFFER_SIZE];
       while (true)
           int bytesRead =,0,BUFFER_SIZE);
           int bytesWritten = outputLine.write(buffer,0, bytesRead);

private SourceDataLine createSourceDataLine() throws LineUnavailableException
SourceDataLine line = null;
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format, BUFFER_SIZE);
Mixer mixer = AudioStreamUtil.getMixerByName(OUTPUT_MIXER_NAME);
line = (SourceDataLine) mixer.getLine(info);, BUFFER_SIZE);
return line;

private TargetDataLine createTargetDataLine() throws LineUnavailableException
DataLine.Info info = new DataLine.Info(TargetDataLine.class,
format, BUFFER_SIZE);

Mixer mixer = AudioStreamUtil.getMixerByName(INPUT_MIXER_NAME); //returns "Built-in Input" mixer

       TargetDataLine line = (TargetDataLine) mixer.getLine(info);, BUFFER_SIZE);
       return line;

I've experimented with various sample rates, and it seems the faster the better so I have been using 44100 or 48000. I'm using signed samples, Big-endian, 1 channel, mono, normally 8 bits per sample (I've experimented with a larger buffer and 16 bits per sample but that doesn't help.)

With 8 bits per sample and a 512 byte buffer, the read takes on average 10.5 milliseconds. (The write only takes about 80 microseconds) If I try a 256 byte buffer the read time is 9 milliseconds, but the sound is completely garbled, no doubt because the output buffer completely drains before the next read can fill it again.

I may have to finally dive in and learn some CoreAudio and write a TargetDataLine implementation as a SPI in JNI, but I would really like to avoid having to do that if at all possible. And I don't even know if that will solve the problem either, since I don't know what the inherent hardware capabilities are of the line-in port.

Does anyone have any suggestions? (This is on a modern dual-core Intel, 2.6GHz, 64 bit, running Java 6, OS 10.5.7, all software up to date.)

Rob Ross, Lead Software Engineer E! Networks

"Beware of he who would deny you access to information, for in his heart he dreams himself your master." -- Commissioner Pravin Lal

Do not post admin requests to the list. They will be ignored.
Java-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden

Visit the Apple Store online or at retail locations.

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2011 Apple Inc. All rights reserved.