2013-01-23 11 views
11

Sto leggendo un file wav su un array di byte utilizzando this method (shown below). Ora che lo ho memorizzato all'interno del mio array di byte, voglio cambiare il volume dei suoni.Audio: modifica del volume dei campioni nell'array di byte

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: Per richiesta di alcune informazioni sul formato audio:

PCM_SIGNED 44100,0 Hz, 16 bit, mono, 2 byte/telaio, little-endian

Da classe fisica Ho ricordato che è possibile modificare l'ampiezza di un'onda sinusoidale moltiplicando il valore seno con un numero compreso tra 0 e 1.

Edit: codice aggiornato per i campioni a 16 bit:

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

Il suono è fortemente distorto se moltiplico audioSample con volume. Se non lo faccio e confronti entrambi gli array con Arrays.compare(array, audioSample), posso concludere che l'array di byte viene convertito correttamente in int e viceversa.

Qualcuno può aiutarmi? Cosa sto sbagliando qui? Grazie! :)

+0

Si potrebbe ottenere risposte migliori su DSP .stackexchange.com – egrunin

+0

1) Per un aiuto migliore, pubblicare un [SSCCE] (http://sscce.org/). 2) Segnala 'audioInputStream.getFormat()'. –

+0

@egrunin Grazie! Posso semplicemente copiarlo e incollarlo lì o quali sono le regole per spostare gli argomenti? – Macks

risposta

7

Sei sicuro di leggere audio mono a 8 bit? Altrimenti un byte non equivale a un campione e non è possibile ridimensionare ogni byte. Per esempio. se si tratta di dati a 16 bit, è necessario analizzare ogni coppia di byte come numero intero a 16 bit, ridimensionarlo e quindi riscriverlo come due byte.

+1

Grazie. Il mio audio ha una dimensione del campione di 16 bit. Ho intenzione di leggere su come convertire correttamente il mio array di byte e di darti il ​​mio feedback una volta che sono riuscito a farlo. – Macks

+0

Ehi. :) Sono finalmente riuscito a convertire correttamente il mio array di byte in int e back. Tuttavia, il mio suono è ancora più pesantemente distorto di prima se moltiplico i miei campioni con 'volume'. Ho aggiornato il codice nella domanda. Potresti dare un'occhiata? Sarebbe grandioso. Grazie! :) – Macks

+1

Gli ho dato una rapida occhiata, ma ho il sospetto che non abbiate a che fare correttamente con i valori negativi (convertite in un 'int', che è 32-bit, forse potreste usare un' short'?). Ricorda che gli interi con segno di java sono il complemento a due. – johusman

1

Sei sicuro che un byte è un campione? In questa specifica di formato sembra che un campione abbia 2 byttes. E non dimenticare di lasciare l'intestazione invariata.

WAVE PCM soundfile format

+0

Grazie per il vostro aiuto. Ho aggiornato il mio codice nella domanda, ma non funziona ancora. :( – Macks

6

Problema nel tipo int, dimensioni di int in Java è di 4 byte e la dimensione del campione è di 2 byte

Questo ha funzionato codice:

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

Sarebbe possibile controllare anche il volume stereo? – nadous

+0

SI e abbastanza facilmente una volta che PCM è a 16 bit LL RR LL RR LL RR LL (dove ogni carattere è 1 byte) quindi incremento solo i 4 e riuso il tuo codice. – nadous

Problemi correlati