2013-01-23 13 views
11

Ich lese eine WAV-Datei zu einem Byte-Array mit this method (shown below). Jetzt, da ich es in meinem Byte-Array gespeichert habe, möchte ich die Lautstärken ändern.Audio: Ändern der Lautstärke von Samples in Byte-Array

private byte[] getAudioFileData(final String filePath) { 
    byte[] data = null; 
    try { 
    final ByteArrayOutputStream baout = new ByteArrayOutputStream(); 
    final File file = new File(filePath); 
    final AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file); 

    byte[] buffer = new byte[4096]; 
    int c; 
    while ((c = audioInputStream.read(buffer, 0, buffer.length)) != -1) { 
     baout.write(buffer, 0, c); 
    } 
    audioInputStream.close(); 
    baout.close(); 
    data = baout.toByteArray(); 
    } catch (Exception e) { 
    e.printStackTrace(); 
    } 
    return data; 
} 

Edit: einige Informationen über das Audio-Format pro Anfrage:

PCM_SIGNED 44.100,0 Hz, 16 Bit, Mono, 2 Bytes/Rahmen, Little-Endian

Aus Physik-Klasse Ich erinnerte mich, dass Sie die Amplitude einer Sinuswelle ändern können, indem Sie den Sinus-Wert mit einer Zahl zwischen 0 und 1 multiplizieren.

Edit: Aktualisiert Code für 16-Bit-Samples:

private byte[] adjustVolume(byte[] audioSamples, double volume) { 
    byte[] array = new byte[audioSamples.length]; 
    for (int i = 0; i < array.length; i+=2) { 
     // convert byte pair to int 
     int audioSample = (int) ((audioSamples[i+1] & 0xff) << 8) | (audioSamples[i] & 0xff); 

     audioSample = (int) (audioSample * volume); 

     // convert back 
     array[i] = (byte) audioSample; 
     array[i+1] = (byte) (audioSample >> 8); 

    } 
    return array; 
} 

Der Klang stark, wenn ich audioSample mit volume multiplizieren ist verzerrt. Wenn ich die beiden Arrays nicht mit Arrays.compare(array, audioSample) vergleiche, kann ich daraus schließen, dass das Byte-Array korrekt in int konvertiert wird und umgekehrt.

Kann mir jemand helfen? Was mache ich hier falsch? Vielen Dank! :)

+0

Sie können bessere Antworten auf dsp erhalten .stackexchange.com – egrunin

+0

1) Für bessere Hilfe, früher, ein [SSCCE] (http://sscce.org/). 2) Melden Sie 'audioInputStream.getFormat()'. –

+0

@egrunin Danke! Kann ich es einfach kopieren und einfügen oder wie lauten die Regeln für das Verschieben von Themen? – Macks

Antwort

7

Sind Sie sicher, dass Sie 8-Bit-Mono-Audio lesen? Andernfalls entspricht ein Byte nicht einem Abtastwert und Sie können nicht jedes Byte skalieren. Z.B. Wenn es sich um 16-Bit-Daten handelt, müssen Sie jedes Bytepaar als 16-Bit-Ganzzahl analysieren, skalieren und dann als zwei Bytes zurückschreiben.

+1

Vielen Dank. Mein Audio hat eine Beispielgröße von 16 Bit. Ich werde lesen, wie ich meine Byte-Array richtig konvertieren und Ihnen mein Feedback geben, sobald ich es geschafft habe. – Macks

+0

Hallo. :) Ich habe es endlich geschafft, mein Byte-Array korrekt in int und zurück zu konvertieren. Allerdings ist mein Sound noch stärker verzerrt als zuvor, wenn ich meine Samples mit "Volume" multipliziere. Ich habe den Code in der Frage aktualisiert. Könntest du es dir ansehen? Das wäre großartig. Vielen Dank! :) – Macks

+1

Ich habe nur einen kurzen Blick darauf geworfen, aber ich vermute, dass Sie nicht richtig mit negativen Werten umgehen (Sie konvertieren zu einem 'int', was 32-bit ist, könnten Sie vielleicht eine' short' verwenden?). Denken Sie daran, dass die vorzeichenbehafteten Ganzzahlen von Java die Zweierkomplemente sind. – johusman

1

Sind Sie sicher, dass ein Byte ein Beispiel ist? In dieser Formatangabe sieht es so aus, als hätte ein Sample 2 Bytes. Und vergessen Sie nicht, den Header unverändert zu lassen.

WAVE PCM soundfile format

+0

Vielen Dank für Ihre Hilfe. Ich habe meinen Code in der Frage aktualisiert, funktioniert aber immer noch nicht. :( – Macks

6

Problem in int-Typ, Größe von int in Java ist 4 Bytes und die Stichprobengröße 2 Byte

Dieser Code funktioniert:

private byte[] adjustVolume(byte[] audioSamples, float volume) { 
     byte[] array = new byte[audioSamples.length]; 
     for (int i = 0; i < array.length; i+=2) { 
      // convert byte pair to int 
      short buf1 = audioSamples[i+1]; 
      short buf2 = audioSamples[i]; 

      buf1 = (short) ((buf1 & 0xff) << 8); 
      buf2 = (short) (buf2 & 0xff); 

      short res= (short) (buf1 | buf2); 
      res = (short) (res * volume); 

      // convert back 
      array[i] = (byte) res; 
      array[i+1] = (byte) (res >> 8); 

     } 
     return array; 
} 
+0

Wäre es möglich, auch Stereo-Lautstärke zu steuern? – nadous

+0

JA und recht einfach, sobald Sie wissen, PCM ist 16-Bit LL (wo jedes Zeichen ist 1 Byte), so dass ich nur um 4 erhöhen und wiederverwenden dein Code. – nadous

Verwandte Themen