如何规范化混合WAV文件

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

首先,如果您的音频确实是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 
  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(); } } 

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

  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(最大短)并且没有任何改变