如何规范化混合WAV文件

时间:2012-07-04 14:14:43

标签: java android c++ c audio

我正在尝试混合两个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位音频文件)时,它会产生噪音。如何标准化混合声音?

3 个答案:

答案 0 :(得分:4)

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

using Android's AudioTrack to combine bytes of sound samples produces noise

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

//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

答案 1 :(得分: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();
    }
}

这是有效的,谢谢大家的答案

答案 2 :(得分: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(最大短路)并且没有任何改变