1

我编写了一个播放 .wav 文件的代码。它工作正常。现在,另一段代码从音频接收器获取音乐数据并继续附加到该 .wav 文件。

假设我运行播放器时音频的长度为 5 秒,现在尽管使用更新程序代码更新了 wav 文件,但播放器只播放了最初的 5 秒。

播放代码很简单:

try{
    AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("junk.wav"));
    Clip clip = AudioSystem.getClip();
    clip.open(audioInputStream);
    clip.start();
}catch(Exception ex){
    System.out.println("Error with playing sound.");
    ex.printStackTrace();
}

如何在输入进入麦克风插孔后播放音频流(允许一些延迟)?

4

2 回答 2

1

您没有发布问题,因此答案将是一般性的。

wav 文件具有严格定义的格式。它包含一个标题和数据(声音样本)。标头定义了 wav 文件中的数据数量。要播放音频,标题提供了额外的信息,如采样率。如果您使用 AudioInputStream 打开 wav 文件,它会解析这些信息。由于标头中定义的数据长度,您无法将数据附加到 wav 文件。您可以修改 wav 文件数据样本,但必须确保交换的数据具有相同的格式。

当您打开 Class AudioInputStream 的文档时,第一条语句是:“音频输入流是具有指定音频格式和长度的输入流。”

从操作系统的角度来看。

在实时播放器中使用文件作为缓冲区可能是个问题。文件系统在许多级别上被缓冲/缓存,以提供对大块内存的快速访问。即时读取/写入文件甚至可能导致文件损坏。如果我了解您想在 WAV 文件中创建一个循环缓冲区(一次又一次地覆盖相同的样本)。您会发现将文件的新内容(由 writer 提供)与循环播放的 Clip 同步的其他问题。

你能做什么?

您可以使用 SourceDataLine / TargetDataLine。接下来即时读取样本并将其保存在字节缓冲区(例如 byte[] 或 ByteBuffer)而不是文件中。您必须首先用传入的数据填充缓冲区,然后在循环中从/到 xxxDataLine 进行读/写。您必须知道该行是为特定的 AudioFormat 打开的。输入和输出使用相同的格式。并非所有格式都受支持(这取决于硬件,因此这是 Java 的“温和”内容)。请注意,有时即使以字节为单位的数据大小也必须调整为帧大小(每个样本 16 位 = 2 个字节)。

于 2013-06-28T16:00:20.303 回答
0

请参阅 Java 教程的声音跟踪中的“捕获音频”

要理解本节,您还必须阅读前面的部分。这不是一本容易阅读的书。但基本上,传单 (+1) 提到的 TargetDataLine 是关键。

我怀疑如果您在读取时附加到 .wav,您将收到并发错误。

如果您只想从麦克风输入声音,并且您正确设置了 TargetDataLine,您应该能够获得相当低的延迟。

于 2013-06-28T19:59:58.587 回答