2011-05-07 4 views
3

J'essaie de mixer plusieurs flux audio différents et d'essayer de les faire jouer en même temps au lieu de un à la fois.Mixage audio avec Java (sans API Mixer)

Le code ci-dessous les lit un à la fois et je n'arrive pas à trouver une solution qui n'utilise pas l'API Java Mixer. Malheureusement, ma carte audio ne supporte pas la synchronisation à l'aide de l'API Mixer et je suis obligé de trouver un moyen de le faire via le code.

Veuillez nous aviser.

///// CODE CI-DESSOUS EST ////

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<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<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 < tracks; i++) 
     { 
     sourceLine[i].start(); 
     }   
     int bytesRead = 0; 
     while(bytesRead != -1) 
     { 
     for(int i = 0; i < tracks; i++) 
     { 
      try 
      { 
      bytesRead = audioInputStream[i].read(buffer, 0, buffer.length); 
      } 
      catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
      }    
      if(bytesRead >= 0) 
      { 
      int bytesWritten = sourceLine[i].write(buffer, 0, bytesRead); 
      System.out.println(bytesWritten); 
      } 
     } 
     } 
    } 
    }; 
    Thread playThread = new Thread(playAudioMixRunner); 
    playThread.start(); 
} 
} 

Répondre

5

Le problème est que vous n'êtes pas les échantillons ensemble ajouterez. Si nous regardons 4 pistes, données PCM 16 bits, vous devez ajouter toutes les différentes valeurs ensemble pour les "mélanger" en une sortie finale. Ainsi, à partir d'un nombre purement point de vue, il ressemblerait à ceci:

[Track1] 320 -16 2000 200 400 
[Track2] 16 8 123 -87 91 
[Track3] -16 -34 -356 1200 805 
[Track4] 1011 1230 -1230 -100 19 
[Final!] 1331 1188 537 1213 1315 

Dans votre code ci-dessus, vous ne devriez écrire un seul tableau d'octets. Ce tableau d'octets est le mixage final de toutes les pistes additionnées. Le problème est que vous écrivez un tableau d'octets pour chaque piste différente (il n'y a donc pas de mixage, comme vous l'avez remarqué). Si vous voulez garantir que vous n'avez aucun "écrêtage", vous devriez prendre la moyenne de toutes les pistes (donc ajoutez les quatre pistes ci-dessus et divisez par 4). Cependant, il y a des artefacts de choisir cette approche (comme si vous avez le silence sur trois pistes et une piste bruyante, la sortie finale sera beaucoup plus quiter que le volume de la piste qui n'est pas silencieuse). Il y a des algorithmes plus compliqués que vous pouvez utiliser pour faire le mixage, mais d'ici là vous écrivez votre propre mixeur: P.