c++volumedirectsoundaudio-processingaudacity

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.


Solution

  • 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.