2013-01-23 12 views
11

Czytam plik wav do tablicy bajtów za pomocą this method (shown below). Teraz, gdy mam go przechowywany wewnątrz tablicy bajtów, chcę zmienić głośność dźwięku.Dźwięk: Zmień głośność próbek w tablicy bajtów

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: Na życzenie kilka informacji na format audio:

PCM_SIGNED 44100,0 Hz, 16 bit, mono, 2 bajty/ramka, little-endian

Od klasa fizyki Przypomniałem sobie, że możesz zmienić amplitudę fali sinusoidalnej, mnożąc wartość sinusoidalną z liczbą od 0 do 1.

Edycja: Zaktualizowany kod dla próbek 16-bitowych:

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

dźwięk jest mocno zniekształcony, jeśli pomnożyć audioSample z volume. Jeśli nie, i porównaj obie tablice z Arrays.compare(array, audioSample), mogę wywnioskować, że tablica bajtów jest poprawnie konwertowana na int i odwrotnie.

Czy ktoś może mi pomóc? Co ja tu robię źle? Dziękuję Ci! :)

+0

Można uzyskać lepsze odpowiedzi na DSP .stackexchange.com – egrunin

+0

1) Aby uzyskać lepszą pomoc wcześniej, opublikuj [SSCCE] (http://sscce.org/). 2) Zgłoś 'audioInputStream.getFormat()'. –

+0

@egrunin Dziękujemy! Czy mogę po prostu skopiować i wkleić tam lub jakie są zasady przenoszenia tematów? – Macks

Odpowiedz

7

Czy na pewno czytasz 8-bitowe audio mono? W przeciwnym razie jeden bajt nie jest równy jednej próbce i nie można po prostu skalować każdego bajtu. Na przykład. jeśli jest to 16-bitowe dane, musisz przetworzyć każdą parę bajtów jako 16-bitową liczbę całkowitą, skalować, a następnie zapisać jako dwa bajty.

+1

Dziękuję. Moje audio ma próbkę o rozmiarze 16 bitów. Przeczytam, jak poprawnie przekonwertować tablicę bajtów i przekazuję moją opinię, gdy już to zrobiłem. – Macks

+0

Hej. :) W końcu udało mi się poprawnie przekonwertować tablicę bajtów na int i back. Jednak mój dźwięk jest jeszcze silniej zniekształcony niż wcześniej, jeśli pomnożę moje próbki za pomocą 'volume'. Zaktualizowałem kod w pytaniu. Mógłbyś rzucić okiem? Byłoby świetnie. Dziękuję Ci! :) – Macks

+1

Spojrzałem tylko na niego, ale podejrzewam, że nie radzisz sobie z wartościami ujemnymi (zamieniasz się na 'int', który jest 32-bitowy, może mógłbyś użyć' short'?). Pamiętaj, że liczby całkowite ze znakiem java są uzupełnieniem dwójki. – johusman

1

Czy jesteś pewien, że jeden bajt to jedna próbka? W tej specyfikacji formatu wygląda na to, że próbka ma 2 bajty. I nie zapomnij, aby nagłówek pozostał niezmieniony.

WAVE PCM soundfile format

+0

Dziękuję za pomoc. Zaktualizowałem swój kod w pytaniu, ale nadal nie działa. :( – Macks

6

Problem w int typ, rozmiar int w Java jest 4 bajty i wielkość próbki jest 2 bajty

To działało kod:

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

Czy możliwe byłoby również sterowanie głośnością stereo? – nadous

+0

TAK i całkiem łatwo, gdy już wiesz, że PCM to 16-bitowy LL RR LL RR LL RR LL (gdzie każdy znak ma 1 bajt), więc po prostu zwiększam o 4 i ponownie używam Twój kod. – nadous

Powiązane problemy