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();


      inputLine.start();
      outputLine.start();
      byte[] buffer = new byte[BUFFER_SIZE];
      while (true)
      {
          int bytesRead = inputLine.read(buffer,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);
line.open(format, 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);
      line.open(format, 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 _______________________________________________ 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.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2011 Apple Inc. All rights reserved.