Stitching together audio buffers with potential discontinuity at the boundary I am writing a sound library for my c++ hobby game engine. The sound library mixes music and sound effects into a single buffer that is sent to the audio hardware.

While mixing, any number of source sounds may appear or disappear between two output buffers causing a discontinuity at the border between the buffers.

The discontinuity can be heard as a disturbing high frequency click when the mix is played by the audio hardware.

I have solved this by doing internal bookkeeping of what sound sources are playing and neatly fading sound sources in and out. However this is more involved than it would first seem. The mixing code becomes difficult to read and maintain.

So I would prefer to instead simply handle any discontinuities in the final mix buffer before sending it to the sound card.

I have experimented with a wavelet transform solution which takes an area around the border between two buffers and adjusts any excessively large coefficients until they fit in with the overall distribution.

However that technique seems tricky and introduces a latency to the output because potentially quite old samples have to be updated if the discontinuity carries all the way down to low frequencies...

It would be preferable if the solution would only alter the new buffer and potentially carry over any residual errors at the end of the new buffer to be resolved in the next buffer.

Are there any known techniques for this?

Any help is greatly appreciated!
In 1998 I made a "zero level adjustment click removal" system that shifted the zero level to fix the discontinuity, and this "zero level" was gradually moved back to 0, by decreasing it by 1/2048 of its value every sample. It worked well for low-frequency sounds, but when a high-frequency sound ended abruptly at a large sample value, that created a low-frequency click. I ended up removing the system and simply adding more channels in order to fade out sounds. For this I used a one-pole lowpass filter on all volume envelopes, and when a sound was killed the volume envelope was set to zero and some time was allowed for the fadeout before making the channel available to other sounds. If too many channels were reserved for fading out, the one with the smallest amplitude value was freed to use.

But the thought kept bugging me that if the zero level adjustment would be done only to a lowpass filtered portion of the output, then it might sound better. Purely high-frequency sounds don't really need click removal.