我正在阅读这篇文章: http ://www.java-tips.org/java-se-tips-100019/120-javax-sound/917-capturing-audio-with-java-sound-api.html 我没有不想写之前文章中的所有代码...
我需要澄清我的理解,我需要解释ByteArrayInputStream和ByteArrayOutputStream的使用......
基于完整代码:
在captureAudio()方法中专注于循环 while
while (running) {
int count = line.read(buffer, 0, buffer.length);
if (count > 0) {
out.write(buffer, 0, count);
}
}
out.close();
根据定义(检查第 64 和 65 行):
final TargetDataLine line = (TargetDataLine)
AudioSystem.getLine(info);
在第 79 行:线是麦克风和 // 从数据线的输入缓冲区读取音频数据。换句话说,从麦克风传入的字节被定位或存储在字节中buffer
。
在第 81 行:
out.write(buffer, 0, count);
out
是一个 ByteArrayOutputStream 对象..
Java IO API 的 ByteArrayOutputStream 类允许您捕获写入到数组中的流的数据。您将数据写入 ByteArrayOutputStream,完成后调用 ByteArrayOutputStream 的方法 toByteArray() 以获取字节数组中的所有写入数据。缓冲区会随着数据写入而自动增长。
用我的话来说:ByteArrayOutputStream
将增长从数量定义的缓冲区中获取字节count
另一方面:
在playAudio()方法中。
我可以看到第一行(完整代码的第 101 行)所有字节都被占用了!!!
byte audio[] = out.toByteArray();
https://docs.oracle.com/javase/7/docs/api/java/io/ByteArrayOutputStream.html#toByteArray()
创建一个新分配的字节数组。它的大小是此输出流的当前大小,并且缓冲区的有效内容已复制到其中。
现在在行(102 和 103)
InputStream input =
new ByteArrayInputStream(audio);
在行(105 到 107 )上,字节被传递:
final AudioInputStream ais =
new AudioInputStream(input, format,
audio.length / format.getFrameSize());
专注于 while 循环和近线
int count;
while ((count = ais.read(
buffer, 0, buffer.length)) != -1) {
if (count > 0) {
line.write(buffer, 0, count);
}
}
line.drain();
line.close();
字节取自ais
线(第 110 和 111 行)代表扬声器
final SourceDataLine line = (SourceDataLine)
AudioSystem.getLine(info);
问题1是:
out
,从captureAudio方法,将无限地占用字节,但是input
从playAudio方法,如何准确地获取所需的字节以使它们始终如一地发声?
请记住:out.toByteArray();
占用所有字节,但扬声器不会重复发出相同的字节...
问题2是:
我可以在不使用相关文章中的这两个对象(ByteArrayOutputStream 和 ByteArrayInputStream)的情况下处理从麦克风(TargetDataLine)读取并写入扬声器(SourceDataLine)的情况吗?
像下一个代码:
while (running) {
int count = microphone.read(buffer, 0, buffer.length);
if (count > 0) {
speaker.write(buffer, 0, count);
}
}
speaker.drain();
speaker.close();
问题3是:
如何实现中继器(从麦克风捕获声音并在扬声器上无限播放,1 或 2 小时)?
注意:无需担心内存中的字节存储问题(无需存储在文件中),不会出现播放延迟。