使用Java混音(不使用混音器API)

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

下面的代码一次一个地播放它们,我无法找出不使用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 = 0) { int bytesWritten = sourceLine[i].write(buffer, 0, bytesRead); System.out.println(bytesWritten); } } } } }; Thread playThread = new Thread(playAudioMixRunner); playThread.start(); } } 

问题是您没有将样本添加到一起。 如果我们查看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。