This discussion is archived
3 Replies Latest reply: Jul 29, 2010 9:34 AM by captfoss RSS

Midi, AudioFormats and DataLines

843802 Newbie
Currently Being Moderated
Hello

I've written a simple application which generates and plays midi events in realtime; this is all fine, except (as I expected there would be) there's a noticeable latency on generating the midi sounds.

I decided to try and prerender audio clips for each of the midi events at various levels so I could use these prerendered ones to lower the latency. I assumed (perhaps incorrectly?) that I could get the audio device, play the midi events, and stream the outputted audio to an audio stream.

However, I'm having troubles getting a TargetDataLine (which I think is they way to get input audio into my java application?) - I keep getting the exception:
Java.lang.IllegalArgumentException: No line matching interface 
TargetDataLine support format <insert params here> is supported
when I call
AudioSystem.getLine(...)
with an AudioFormat.

I thought this was because I was providing some parameters to AudioFormat that my version of Java didn't support (Windows Vista, Java 1.6.0_10-rc2) so wrote a quick loop to try all of them:
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.TargetDataLine;

public class TestAudioFormat {

  public static void main(String[] args) {
    TargetDataLine line=null;
    float[] sampleRates=new float[] { 8000, 11025, 16000, 22050, 44100 };
    int[] sampleSizes=new int[] { 8, 16 };
    int[] channels=new int[] {1, 2};
    boolean[] signs=new boolean[] { false, true };
    boolean[] endians=new boolean[] { false, true };
    for (float sampleRate: sampleRates) {
      for (int sampleSize: sampleSizes) {
        for (int channel: channels) {
          for (boolean sign: signs) {
            for (boolean endian: endians) {
              try {
                AudioFormat format=new AudioFormat(sampleRate, sampleSize, channel, sign, endian);
                DataLine.Info info=new DataLine.Info(TargetDataLine.class, format);
                line=(TargetDataLine)AudioSystem.getLine(info);
                System.out.println("Found Audio format that works: "+sampleRate+","+sampleSize+","+channel+","+sign+","+endian);
              }
              catch (Exception e) {
                System.out.println(e);
              }
            }
          }
        }
      }
    }
    System.out.println("Line found: " + line);
  }
}
I also tried using the alternative AudioFormat constructor which takes an Encoding as the first parameter to no avail...

So, 2 questions really:
1. How should I be getting an AudioFormat that TargetDataLine supports?
2. Even if I manage to get a TargetDataLine, will that allow me to render midi sounds to wav? (or some other raw audio format for storage in memory, then play without delay)

Thanks very much!

Seb