dapphp/securimage — comment on commit eca4cd8873d2765f091a6e5b409db421a9f0be11
File:  line 0
By Uranium235:

Not sure if you really need to mix more than 2 wav files for this particular purpose. I added sound from a Finnish party to my English spoken NATO alphabet + gaussian white noise (clipped). The result looks like a mess in an audio editor but is still good to understand, although I have occasional clicking (like 1/s) - I guess that's unavoidable without a 2nd pass post processing. But I am not sure what the reason is so far...

I guess 16 and 24 bit _signed_ integers should behave similar to 8 bit with baseline 128. After all they could be transformed into a "signed tinyint". So his formula should work as well, if adjusted accordingly:

/**
* $ai = (signed) integer sample 1st wav
* $bi = (signed) integer sample 2nd wav
* $BitDepth = bit depth of $a and $b (8, 16, 24)
* $result = (signed) integer sample of the mixed wav in $BitDepth bit depth
**/

// transform into the [0,1] domain (float) with 0.5 as baseline = silence
$d = pow(2, $BitDepth);
if ($BitDepth == 8) {
$a = $ai <= 128 ? ($ai - 128) / $d + 0.5 : ($ai - 127) / $d + 0.5;
$b = $bi <= 128 ? ($bi - 128) / $d + 0.5 : ($bi - 127) / $d + 0.5;
} else {
$a = $ai <= 0 ? $ai / $d + 0.5 : ($ai + 1) / $d + 0.5;
$b = $bi <= 0 ? $bi / $d + 0.5 : ($bi + 1) / $d + 0.5;
}

// mix $a and $b
$c = $a < 0.5 && $b < 0.5 ? 2 * $a * $b : 2 * ($a + $b) − 2 * $a * $b − 1;

// Transform back
if ($BitDepth == 8) {
$c = $c <= 0.5 ? ($c - 0.5) * $d + 128 : ($c - 0.5) * $d + 127;
} else {
$c = $c <= 0.5 ? ($c - 0.5) * $d : ($c - 0.5) * $d - 1;
}
$result = (int)round($c);

This should work, although not tested - only on paper in theory. This also takes care of the problem that the range above silence is narrower than below, a fact Viktor missed imho. Thinking about it now, I guess that's where my clicking may be coming from... ;-)
Will implement this in my app now and see what happens...