HydrogenAudio

Lossy Audio Compression => Opus => Topic started by: nu774 on 2013-09-13 06:39:43

Title: issue on opus_pcm_soft_clip() function
Post by: nu774 on 2013-09-13 06:39:43
I played around a bit on opus_pcm_soft_clip(), and I noticed that it occasionally yields audible noises when I feed simple sine wave with peak above 0dBFS to it.

It seems that opus_pcm_soft_clip() function can yields noise on special cases, where ending of previous frame is not soft clipped but beginning of new frame requires soft clipping.
I'm not a smart guy and not quite familiar with DSP, but as far as I understand:

This filter uses the following transfer function:
f(x) = x (ordinary case)
f(x) = x + ax^2 (soft clipping case, a is chosen so that f(x) = 1 on peak value)

Usually, soft clip is only applied on surrounding points of clipping, from nearest previous zero crossing point to nearest next zero crossing point.
Zero crossing point is used as boundary because two function above can be smoothly connected only at x = 0.

However, on the "special case", this function has to use non zero-crossing point as boundary. This is already specially taken care of so that result is at least "continuous", but it is not "smooth" (differentiable). And it seems to result in widely spread frequency components and audible noise at the boundary point.

I think this can be avoided by processing only until the final zero crossing point, and returning minimum of number of processed samples for each channels. And only when there is no more input, all remaining input can be processed.
This requires slightly more complex book keeping, but it's possible. I don't know it's worth doing, though.

Anyway, test program is attached.
[attachment=7625:softclip.zip]
Title: issue on opus_pcm_soft_clip() function
Post by: jmvalin on 2013-09-14 16:51:57
It seems that opus_pcm_soft_clip() function can yields noise on special cases, where ending of previous frame is not soft clipped but beginning of new frame requires soft clipping.
I'm not a smart guy and not quite familiar with DSP, but as far as I understand:

This filter uses the following transfer function:
f(x) = x (ordinary case)
f(x) = x + ax^2 (soft clipping case, a is chosen so that f(x) = 1 on peak value)


That's correct.

Usually, soft clip is only applied on surrounding points of clipping, from nearest previous zero crossing point to nearest next zero crossing point.
Zero crossing point is used as boundary because two function above can be smoothly connected only at x = 0.

However, on the "special case", this function has to use non zero-crossing point as boundary. This is already specially taken care of so that result is at least "continuous", but it is not "smooth" (differentiable). And it seems to result in widely spread frequency components and audible noise at the boundary point.


Again, that's correct. The case where we don't have a crossing at the beginning of the frame is indeed annoying.

I think this can be avoided by processing only until the final zero crossing point, and returning minimum of number of processed samples for each channels. And only when there is no more input, all remaining input can be processed.
This requires slightly more complex book keeping, but it's possible. I don't know it's worth doing, though.


The problem with returning a smaller number of samples is that it breaks the current Opus API and it can't work for real-time applications (the samples have to go to the soundcard now and not later). So one of the design constraints of opus_pcm_soft_clip() is be completely transparent for the user of the API, while doing a better job than hard clipping. I assume that the glitches you've been talking about are less audible than hard clipping, right? Otherwise it would be a bug. In any case, I'm definitely interested in ways that opus_pcm_soft_clip() can be improved while still returning the same number of samples. So if you have any ideas (or better, patches), please let me know.
Title: issue on opus_pcm_soft_clip() function
Post by: nu774 on 2013-09-14 18:49:24
The problem with returning a smaller number of samples is that it breaks the current Opus API and it can't work for real-time applications (the samples have to go to the soundcard now and not later).

Yeah, considering target of opus (it's a low delay codec anyway), I can imagine non constant unpredictable amount of delay is not acceptable.

So one of the design constraints of opus_pcm_soft_clip() is be completely transparent for the user of the API, while doing a better job than hard clipping. I assume that the glitches you've been talking about are less audible than hard clipping, right? Otherwise it would be a bug.

The amount of harmonic distortions is surely much smaller than hard clipping, but glitches can be also quite annoying.
[attachment=7634:sample.zip]
In the attached archive, test.wav is the original sine wave, and softclipped.wav was processed by this function,  using 256 samples length buffer.
Anyway, given that constraint above, I will not call it a bug.
Title: issue on opus_pcm_soft_clip() function
Post by: nu774 on 2013-09-15 01:26:23
In any case, I'm definitely interested in ways that opus_pcm_soft_clip() can be improved while still returning the same number of samples. So if you have any ideas (or better, patches), please let me know.

Only way I can think of is to use a special transfer function for this special case.
We want a transfer function such that smoothly connected to arbitrary value of x0. Maybe cubic spline or something? I don't know.