Java 无法同时播放声音
我试图在点击一个按钮的同时播放六个音轨,但点击后它会播放第一个音轨并等待播放完第二个音轨,依此类推。这是我的密码Java 无法同时播放声音,java,audio,volume,Java,Audio,Volume,我试图在点击一个按钮的同时播放六个音轨,但点击后它会播放第一个音轨并等待播放完第二个音轨,依此类推。这是我的密码 button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (e.getSource() == button) { System.out.println("Button Press
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button) {
System.out.println("Button Pressed");
AudioPlayerExample2 player1 = new AudioPlayerExample2();
AudioPlayerExample2 player2 = new AudioPlayerExample2();
AudioPlayerExample2 player3 = new AudioPlayerExample2();
AudioPlayerExample2 player4 = new AudioPlayerExample2();
AudioPlayerExample2 player5 = new AudioPlayerExample2();
AudioPlayerExample2 player6 = new AudioPlayerExample2();
player1.play(track1);
player2.play(track2);
player3.play(track3);
player4.play(track4);
player5.play(track5);
player6.play(track6);
}
}
});
还有音频播放器
public class AudioPlayerExample2 {
private static final int BUFFER_SIZE = 4096;
public void play(String audioFilePath) {
File audioFile = new File(audioFilePath);
try {
AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
AudioFormat format = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
SourceDataLine audioLine = (SourceDataLine) AudioSystem.getLine(info);
audioLine.open(format);
audioLine.start();
System.out.println("Playback started.");
byte[] bytesBuffer = new byte[BUFFER_SIZE];
int bytesRead = -1;
while ((bytesRead = audioStream.read(bytesBuffer)) != -1) {
audioLine.write(bytesBuffer, 0, bytesRead);
}
audioLine.drain();
audioLine.close();
audioStream.close();
System.out.println("Playback completed.");
} catch (UnsupportedAudioFileException ex) {
System.out.println("The specified audio file is not supported.");
ex.printStackTrace();
} catch (LineUnavailableException ex) {
System.out.println("Audio line for playing back is unavailable.");
ex.printStackTrace();
} catch (IOException ex) {
System.out.println("Error playing the audio file.");
ex.printStackTrace();
}
}
public static void main(String[] args) {
String audioFilePath = "";
AudioPlayerExample2 player = new AudioPlayerExample2();
player.play(audioFilePath);
}}
播放曲目时,按钮也会保持单击状态,因此我也无法使用我的volume jslider。谢谢你的帮助 您编写播放方法的方式将阻止播放,直到流完全播放完毕,这意味着流将一个接一个地播放。一种选择是为每个流分叉一个新线程。这将避免阻塞问题,但会引入另一个问题,即所有线程都将竞相启动。这意味着流不一定都在同一时间启动,尽管您可以使用一个信号使它们非常接近同步 我认为更好的方法是在一个线程中使用从所有文件读取和写入一个SourceDataLine。这意味着您必须自己手动将信号混合在一起。假设所有文件都具有相同的采样率和位深度,这并不太困难。我假设了16位样本。如果您的文件不同,那么您可以找到处理方法
public void play(String[] audioFilePath) {
int numStreams = audioFilePath.length;
// Open all of the file streams
AudioInputStream[] audioStream = new AudioInputStream[numStreams];
for (int i = 0; i < numStreams; i++)
audioStream[i] = AudioSystem.getAudioInputStream(audioFile);
// Open the audio line.
AudioFormat format = audioStream[0].getFormat();
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
SourceDataLine audioLine = (SourceDataLine) AudioSystem.getLine(info);
audioLine.open(format);
audioLine.start();
while (true) {
// Read a buffer from each stream and mix into an array of
// doubles.
byte[] bytesBuffer = new byte[BUFFER_SIZE];
double[] mixBuffer = new double[BUFFER_SIZE/2];
int maxSamplesRead = -1;
for (int i = 0 ; i < numStreams; i++)
{
int bytesRead = audioStream.read(bytesBuffer);
if (bytesRead != -1) {
int samplesRead = bytesRead/2;
if (samplesRead > maxSamplesRead) {
maxSamplesRead = samplesRead;
}
for (int j = 0 ; j < bytesRead/2 ; j++) {
double sample = ((bytesBuffer[j*2] << 8) | bytesBuffer[j*2+1]) / 32768.0;
mixBuffer[j] += sample;
}
}
}
// Convert the mixed samples back into a byte array and play.
if (maxSamplesRead > 0) {
for (int i = 0; i < maxSamplesRead; i++) {
// rescale data between -1 and 1
mixBuffer[i] /= numStreams;
// and now back to 16-bit
short sample16 = (short)(mixBuffer * 32768);
// and back to bytes
bytesBuffer[i*2] = (byte)(sample16 >> 8);
bytesBuffer[i*2+1] = (byte)(sample16);
}
audioLine.write(bytesBuffer, 0, maxSamplesRead*2);
}
else {
// All of the streams are empty so cleanup.
audioLine.drain();
audioLine.close();
for (int i = 0 ; i < numStreams; i++)
audioStream[i].close();
break;
}
}
}
第三种可能更好的选择是从InputStream派生一个类,该类支持多个文件并在内部进行混合。通过这种方法,您可以使用大多数现有的AudioPlayerExample2类,但只有一个实例。这件事会比我现在想做的要复杂得多
顺便说一句,我还没试过编译这些东西。我只是想让大家明白这个想法。排水管堵塞不是吗?我觉得你似乎很难做到这一点,你可以简单地使用剪辑和它的开始,停止和其他功能,正如播放曲目时所演示的那样,按钮也会保持单击状态,因此我也无法使用我的音量jslider。-这意味着您正在阻止EDT并阻止更新/重新绘制UI或响应UI事件,这可能与您的第一个问题有关。你需要找到你正在使用的哪些方法阻止了当前线程,因为你的播放方法在曲目播放完成之前不会返回?我不能使用Clip,因为音频文件非常大,为50mb和@immibis,我如何解决这个问题?
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button) {
System.out.println("Button Pressed");
AudioPlayerExample2 player = new AudioPlayerExample2(allTracks);
}
}
});