Java: Mixing two WAV files without introducing noise

一曲冷凌霜 提交于 2019-12-01 06:34:42

问题


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.

The first, simpler method:

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

And the second, more specific method:

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

回答1:


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.

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 +.



来源:https://stackoverflow.com/questions/32856836/java-mixing-two-wav-files-without-introducing-noise

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!