I'm reading a wav-file to a byte array using this method (shown below). Now that I have it stored inside my byte array, I want to change the sounds volume.
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 request some info on the audio format:
PCM_SIGNED 44100.0 Hz, 16 bit, mono, 2 bytes/frame, little-endian
From physics-class I remembered that you can change the amplitude of a sine-wave by multiplying the sine-value with a number between 0 and 1.
Edit: Updated code for 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;
}
The sound is heavily distorted if I multiply audioSample
with volume
. If I don't and compare both arrays with Arrays.compare(array, audioSample)
I can conclude that the byte-array is being converted correctly to int and the other way around.
Can anybody help me out? What am I getting wrong here? Thank you! :)
Are you sure you're reading 8-bit mono audio? Otherwise one byte does not equal one sample, and you cannot just scale each byte. E.g. if it is 16-bit data you have to parse every pair of bytes as a 16-bit integer, scale that, and then write it back as two bytes.