0

2つのWAVファイルをミックスしようとしています。

WAVファイルはバイト配列として利用可能であり、私は以下のコードを使用して2つを混合しています。

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を使用してサウンドサンプルのバイトを結合すると、ノイズが発生します

次に、それを「正規化」するには、最初にピークを見つけてから、すべての結果をその値にスケーリングする必要があります。つまり、2つのループがあります。1つは「ピーク」を見つけるためのもので、もう1つは値を追加して、新しいピークに合わせてスケーリングするためのものです。このようなもの:

//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 に答える