3 Replies Latest reply: Jul 29, 2010 11:34 AM by captfoss RSS

    Midi, AudioFormats and DataLines

    843802
      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