0

我正在阅读这篇文章: 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方法,将无限地占用字节,但是inputplayAudio方法,如何准确地获取所需的字节以使它们始终如一地发声?

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

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

4

1 回答 1

0

我不熟悉声音 API。

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

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

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

于 2016-02-20T22:11:50.487 回答