Compressors on 16-bit pcm files
-
- KVRer
- 6 posts since 8 Nov, 2006
Hi,
I have basically finished a multi-track recorder for java, but it has became appearnt that my gain controls do not work like how they should. Here is what I got:
- a 1:1 ratio compressor which processes a 16-bit chunk from 16-bit stereo pcm audio file. The problem is that when I turn the gain down (the volume variable) it starts to produce noticeable static. I need a compressor that does not produce static at low volumes. The variable toModify and toModify2 are two consecutive bytes read straight from a PCM file..
Could anyone point me to any helpers on this specific subject? If you understand java enough (much like c++) and think you know the problem, please let me know. I can't seem to find any information on how to eliminate the static. No matter what I do I can't get it to work.
Thanks in advance
public byte[] getCompressedVolume(byte toModify, byte toModify2){
byte[] arr= new byte[2];
int tmp = (int)toModify << 8;
tmp= (int)((double)tmp * ((double)(volume/MaxVolume)) ) ; //MaxVolume is
//a constant value
arr[0]=(byte)(tmp);
tmp = toModify2;
tmp= (int)((double)tmp *((double)(volume/MaxVolume)) );
arr[1]=(byte)tmp;
return arr;
}
I have basically finished a multi-track recorder for java, but it has became appearnt that my gain controls do not work like how they should. Here is what I got:
- a 1:1 ratio compressor which processes a 16-bit chunk from 16-bit stereo pcm audio file. The problem is that when I turn the gain down (the volume variable) it starts to produce noticeable static. I need a compressor that does not produce static at low volumes. The variable toModify and toModify2 are two consecutive bytes read straight from a PCM file..
Could anyone point me to any helpers on this specific subject? If you understand java enough (much like c++) and think you know the problem, please let me know. I can't seem to find any information on how to eliminate the static. No matter what I do I can't get it to work.
Thanks in advance
public byte[] getCompressedVolume(byte toModify, byte toModify2){
byte[] arr= new byte[2];
int tmp = (int)toModify << 8;
tmp= (int)((double)tmp * ((double)(volume/MaxVolume)) ) ; //MaxVolume is
//a constant value
arr[0]=(byte)(tmp);
tmp = toModify2;
tmp= (int)((double)tmp *((double)(volume/MaxVolume)) );
arr[1]=(byte)tmp;
return arr;
}
- KVRAF
- 9600 posts since 17 Sep, 2002 from Gothenburg Sweden
The problem i think is that 16 bit integer isn't enough room to do that kind of calculations in. If you lower the volume you loose bits. Loose enough bits and it starts to sound like crap.
Convert it to 32 bit float, do your calculations,convert back to 16 bit integer.
Convert it to 32 bit float, do your calculations,convert back to 16 bit integer.
-
- KVRer
- Topic Starter
- 6 posts since 8 Nov, 2006
Java's integer is 32 bit.. more than enough room for 16 bits.. I think there has to be something wrong with the implementation, I just don't know what. Thanks for your response!
- KVRAF
- 16891 posts since 8 Mar, 2005 from Utrecht, Holland
Did you implement a threshold, attack and release for this compressor? Because a sudden change of volume will result in static. And reduction of volume should only be applied relative to the threshold...
We are the KVR collective. Resistance is futile. You will be assimilated. 
My MusicCalc is served over https!!
My MusicCalc is served over https!!
- KVRAF
- 9600 posts since 17 Sep, 2002 from Gothenburg Sweden
My response was'nt entirely accurate.
The problem is that your working with integers.
If you lower the volume of a 16 bit integer file you will loose bits. That is probably the static you're experiencing.
For example if you lower the amplitude in half (out=in*0.5)you only have 8 bit representing the waveform.
The problem is that your working with integers.
If you lower the volume of a 16 bit integer file you will loose bits. That is probably the static you're experiencing.
For example if you lower the amplitude in half (out=in*0.5)you only have 8 bit representing the waveform.
-
- KVRer
- Topic Starter
- 6 posts since 8 Nov, 2006
Just tried the following; it still produces static at low volumes (same as int). Do you think it might be an error with how I apply the compression to each individual byte?
public byte[] getCompressedMasterVolume(byte toModify, byte toModify2){
byte[] arr = new byte[2];
float sample = toModify<<8;
sample = (float)sample* ((float)((float)volume/(float)MaxVolume));
arr[0] = (byte)sample;
sample = toModify2;
sample = (float)sample* ((float)((float)volume/(float)MaxVolume));
arr[1] = (byte) sample;
return arr;
public byte[] getCompressedMasterVolume(byte toModify, byte toModify2){
byte[] arr = new byte[2];
float sample = toModify<<8;
sample = (float)sample* ((float)((float)volume/(float)MaxVolume));
arr[0] = (byte)sample;
sample = toModify2;
sample = (float)sample* ((float)((float)volume/(float)MaxVolume));
arr[1] = (byte) sample;
return arr;
- KVRAF
- 9600 posts since 17 Sep, 2002 from Gothenburg Sweden
Why are you calling it a compressor? As far as i can see all you're doing is volume changes. And why are you trying to it on 2 bytes at a time ? Any special reason for that?
The problem is still the 16 bit representation which isn't enough.
The problem is still the 16 bit representation which isn't enough.
-
- KVRer
- Topic Starter
- 6 posts since 8 Nov, 2006
Okay, I don't know what an attack and release is? Any links on the matter would be much appreciated. I do have a threshold which is represented as a constant MaxVolume=32767 Volume is simply a value between 0 and MaxVolume, which is set by the user based on where they click.
-
- KVRer
- Topic Starter
- 6 posts since 8 Nov, 2006
My understanding was that this is a compressor? My bad, sot of new to the audio stuff effects
all I really want to do is to be able to turn down the voluem from the starting volume->0 without static in the backround.
- KVRAF
- 12615 posts since 7 Dec, 2004
"For example if you lower the amplitude in half (out=in*0.5)you only have 8 bit representing the waveform."
if you cut the amplitude in half, you have 15 bits representing the signal, not 8. you would need to make a cut of 1/256th in order to get only 8 bits accuracy.
if you simply want to adjust the volume, do this:
volume is 0 ... 32767
signal = (signal * volume) / 32768;
this should compile to a register imul and sar, taking two or three cycles, much better than using float.
if you cut the amplitude in half, you have 15 bits representing the signal, not 8. you would need to make a cut of 1/256th in order to get only 8 bits accuracy.
if you simply want to adjust the volume, do this:
volume is 0 ... 32767
signal = (signal * volume) / 32768;
this should compile to a register imul and sar, taking two or three cycles, much better than using float.
Last edited by aciddose on Wed Nov 08, 2006 11:47 am, edited 1 time in total.
- KVRAF
- 9600 posts since 17 Sep, 2002 from Gothenburg Sweden
You're absolutley correct sir! I did think and changed to and from a few times and still messed up.aciddose wrote:"For example if you lower the amplitude in half (out=in*0.5)you only have 8 bit representing the waveform."
if you cut the amplitude in half, you have 15 bits representing the signal, not 8. you would need to make a cut of 1/256th in order to get only 8 bits accuracy.
Still does'nt change the main problem though.
- KVRAF
- 16891 posts since 8 Mar, 2005 from Utrecht, Holland
There only is a rounding error in the least significant bit (representing a loudess of -90dB) so considering "physical" limitations there should be no more quality loss than to be expected. The Windows volume fader does it the same me thinks.
If you've multiplied each sample with the same constant, there should be no static or other audible artefacts louder than -90dB. Maybe it helps to write output PCM of your a WAV file, and compare that to the original. Maybe with visual feedback using an audio editor (zoom in until you can see individual samples) you can see what went wrong.
If you've multiplied each sample with the same constant, there should be no static or other audible artefacts louder than -90dB. Maybe it helps to write output PCM of your a WAV file, and compare that to the original. Maybe with visual feedback using an audio editor (zoom in until you can see individual samples) you can see what went wrong.
We are the KVR collective. Resistance is futile. You will be assimilated. 
My MusicCalc is served over https!!
My MusicCalc is served over https!!
