title: Audio Mixing with Java (without Mixer API)
body: <p>I am attempting to mix several different audio streams and trying to get them to play at the same time <em>instead of</em> one-at-a-time.  </p>
  
  <p>The code below plays them one-at-a-time and I cannot figure out a solution that does not use the Java Mixer API.  Unfortunately, my audio card does not support synchronization using the Mixer API and I am forced to figure out a way to do it through code.</p>
  
  <p>Please advise.</p>
  
  <p>/////CODE IS BELOW////</p>
  
  <pre><code>class MixerProgram {
  public static AudioFormat monoFormat;
  private JFileChooser fileChooser = new JFileChooser(); 
  private static File[] files;
  private int trackCount;   
  private FileInputStream[] fileStreams = new FileInputStream[trackCount];
  public static AudioInputStream[] audioInputStream;
  private Thread trackThread[] = new Thread[trackCount];
  private static DataLine.Info sourceDataLineInfo = null; 
  private static SourceDataLine[] sourceLine;  
  
  public MixerProgram(String[] s)
  {
    trackCount = s.length;
    sourceLine = new SourceDataLine[trackCount];
    audioInputStream = new AudioInputStream[trackCount]; 
    files = new File[s.length];
  }
  
  public static void getFiles(String[] s)
  {
    files = new File[s.length];
    for(int i=0; i&lt;s.length;i++)
    {
      File f = new File(s[i]);
      if (!f.exists()) 
      System.err.println("Wave file not found: " + filename);
      files[i] = f;
    }
  }
  
  
  public static void loadAudioFiles(String[] s) 
  {
    AudioInputStream in = null;
    audioInputStream = new AudioInputStream[s.length];
    sourceLine = new SourceDataLine[s.length];
    for(int i=0;i&lt;s.length;i++){
      try 
      {
        in = AudioSystem.getAudioInputStream(files[i]); 
      } 
      catch(Exception e) 
      {
        System.err.println("Failed to assign audioInputStream");
      }
      monoFormat = in.getFormat();
      AudioFormat decodedFormat = new AudioFormat(
                                                AudioFormat.Encoding.PCM_SIGNED,
                                                monoFormat.getSampleRate(), 16, monoFormat.getChannels(),
                                                monoFormat.getChannels() * 2, monoFormat.getSampleRate(),
                                                false);
    monoFormat = decodedFormat; //give back name
    audioInputStream[i] = AudioSystem.getAudioInputStream(decodedFormat, in);
    sourceDataLineInfo = new DataLine.Info(SourceDataLine.class, monoFormat);
    try 
    {
      sourceLine[i] = (SourceDataLine) AudioSystem.getLine(sourceDataLineInfo); 
      sourceLine[i].open(monoFormat);
    } 
    catch(LineUnavailableException e) 
    {
      System.err.println("Failed to get SourceDataLine" + e);
    }
  }               
  }
  
  public static void playAudioMix(String[] s)
  {
    final int tracks = s.length;
    System.out.println(tracks);
    Runnable playAudioMixRunner = new Runnable()
    {
      int bufferSize = (int) monoFormat.getSampleRate() * monoFormat.getFrameSize();
      byte[] buffer = new byte[bufferSize]; 
      public void run()
      {
        if(tracks==0)
          return;
        for(int i = 0; i &lt; tracks; i++)
        {
          sourceLine[i].start();
        }        
        int bytesRead = 0;
        while(bytesRead != -1)
        {
          for(int i = 0; i &lt; tracks; i++)
          {
            try 
            {
              bytesRead = audioInputStream[i].read(buffer, 0, buffer.length);
            } 
            catch (IOException e) {
            // TODO Auto-generated catch block
              e.printStackTrace();
            }            
            if(bytesRead &gt;= 0)
            {
              int bytesWritten = sourceLine[i].write(buffer, 0, bytesRead);
              System.out.println(bytesWritten);
            }
          }
        }
      }
    };
    Thread playThread = new Thread(playAudioMixRunner);
    playThread.start();
  }
  }
  </code></pre>