Since your profile says you work in embedded systems, I will assume that floating point operations are not always an option.
> So what's the correct method to add these sounds together in my software mixer?
As you guessed, adding and clipping is the correct way to go if you do not want to lose volume on the sources. With samples that are int16_t
, you need to the sum to be int32_t
, then limit and convert back to int16_t
.
> Am I wrong and the correct method is to lower the volume of each by half?
Yes. Halving of volume is somewhat subjective, but what you can see here and there is that halving the volume (loudness) is a decrease of about 10 dB (dividing the power by 10, or the sample values by 3.16). But you mean obviously to lower the sample values by half. This is a 6 dB decrease, a noticeable reduction, but not quite as much as halving the volume (the loudness table there is very useful).
With this 6 dB reduction you will avoid all clipping. But what happens when you want more input channels? For four channels, you would need to divide the input values by 4, that is lowering by 12 dB, thus going to less that half the loudness for each channel.
> Do I need to add a compressor/limiter or some other processing stage to
get the volume and mixing effect I'm trying for?
You want to mix, not clip, and not lose loudness on the input signals. This is not possible, not without some kind of distortion.
As suggested by Mark Ransom, a solution to avoid clipping while not losing as much as 6 dB per channel is to hit somewhere in between "adding and clipping" and "averaging".
That is for two sources: adding, dividing by somewhere between 1 and 2 (reduce the range from [-65536, 65534] to something smaller), then limiting.
If you often clip with this solution and it sounds too harsh, then you might want to soften the limit knee with a compressor. This is a bit more complex, since you need to make the dividing factor dependent on the input power. Try the limiter alone first, and consider the compressor only if you are not happy with the result.