我正在读这篇文章: http://www.java-tips.org/java-se-tips-100019/120-javax-sound/917-capturing-audio-with-java-sound-api.html 我不想在文章之前编写所有代码......
我需要澄清我的理解,我需要解释有关使用 ByteArrayInputStream 和 ByteArrayOutputStream ......
基于完整代码:
captureAudio()方法专注于循环
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行的:Line是Microphone,//从数据行的输入缓冲区读取音频数据。换句话说,从麦克风传入的字节以字节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 是:
来自 captureAudio 方法的 out
将无限地占用字节,但 playAudio 方法中的input
如何获取所需的字节数一致地发出声音吗?
请记住:out.toByteArray();
占用所有字节,但扬声器不会重复相同的字节......
问题2 是:
我可以处理这种从麦克风(TargetDataLine)读取并写入扬声器(SourceDataLine)而不使用这两个对象(ByteArrayOutputStream和ByteArrayInputStream)的相关文章吗?
像下一个代码:
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小时)?
注意:不要担心内存中的存储问题字节(没有存储在文件中)而没有播放延迟。
答案 0 :(得分:0)
我不熟悉Sound API。
但是,没有特别的理由说明为什么你的最后一个代码片段不能正常工作,假设输入可以无限读取,而输出可以无休止地输入。唯一的问题是一端还是另一端"摊位" (这里我缺乏对Sound API的了解)。
如果输出端由于某种原因而停止,则输入端可能会溢出某些内部缓冲区,从而丢失信息。如果输入停止,那么问题就不那么重要了。我不知道这是否是Sound API的实际问题。相反,如果有两个线程发生(或使用Async I / O),一个管理输入,一个管理输出,输入端将为您的程序提供使用您的语义缓存传入数据的机会,而不是API语义,而输出通道停滞。
ByteArrayStreams的问题只是填充和扩展每个字节数组的机制,而不是自己管理它,类似地,将流语义添加到底层字节数组(具有各种有用的功能)。