Java了解ByteArrayOutputStream和ByteArrayInputStream

时间:2016-02-20 02:42:48

标签: java audio bytearrayoutputstream bytearrayinputstream

我正在读这篇文章: 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小时)?

注意:不要担心内存中的存储问题字节(没有存储在文件中)而没有播放延迟。

1 个答案:

答案 0 :(得分:0)

我不熟悉Sound API。

但是,没有特别的理由说明为什么你的最后一个代码片段不能正常工作,假设输入可以无限读取,而输出可以无休止地输入。唯一的问题是一端还是另一端"摊位" (这里我缺乏对Sound API的了解)。

如果输出端由于某种原因而停止,则输入端可能会溢出某些内部缓冲区,从而丢失信息。如果输入停止,那么问题就不那么重要了。我不知道这是否是Sound API的实际问题。相反,如果有两个线程发生(或使用Async I / O),一个管理输入,一个管理输出,输入端将为您的程序提供使用您的语义缓存传入数据的机会,而不是API语义,而输出通道停滞。

ByteArrayStreams的问题只是填充和扩展每个字节数组的机制,而不是自己管理它,类似地,将流语义添加到底层字节数组(具有各种有用的功能)。