【问题标题】:Audio Mixing with Java (without Mixer API)使用 Java 进行音频混合(没有 Mixer API)
【发布时间】:2011-08-20 19:08:16
【问题描述】:

我正在尝试混合几个不同的音频流并尝试让它们同时播放而不是一次播放。

下面的代码一次播放一个,我想不出不使用 Java Mixer API 的解决方案。不幸的是,我的声卡不支持使用 Mixer API 进行同步,我不得不想办法通过代码来实现。

请指教。

/////代码在下面////

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

【问题讨论】:

    标签: java audio streaming mixing mixer


    【解决方案1】:

    问题在于您没有将样本添加在一起。如果我们正在查看 4 个音轨、16 位 PCM 数据,您需要将所有不同的值加在一起以将它们“混合”成一个最终输出。因此,从纯数字的角度来看,它看起来像这样:

    [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
    

    在您上面的代码中,您应该只编写一个单字节数组。该字节数组是添加在一起的所有轨道的最终混合。问题是您正在为每个不同的轨道编写一个字节数组(因此没有发生混音,正如您所观察到的)。

    如果您想保证没有任何“剪辑”,您应该取所有轨道的平均值(因此将上面的所有四个轨道相加并除以 4)。但是,选择该方法会产生伪影(例如,如果您在三个轨道和一个响亮的轨道上静音,则最终输出将比一个不静音的轨道的音量要安静得多)。您可以使用更复杂的算法来进行混音,但到那时您正在编写自己的混音器:P。

    【讨论】:

      猜你喜欢
      • 2016-10-19
      • 2014-05-27
      • 1970-01-01
      • 1970-01-01
      • 2013-08-10
      • 2012-03-02
      • 2013-08-09
      • 2015-11-08
      • 1970-01-01
      相关资源
      最近更新 更多