java中的连续音频流
我正在学习使用Java的声音API。我在YouTube上观看了一段视频,其中讲师只需创建SourceDataLine和TargetDataLine实例,并在单独的线程中使用它们。他使用Thread.sleep()方法一个接一个地调用线程。在这段睡眠时间内,捕捉到所需的声音,然后听到声音 现在,在下面的程序中,我尝试扩展这个想法,并尝试实现连续的音频流。也就是说,我会说话,声音会自动被听到。但这是不可能实现的。我知道我错了,因为我在这方面还是个新手。我应该在哪里做什么更改?如果在录音和播放声音之间有令人满意的延迟,这不会是一个问题 p.S.我将在另一个程序中尝试将其与OpenCV视频共享结合使用。如果您对此有所了解,请随时与我们分享。谢谢java中的连续音频流,java,multithreading,synchronization,Java,Multithreading,Synchronization,我正在学习使用Java的声音API。我在YouTube上观看了一段视频,其中讲师只需创建SourceDataLine和TargetDataLine实例,并在单独的线程中使用它们。他使用Thread.sleep()方法一个接一个地调用线程。在这段睡眠时间内,捕捉到所需的声音,然后听到声音 现在,在下面的程序中,我尝试扩展这个想法,并尝试实现连续的音频流。也就是说,我会说话,声音会自动被听到。但这是不可能实现的。我知道我错了,因为我在这方面还是个新手。我应该在哪里做什么更改?如果在录音和播放声音之间
import javax.sound.sampled.*;
import java.io.ByteArrayOutputStream;
public class Main {
public boolean recording = true;
public int rate = 0;
public static void main(String[] args) throws Exception{
AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, false);
final ByteArrayOutputStream out = new ByteArrayOutputStream();
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
final TargetDataLine targetLine = (TargetDataLine) AudioSystem.getLine(info);
info = new DataLine.Info(SourceDataLine.class, format);
final SourceDataLine sourceLine = (SourceDataLine) AudioSystem.getLine(info);
Main m = new Main();
new record(m, format, out, targetLine);
new play(m, format, out, sourceLine);
}
synchronized public void record(TargetDataLine targetLine, ByteArrayOutputStream out){
while(!recording){
try{
wait();
}catch(Exception e){
System.out.println(e);
}
}
byte[] data = new byte[targetLine.getBufferSize()/5];
int readBytes;
readBytes = targetLine.read(data, 0, data.length);
out.write(data, 0, readBytes);
}
synchronized public void play(SourceDataLine sourceLine, ByteArrayOutputStream out){
while(recording){
try{
wait();
}catch(Exception e){
System.out.println(e);
}
}
sourceLine.write(out.toByteArray(), 0, out.size());
}
synchronized public int change(){
rate++;
if(rate > 6000 && recording){
rate = 0;
recording = false;
notifyAll();
return 1;
}
else if(rate > 6000 && !recording){
rate = 0;
recording = true;
notifyAll();
return 1;
}
return 0;
}
}
class record implements Runnable{
private Main m;
private AudioFormat format;
private ByteArrayOutputStream out;
final TargetDataLine targetLine;
public record(Main m, AudioFormat format, ByteArrayOutputStream out, TargetDataLine targetLine) throws Exception{
this.m = m;
this.format = format;
this.out = out;
this.targetLine = targetLine;
targetLine.open();
System.out.println("Started recording...");
new Thread(this).start();
}
@Override
public void run() {
targetLine.start();
while(true){
m.record(targetLine, out);
while(m.change() == 1) targetLine.stop();
targetLine.start();
}
}
}
class play implements Runnable{
private Main m;
private AudioFormat format;
private ByteArrayOutputStream out;
final SourceDataLine sourceLine;
public play(Main m, AudioFormat format, ByteArrayOutputStream out, SourceDataLine sourceLine) throws Exception{
this.m = m;
this.format = format;
this.out = out;
this.sourceLine = sourceLine;
sourceLine.open();
System.out.println("Started playing...");
new Thread(this).start();
}
@Override
public void run() {
sourceLine.start();
while(true){
m.play(sourceLine, out);
while(m.change() == 1) sourceLine.stop();
sourceLine.start();
}
}
}
编辑:
我可以让两个流一个接一个地运行,如下所示,但我必须对线程进行硬编码。我分别写了四个线程。如何编写高效的代码,即使用前面的两个线程并连续录制播放声音?我的同步似乎不起作用
import javax.sound.sampled.*;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
public class Main {
public static void main(String[] args) throws Exception{
AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, false);
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
final SourceDataLine sourceLine = (SourceDataLine) AudioSystem.getLine(info);
sourceLine.open();
info = new DataLine.Info(TargetDataLine.class, format);
final TargetDataLine targetLine = (TargetDataLine) AudioSystem.getLine(info);
targetLine.open();
final ByteArrayOutputStream out = new ByteArrayOutputStream();
Thread record = new Thread(){
@Override
public void run(){
targetLine.start();
byte[] data = new byte[targetLine.getBufferSize()/5];
int readBytes;
while(true){
readBytes = targetLine.read(data, 0, data.length);
out.write(data, 0, readBytes);
}
}
};
Thread play = new Thread(){
@Override
public void run(){
sourceLine.start();
while(true){
sourceLine.write(out.toByteArray(), 0, out.toByteArray().length);
}
}
};
final ByteArrayOutputStream out1 = new ByteArrayOutputStream();
Thread record1 = new Thread(() -> {
targetLine.start();
byte[] data = new byte[targetLine.getBufferSize()/5];
int readBytes;
while(true){
readBytes = targetLine.read(data, 0, data.length);
out1.write(data, 0, readBytes);
}
});
Thread play1 = new Thread(() -> {
sourceLine.start();
while(true){
sourceLine.write(out1.toByteArray(), 0, out1.toByteArray().length);
}
});
record.start();
System.out.println("Recording...");
Thread.sleep(4000);
targetLine.stop();
targetLine.drain();
targetLine.close();
play.start();
Thread.sleep(4000);
System.out.println("Playing...");
sourceLine.stop();
sourceLine.drain();
sourceLine.close();
targetLine.open();
sourceLine.open();
record1.start();
System.out.println("Recording...");
Thread.sleep(4000);
targetLine.stop();
targetLine.close();
play1.start();
Thread.sleep(4000);
System.out.println("Playing...");
sourceLine.stop();
sourceLine.close();
}
}