Java - 合并超过 2 个 .wav 文件时遇到问题

Posted

技术标签:

【中文标题】Java - 合并超过 2 个 .wav 文件时遇到问题【英文标题】:Java - Trouble combining more than 2 .wav files 【发布时间】:2011-06-17 03:24:20 【问题描述】:

对于我正在进行的项目,我希望能够连接多个 .wav 文件。

通过我的研究,我能够想出这个代码:

File sample1 = new File("F:\\Programming\\Resources\\Java_Sound\\trumpet1.wav");
File sample2 = new File("F:\\Programming\\Resources\\Java_Sound\\trumpet2.wav");

File fileOut = new File("F:\\Programming\\Resources\\Java_Sound\\Test.wav");

AudioInputStream audio1 = Audiosystem.getAudioInputStream(sample1);
AudioInputStream audio2 = AudioSystem.getAudioInputStream(sample2);

AudioInputStream audioBuild = new AudioInputStream(new SequenceInputStream(audio1, audio2), audio1.getFormat(), audio1.getFrameLength() + audio2.getFrameLength());

//for(int i = 0; i < 5; i++)
//    audioBuild = new AudioInputStream(new SequenceInputStream(audioBuild, audio2), audioBuild.getFormat(), audioBuild.getFrameLength() + audio2.getFrameLength());
//

AudioSystem.write(audioBuild, AudioFileFormat.Type.WAVE, fileOut);

它可以很好地组合两个 .wav 文件,但是当我取消注释 for 循环时,生成的 .wav 文件只播放第一个连接的音频。音轨似乎提前结束了,因为 wmp 的持续时间条仅在屏幕的 1\5 处移动。

我假设问题出在创建的 .wav 文件中的标头上。我研究了许多不同的网页,讨论如何构建标题,但它们的定义略有不同,但都说标题应该是十六进制的。转换流(不是音频流,标准 FileInputStream)时,我拥有的标头是十进制的。此外,在 RIFF 部分之后和 WAVE 部分之前,应该是整个文件的大小,不包括前 8 个字节。然而,我的一些包括连字符。老实说,我不知道这些是什么意思。但是忽略它们,取消注释上面的代码后测试文件的大小仍然是一个更大的数字。

所以在研究了如何连接多个音频文件以及如何创建\管理 .wav 标头之后,我仍然不知道为什么我的其余音频没有播放,如果它甚至存在的话。任何帮助是极大的赞赏。提前致谢。

【问题讨论】:

【参考方案1】:

这可能是因为输入流不能被多次读取。读取输入流后,它将在其末尾,尝试进一步读取将不再从该流中读取字节。

这应该稍作修改,继续在循环中创建新的音频输入流:

File sample1 = new File("f1.wav");
File sample2 = new File("f2.wav");

File fileOut = new File("combined.wav");

AudioInputStream audio1 = AudioSystem.getAudioInputStream(sample1);
AudioInputStream audio2 = AudioSystem.getAudioInputStream(sample2);

AudioInputStream audioBuild = new AudioInputStream(new SequenceInputStream(audio1, audio2), audio1.getFormat(), audio1.getFrameLength() + audio2.getFrameLength());

for(int i = 0; i < 5; i++)

    audioBuild = new AudioInputStream(new SequenceInputStream(audioBuild, /* keep creating new input streams */ AudioSystem.getAudioInputStream(sample2)), audioBuild.getFormat(), audioBuild.getFrameLength() + audio2.getFrameLength());


AudioSystem.write(audioBuild, AudioFileFormat.Type.WAVE, fileOut);

另外,请确保文件的音频格式完全相同。也就是说,相同的采样率、相同的通道数、相同的每个样本位数。否则,您将需要额外的代码来进行示例转换。

【讨论】:

谢谢你,每次创建一个新的输入流都很好。我现在唯一的问题是,是否应该将正在创建的输入流作为 for 循环中的最后一行代码关闭? @Pojo226:关闭序列输入流会关闭其所有底层流,关闭音频输入流也会关闭其底层流。在 finally 块的末尾关闭 audioBuild 应该足够好,但不要在 AudioSystem.write() 调用之前关闭它们,因为这是读取所有流的调用。【参考方案2】:

这是我用来加入任意数量的波形文件的方法。我遍历了波形文件路径的字符串值列表,每次我将上一个生成的 AudioInputStream 与下一个剪辑连接起来。

List<String> paths;
AudioInputStream clip1 = null;
for (String path : paths)

    if(clip1 == null)
    
        clip1 = AudioSystem.getAudioInputStream(new File(path));
        continue;
    
    AudioInputStream clip2 = AudioSystem.getAudioInputStream(new File(path));
    AudioInputStream appendedFiles = new AudioInputStream(
            new SequenceInputStream(clip1, clip2),     
            clip1.getFormat(), 
            clip1.getFrameLength() + clip2.getFrameLength());
    clip1 = appendedFiles;

AudioSystem.write(clip1, AudioFileFormat.Type.WAVE, new File("exported.wav"));

【讨论】:

我该如何做同样的事情,而不是在它们之间添加混合意味着重叠?

以上是关于Java - 合并超过 2 个 .wav 文件时遇到问题的主要内容,如果未能解决你的问题,请参考以下文章

如何将两个 wav 文件合并/合并为一个 wav 文件?

合并音频文件

Java合并音频文件延迟和重叠

在 Python 中合并音频文件

delphi 合并两个 Wav 文件流的函数

多个wav音频文件合并(连接)成一个文件