【问题标题】:Java Understanding ByteArrayOutputStream and ByteArrayInputStreamJava 理解 ByteArrayOutputStream 和 ByteArrayInputStream
【发布时间】:2016-06-01 19:18:47
【问题描述】:

我正在阅读这篇文章: http://www.java-tips.org/java-se-tips-100019/120-javax-sound/917-capturing-audio-with-java-sound-api.html 我不想写之前文章的所有代码...

我需要澄清我的理解,我需要解释一下ByteArrayInputStreamByteArrayOutputStream的用法...

基于完整代码:

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 方法,将无限占用字节,但来自 playAudio 方法的 input 如何准确地获取所需的字节以使它们始终如一?

记住: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 小时)?

注意:无需担心内存中字节的存储问题(无需存储在文件中),不会出现播放延迟。

【问题讨论】:

  • 首先我们需要了解你! - 这是无法理解的 - 也许你最好用西班牙语或其他语言发布它
  • @gpasch,你说什么文字不清楚?

标签: java audio bytearrayoutputstream bytearrayinputstream


【解决方案1】:

我不熟悉声音 API。

但是,假设输入可以被无休止地读取,而输出可以被无休止地馈送,那么你的最后一个代码 sn-p 不应该工作并没有什么特别的原因。唯一的问题是一端还是另一端“失速”(这里我对声音 API 的了解不足起了作用)。

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

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

【讨论】:

  • Thaks 我认为 ByteArrayOutputStream 和 ByteArrayInputStream 会增长,但都需要缩小(一方面将引入字节,另一方面将删除它们)。 bytearrayoutputstream 将如何减小其大小(或将再次为空)?,因为每个out.write(buffer, 0, count); 被调用,bytearrayoutputstream 将增长,以及如何将(最后读取的确切字节)传递给 ByteArrayInputStream?或ByteArrayInputStream(audio); 如何准确读取未读的最后一个字节? out.toByteArray() 这里是所有字节(甚至是第一个字节到最后一个字节)
猜你喜欢
  • 1970-01-01
  • 2022-10-14
  • 2016-10-31
  • 1970-01-01
  • 1970-01-01
  • 2011-02-12
  • 1970-01-01
  • 2012-08-11
  • 1970-01-01
相关资源
最近更新 更多