Java:混合两个WAV文件而不会引入噪音 [英] Java: Mixing two WAV files without introducing noise

查看:163
本文介绍了Java:混合两个WAV文件而不会引入噪音的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to mix 2 WAV files into a single WAV file. The files will always be the exact same duration and have the same format (16 bit, 44.1 kHz, signed, little endian, mono). Both WAVs are put into to byte arrays using a ByteArrayOutputStream using AudioSystem.getAudioInputSream to ensure I'm just getting the PCM data and no headers.

在其他几个线程的帮助下,我已经能够成功地组合阵列,但不会在信号中引入大量噪声。它肯定听起来不像削波或失真,但我已经尝试平均每对字节的总和以确保安全,这使得一切都更安静,噪音等等。

With the help of a few other threads, I've been able to successfully combine the arrays, but not without introducing a significant amount of noise to the signal. It definitely doesn't sound like clipping or distortion, but I have tried averaging the sum of each pair of bytes for safety which just makes everything quieter, noise and all.

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

Any insight would be greatly appreciated! I've tried two methods which should do the same thing, and seem to produce the same sonic results.

第一种更简单的方法:

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;
}

如果有帮助,这就是我如何将文件放入字节数组中:

If it helps, here's how I'm getting the files into the byte arrays:

{
    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位samples - 每个样本长度为两个字节。但是,您的第一种方法尝试独立地混合每个字节。结果就像添加一个数字一样,通过添加每个数字(不带进位):165 + 248 - > 103。

These files contain 16-bit samples - each sample is two bytes long. However, your first method tries to mix each byte independently. The result is like adding a number by adding each digit (without carry): 165 + 248 -> 103.

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

Your second method is using bitwise OR instead of addition. That's like adding two numbers by taking the greatest value of each digit: 165 + 248 -> 268.

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

Try using your second method, but replacing | with +.

这篇关于Java:混合两个WAV文件而不会引入噪音的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆