Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modify volume gain on audio sample buffer

I want to increase a volume on buffer with voice data. The point is I'm using DirectSound and I have one primary and one secondary buffer - all streams mixing is done by hand. In a voice chat all participants can have independent volume levels. I multiply each stream data by a value (gain) and sum it to one buffer. Everything works fine but when I try to multiply data by a value greater than 1.0f - I hear some clipping or what.

I've tried using Audacity effect compressor but this doesn't help reducing the strange noise.

Probably I should modify gain in some other way? Or just use another post-processing algorithm?

UPDATE: Wow, I've just found out interesting thing! I've dumped audio before increasing volume and right after that.

Here is the pic Clipped audio

Sorry for the quality - I think that's how the sound is supposed to appear (I've drawn red line myself). Really looks like values exceed the sample data type. But I cannot understand WHY? My samplebuffer is BYTE but I access it only via short pointer. It is signed but clipping happens even when *ptr is about 15-20 thousand.

like image 757
Dalamber Avatar asked Nov 29 '10 05:11

Dalamber


1 Answers

For every sample - convert it to some larger data type - if you have 16 bit signed samples, they originally fit in SHORT - extract it from the stream, then cast to local double, then multiply, then CLIP, then cast back to SHORT.

It MUST work that way...

I can even provide code sample if needed.

EDIT:

Your picture is exact evidence that you didn't expand to larger type before multiplication - you can't 'capture' clipping condition on SHORT because it will wrap automatically.

short* sampleBuffer;
...
short sample=*sampleBuffer;
double dsample=(double)sample * gain;
if (dsample>32767.0) {dsample=32767.0;}
if (dsample<-32768.0) {dsample=-32768.0;}
*sampleBuffer=(short)dsample;
sampleBuffer++;

And one more EDIT:

if you have several voices - first put them all to double - then GAIN each one - then add them - and CLIP them as the last step.

One more EDIT (+1s are inspiring me):

If you have STEREO, same stuff will work also, just count all the samples x2 i.e.

number of shorts = number of samples * 2.

like image 172
Daniel Mošmondor Avatar answered Oct 21 '22 17:10

Daniel Mošmondor