当前位置: 首页 > 面试题库 >

Java:混合两个WAV文件而不引入噪音

姜淇
2023-03-14
问题内容

我正在尝试将2个WAV文件混合到一个WAV文件中。文件将始终具有完全相同的持续时间,并具有相同的格式(16位,44.1
kHz,带符号,小字节序,单声道)。使用AudioSystem.getAudioInputSream的ByteArrayOutputStream将两个WAV放入字节数组,以确保我只是获取PCM数据而没有标题。

在其他几个线程的帮助下,我已经能够成功地组合阵列,但又不会在信号中引入大量噪声。它绝对听起来不像是削波或失真,但为了安全起见,我尝试对每对字节的总和求平均,这只会使所有内容变得更安静,更安静。

任何见解将不胜感激!我尝试了两种方法,它们应该执行相同的操作,并且似乎产生相同的声音结果。

第一种更简单的方法:

private byte[] mixBuffers(byte[] bufferA, byte[] bufferB) {
    byte[] array = new byte[bufferA.length];
    for (int i=0; i<bufferA.length; i++) {
        array[i] = (byte) ((bufferA[i] + bufferB[i]));
    }
    return array;
}

第二种更具体的方法:

private byte[] mixBuffers(byte[] bufferA, byte[] bufferB) {
    byte[] array = new byte[bufferA.length];

    for (int i=0; i<bufferA.length; i+=2) {
        short buf1A = bufferA[i+1];
        short buf2A = bufferA[i];
        buf1A = (short) ((buf1A & 0xff) << 8);
        buf2A = (short) (buf2A & 0xff);

        short buf1B = bufferB[i+1];
        short buf2B = bufferB[i];
        buf1B = (short) ((buf1B & 0xff) << 8);
        buf2B = (short) (buf2B & 0xff);

        short buf1C = (short) (buf1A + buf1B);
        short buf2C = (short) (buf2A + buf2B);

        short res = (short) (buf1C | buf2C);

        array[i] = (byte) res;
        array[i+1] = (byte) (res >> 8);
    }

    return array;
}

如果有帮助,请按照以下步骤将文件放入字节数组:

{
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    AudioInputStream ais;
    ais = AudioSystem.getAudioInputStream(audioFile);
    int read;
    byte[] buffer = new byte[1024];
    while ((read = ais.read(buffer)) != -1) {
        baos.write(buffer, 0, read);
    }
    baos.flush();
    byte[] byteBufferA = baos.toByteArray();

    baos = new ByteArrayOutputStream();
    ais = AudioSystem.getAudioInputStream(audioFile2);
    buffer = new byte[1024];
    while ((read = ais.read(buffer)) != -1) {
        baos.write(buffer, 0, read);
    }
    baos.flush();
    byte[] byteBufferB = baos.toByteArray();

    byte[] byteBufferC = mixBuffers(byteBufferA, byteBufferB);
}

问题答案:

这些文件包含16位样本-每个样本为两个字节长。但是,您的第一种方法尝试单独混合每个字节。结果就像通过加每个数字(不带进位)来加一个数字:165 +
248-> 103。

第二种方法是使用按位或而不是加法。这就像通过取每个数字的最大值将两个数字相加:165 + 248-> 268。

尝试使用第二种方法,但将|+



 类似资料:
  • 问题内容: 如何使用Java合并两个WAV文件? 我试过了,但是没有正常工作,他们还有其他方法吗? 问题答案: 如果直接使用wav文件的字节,则可以在任何编程语言中使用相同的策略。对于此示例,我将假设两个源文件具有相同的比特率/数字通道,并且具有相同的长度/大小。(否则,您可能可以在开始合并之前对其进行编辑)。 首先看一下WAV规范,我在斯坦福课程网站上找到了一个很好的人: 常见的标头长度为44或

  • 我正在用GLSL处理纹理。我如何用GLSL处理两个纹理?一个人推荐我在我的GLSL中做两个采样2D...但是GLSL如何知道2D应该使用哪些采样器呢?(我不是在说混合纹理...) 我听说我应该使用glbindtexture。我怎么能这么做?用glbindtexture?有人有这方面的例子吗?

  • 问题内容: 我在数组列表中有很多Slot类型的对象。 插槽类别如下所示- 让类型列表被调用。插槽根据开始时间进行排序。一个时隙的结束时间可以等于下一时隙的开始时间,但是它们永远不会重叠。 是否有任何可能的方式可以使用Java 8流在此列表上进行迭代,并且如果一个的结束时间与下一个的开始时间匹配,则将两个插槽合并并输出到一个插槽中? 问题答案: 我的免费StreamEx库完全支持这种情况,该库增强了

  • 我正在为工作中的一个项目尝试闪烁。我已经到了通过应用计数窗口等来处理流的地步。然而,我注意到一个特殊的行为,我无法解释。 看起来一个流是由两个线程处理的,输出也是分成两部分的。 首先,我注意到使用将流打印到标准控制台时的行为。 然后,我打印到一个文件,它实际上正在输出文件夹中的两个名为1和2的文件中打印。 有人能解释一下为什么Flink会有这种行为吗?如何配置它?为什么有必要对结果流进行拆分? 并

  • 问题内容: 我正在编写一个使用QuickFIX / J作为FIX框架的应用程序。我的对方向我发送了FIX版本4.4 的消息,但只有某些字段(组件)的版本为5.0 现在,我正在尝试实现可以​​阅读此组件的功能。 这个 不起作用!消息来自版本4.4,这就是为什么只需要a 而不是版本5.0的原因 如果我尝试这个 我收到以下错误: 这是因为我得到4.4场,但要像对待4.4版本。看这里 也许有人可以帮我…

  • 问题内容: 我有一些String []数组,例如: 如何混合它们,以便得到(a的0个元素,然后b,c,a,b,c的1个元素,依此类推)?谢谢 更准确地说,结果数组必须包含第一个数组的第一个值,然后是第二个数组的第一个值,…,最后一个数组的第一个值,第一个数组的第二个值,…,最后一个数组的第二个值,…,最大数组的最后一个值。如果数组的大小不同,则不会考虑较小的数组。 这是一个例子: 另外,我想结合可