gpt4 book ai didi

java - 使用 Java 进行音频混合(没有 Mixer API)

转载 作者:塔克拉玛干 更新时间:2023-11-02 07:56:36 25 4
gpt4 key购买 nike

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

下面的代码一次播放一个,我想不出不使用 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();
}
}

最佳答案

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

关于java - 使用 Java 进行音频混合(没有 Mixer API),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5922135/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com