volumen online normalizar nivelar mp3gain las full como canciones bajarle java android c++ c audio

java - online - mp3gain windows 7



Cómo normalizar archivos WAV mixtos (3)

Estoy tratando de mezclar dos archivos WAV.

Los archivos WAV están disponibles como matrices de bytes y estoy usando el código siguiente para mezclar los dos.

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

El código anterior funciona en su mayoría. Pero cuando el resultado es más que onda máxima (archivo de audio de 16 bits), tiene ruido. ¿Cómo puedo normalizar el sonido mixto?


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

ahora es, en resumen, no funcionará porque el valor máximo es 32768 (máximo corto) y nada ha cambiado


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

esto funciona, gracias a todos por las respuestas


En primer lugar, si su audio es de 16 bits, agregarlo byte a byte no funcionará. Otras personas comentaron sobre esto. Puedes ver mi respuesta aquí para saber cómo manejar este problema.

utilizar AudioTrack de Android para combinar bytes de muestras de sonido produce ruido

En segundo lugar, para "normalizarlo", primero deberá encontrar el pico y luego escalar todos los resultados a ese valor. Eso significa dos bucles: uno para encontrar el "pico" y otro para agregar los valores, escalando al nuevo pico. Algo como esto:

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