Declick/Anticlick algorithm

Started by bass, December 17, 2015, 21:20:40

Previous topic - Next topic

bass

Hi,

I'm writing a mod player in C# and I wonder how to avoid clicks when there are volume changes or changes in sample positions (like new note).
I already tried crossfade for sample positions and volume ramping for vol changes, it seems to work but it's much processing to generate a crossfade, because I have to calculate the next 256 samples for the current note to make a crossfade with the new note.
Does anyone have a fast and good declicking algorithm?
How is this solved in OpenMPT?
Thx!

Saga Musix

#1
It's fairly simple and part of the regular volume calculations. While there is some ramping going on, OpenMPT memorizes the current and new volume and computes the slope between the new values (which depends on the ramp length). The volume is then decreased or increased by this slope value on every mixed sampling point.

Mixing samples is a linear process so you are overcomplicating things by actually implementing a crossfade. It is enough to just fade out the old channel and fade in the new channel. At least in the case of mixing ITs or other module types with New Note Actions it's just easier to put the old note on a virtual channel where it fades out, and the new note on the new pattern channel.

Alternatively, you can stop mixing the old sample but store its last DC offset (i.e. the last mixed sampling point) for each channel (left and right) and the build a slope from that point to zero. This is basically what OpenMPT does when a note ends on its own but does not end with a zero crossing. In this case it does not use a linear slope though.
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.

bass

Thank you very much for the detailed explanation!
I meant a linear crossfade like you described. So I think I am doing it correctly then.
I've got three declick positions in my code, one for volume changes, one for sample pos changes and one for pan changes. Perhaps I can optimize things there... I don't know.

A question to the algorithm in OpenMPT:
Doesn't it sound bad when you just take the last sample value (lets say we are mixing mono) and build a slope to zero?
And why not a linear slope?

Saga Musix

Quote from: bass on December 17, 2015, 22:01:14I've got three declick positions in my code, one for volume changes, one for sample pos changes and one for pan changes. Perhaps I can optimize things there... I don't know.
Since panning is just another form of volume control, you can actually reduce the complexity of the code by just calculating the slope after calculating the total channel volume, which should include any panning.

Quote from: bass on December 17, 2015, 22:01:14Doesn't it sound bad when you just take the last sample value (lets say we are mixing mono) and build a slope to zero?
No, it basically sounds like "nothing", which is exactly the goal of this approach. As said this approach is just used at the end of a sample, not when cutting it. For normal volume changes it is of no use, but I can imagine that this would also work well in the case of stopped samples, because it would really stop the sample, so you can be sure that no further sample content is being played. I have never tested if it would work but it sounds plausible to me, and I think that some players actually use this approach.

Quote from: bass on December 17, 2015, 22:01:14And why not a linear slope?
It's not documented but I guess it's just to have a quicker decay while still not introducing any pops.
» No support, bug reports, feature requests via private messages - they will not be answered. Use the forums and the issue tracker so that everyone can benefit from your post.

bass

For some reasons I'm mixing every channel "mono" without left and right sample values. At the end I mix all channels together and make it stereo with the channel pan positions. That's easier for me to generate and manipulate the final mix. But I will have a look to my source code if I can optimize it :)
Thanks for your fast and helpful answers!