0

我正在尝试混合两个 WAV 文件。

WAV 文件可用作字节数组,我使用下面的代码将两者混合。

byte[] byte1 , byte[] byte2

// 44 is header of wav file
for( int i = 44 ; i < byte1.length ; i++){
   byte1[i] = byte1[i] + byte2[i];
}

上面的代码大部分都有效。但是当结果超过最大波(16 位音频文件)时,它就会有噪音。如何标准化混合声音?

4

3 回答 3

4

首先,如果你的音频确实是 16 位,那么逐字节添加它是行不通的。其他人对此发表了评论。您可以在此处查看我的回答,了解如何处理此问题。

使用 Android 的 AudioTrack 来组合声音样本的字节会产生噪音

其次,要“标准化”它,您必须先找到峰值,然后将所有结果缩放到该值。这意味着两个循环:一个是找到“峰值”,一个是添加值,缩放到新的峰值。像这样的东西:

//this is the raw audio data -- no header
short[] audioData1 , short[] audioData2

//find the max:
float max = 0;
for( int i = 0 ; i < audioData1.length ; i++) {
   if( Math.abs( audioData1[i] + audioData2[i] ) > max )
      max = Math.abs( audioData1[i] + audioData2[i] );
}

//now find the result, with scaling:
for( int i = 0 ; i < audioData1.length ; i++) {
   audioData1[i] = Math.Round(Short.MAX_VALUE * ( audioData1[i] + audioData2[i] ) / max) ;
}
//normalized result in audioData1
于 2012-07-04T16:27:52.733 回答
4
    short[] audioData1 = null;
    short[] audioData2 = null;

    int n = 0;

    try {
        DataInputStream in1;
        in1 = new DataInputStream(new FileInputStream("v1.wav"));
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        try {

            while ((n = in1.read()) != -1) {
                bos.write(n);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        ByteBuffer bb = ByteBuffer.wrap(bos.toByteArray());
        bb.order(ByteOrder.LITTLE_ENDIAN);
        ShortBuffer sb = bb.asShortBuffer();
        audioData1 = new short[sb.capacity()];

        for (int i = 0; i < sb.capacity(); i++) {
            audioData1[i] = sb.get(i);
        }

    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        DataInputStream in1;
        in1 = new DataInputStream(new FileInputStream("v2.wav"));
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        try {

            while ((n = in1.read()) != -1) {
                bos.write(n);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        ByteBuffer bb = ByteBuffer.wrap(bos.toByteArray());
        bb.order(ByteOrder.LITTLE_ENDIAN);
        ShortBuffer sb = bb.asShortBuffer();
        audioData2=  new short[sb.capacity()];

        sb.get(audioData2);


        System.out.println();
    } catch (IOException e) {
        e.printStackTrace();
    }

    // find the max:
    float max = 0;
    for (int i = 22; i < audioData1.length; i++) {
        if (Math.abs(audioData1[i] + audioData2[i]) > max)
            max = Math.abs(audioData1[i] + audioData2[i]);
    }

    System.out.println("" + (Short.MAX_VALUE - max));

    int a, b, c;

    // now find the result, with scaling:
    for (int i = 22; i < audioData1.length; i++) {
        a = audioData1[i];
        b = audioData2[i];

        c = Math.round(Short.MAX_VALUE * (audioData1[i] + audioData2[i])
                / max);

        if (c > Short.MAX_VALUE)
            c = Short.MAX_VALUE;
        if (c < Short.MIN_VALUE)
            c = Short.MIN_VALUE;


        audioData1[i] = (short) c; 

    }

    // to turn shorts back to bytes.
    byte[] end = new byte[audioData1.length * 2];
    ByteBuffer.wrap(end).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().put(audioData1);

    try {
        OutputStream out  = new FileOutputStream("mixer.wav");

        for (int i = 0; i < end.length; i++) {
            out.write(end[i]);
            out.flush();
        }

        out.close();

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

这行得通,谢谢大家的回答

于 2012-07-09T08:01:01.150 回答
0
    short[] audioData1 = null;
    short[] audioData2 = null;

    int n = 0;

    DataInputStream in1;
    try {
        in1 = new DataInputStream(new FileInputStream("audio1.wav"));

        audioData1 = new short[in1.available() / 2];
        ShortBuffer b1 = ShortBuffer.wrap(audioData1);
        try {

            while (true) {
                n = in1.readShort();
                b1.put((short) n);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    DataInputStream in2;
    try {
        in2 = new DataInputStream(new FileInputStream("audio2.wav"));

        audioData2 = new short[in2.available() / 2];
        ShortBuffer b2 = ShortBuffer.wrap(audioData2);
        try {

            while (true) {
                n = in2.readShort();
                b2.put((short) n);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    } catch (IOException e) {
        e.printStackTrace();
    }

        // find the max:
    float max = 0;
    for (int i = 44; i < audioData1.length; i++) {
        if (Math.abs(audioData1[i] + audioData2[i]) > max)
            max = Math.abs(audioData1[i] + audioData2[i]);
    }

    // now find the result, with scaling:
    for (int i = 44; i < audioData1.length; i++) {
        audioData1[i] = (short) Math.round(Short.MAX_VALUE
                * (audioData1[i] + audioData2[i]) / max);
    }


    DataOutputStream out;

    try {
        out = new DataOutputStream(new FileOutputStream("mix.wav"));

        for (int i = 0; i < audioData1.length; i++) {
            out.writeShort(audioData1[i]);
            out.flush();
        }

        out.close();

    } catch (IOException e) {
        e.printStackTrace();
    }

现在简而言之,它不会工作,因为最大值是 32768(最大短)并且没有任何改变

于 2012-07-05T08:13:26.093 回答