In a dither over "dither"

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

I want to add dither to one of my plugins and thought it would be easy to find some generic code for basic, flat TPDF. But it seems I was wrong - not so easy to find. And what I HAVE found sounds terrible. Lots of noise, little benefit. Nothing like Apogee or even most DAW's basic options.

Now, I appreciate that someone like Apogee put a lot of R&D into their dither design - so I don't expect to compete with that BUT I can't even seem to match the performance of basic DAW dither options. It seems there are some magic tricks required for a good dither design.

I started with flat white noise ("RPDF") at various amplitudes. It does recover low level audio BUT the audio modulates the noise - and there is a LOT of noise. And even though quantization noise is greatly reduced the audio has a "gritty" quality to it.

So then I moved on to "flat TPDF" dither (two white noise signals averaged). That seems to cure the modulation problem but is still very noisy and the recovered audio still has "grit" in it - not smooth like commercial dither.

Then I tried high-passed (differentiated) TPDF. It has a more characteristic tape hiss sound to it which is better, IMO, than flat TPDF - but I still hear distortion/quantization noise in the audio even with fairly high dither levels. And the dither itself is still very "loud".

Now, I understand that most commercial dither algorithms use noise shaping to reduce the audibility of dither. But even when noise shaping is turned off the commercial dithers I have tried produce less noise - with less audio distortion - than my TPDF dither attempts.

So, apparently, there is something I'm missing. Flat TPDF dither seems to be preferred by most mastering engineers - and is all I'm looking for - but yet my attempt to produce it sounds terrible. What is the "trick"?

BTW - I am testing this in Wavelab using the "Monitor 16-bit dither" mode which allows easily hearing all the "flavors" of dither. Great tool for this purpose!

Post

The peak-to-peak amplitude of the TPDF dither (flat or not) should be exactly 2 quantization steps.

Also just to sanity check: you should add your TPDF dither to a high-dynamic range (eg. floating point) signal just before it is reduced to 16-bits. If your source audio is already 16-bits, then at that point it's already too late to dither. If you do any further processing after dithering (even changing the volume counts), then you should dither again.

Post

mystran wrote: Sat Sep 12, 2020 4:40 pm The peak-to-peak amplitude of the TPDF dither (flat or not) should be exactly 2 quantization steps.
OK. Will check that to be sure. Could be I'm off somewhere (32768 vs 32767, etc.).
mystran wrote: Sat Sep 12, 2020 4:40 pm Also just to sanity check: you should add your TPDF dither to a high-dynamic range (eg. floating point) signal just before it is reduced to 16-bits.
Yes, dither is being applied before bit reduction. But that doesn't mean I'm sane...

Post

I was already questioning your use case, but now know for sure it is misplaced.
Let dithering be done by the DAW / audio editor, not a plugin. Your plugin emits 32bit floats and is not last in chain saving 16bit audio to disk.
We are the KVR collective. Resistance is futile. You will be assimilated. Image
My MusicCalc is served over https!!

Post

BertKoor wrote: Sat Sep 12, 2020 6:26 pm I was already questioning your use case, but now know for sure it is misplaced.
Let dithering be done by the DAW / audio editor, not a plugin. Your plugin emits 32bit floats and is not last in chain saving 16bit audio to disk.
My plugin is the last processor in the chain - like Ozone and many other limiter plugins that offer dither. It does not truncate the audio to 16-bits, that's true, but it can prepare the signal for it and my customers have asked for it, so...

Post

Fender19 wrote: Sat Sep 12, 2020 8:12 pm my customers have asked for it, so...
“If I had asked customers what they wanted, they would have said faster horses.” - H.Ford
We are the KVR collective. Resistance is futile. You will be assimilated. Image
My MusicCalc is served over https!!

Post

BertKoor wrote: Sat Sep 12, 2020 8:19 pm
Fender19 wrote: Sat Sep 12, 2020 8:12 pm my customers have asked for it, so...
“If I had asked customers what they wanted, they would have said faster horses.” - H.Ford
I didn't ask - THEY did. Give 'em 10 features, they want 20. :roll:

Post

First, what mystran and Bert (both comments) said.

Second, proper TPDF dither should sound exactly like a very tiny bit of smooth white noise summed with your original (full bit depth) signal. Start by generating your dither and listen to it before moving to the next step. The next step would be setting the dither amplitude. Take mystran's advice on level—too little and it won't properly dither, too much and you're just adding excess noise. You've probably seen my video on dither, which illustrates the proper level.

Third, don't worry about advanced dither. Noise-shaped dither is interesting, in some cases it will sound worse, some better, but you'll really only hear the difference between that and TPDF on smaller sample sizes, and it's unlikely your will be smaller than 16-bit. TPDF always sounds natural and unobtrusive (you're doing something wrong if you hear grit), even if the technical specs don't win. Of course, your fast-horse-loving customers may want those tech specs, but you have to produce good TPDF first anyway.

But you really need to be certain your plugin has a good reason to be responsible for the final dithered truncating, and it's something your customers really expect. The only thing it's good for is if you want to print that exact bit depth to a file (with your customers understanding there can be no gain changes after it), or to audition same.

(I tried to add the video link above without having it inline here, but it showed up inline anyway...but might as well include it...) Audio Dither Explained
My audio DSP blog: earlevel.com

Post

earlevel wrote: Tue Sep 15, 2020 4:17 am First, what mystran and Bert (both comments) said.
Thank you for the reply however Mystran sent me some code that I compiled and tested and it does the exact same thing as my code. It does not sound like the "flat, TPDF with noise shaping turned off" dither that my DAW produces. It takes more of it yet produces lower quality results than the DAW's dither.

And, before you suggest, Noise Shaping is not the cause - it's turned off. The issue is the noise signal itself which is somehow different. Perhaps they are using Gaussian noise or some other "PDF", IDK. I measured the Peak to RMS level of my (and Mystran's) noise signal at 8dB while the stock dither is only 6dB and with a lower peak level. The stock dither, even though at a lower level, removes ALL quantization noise (sounds smooth) while ours do not (sounds gritty).

Every limiter plugin I have in my studio - Sonnox, Fabfilter, TDR Labs, Izotope, Toneboosters, etc., as well as the stock limiter plugins in my DAWs (Pro Tools, Wavelab, Logic, Cubase) - ALL have dither options. This is a common feature in such plugins - not sure why it comes as a surprise here.

Post

I suggest breaking it down into steps. TPDF dither is very simple, each step is trivially testable.

Make white noise of a given audible level, listen to it. Check its bounds (bit scope, looking at the waveform, or measuring the amplitude with min/max) to make sure it's the level you expect (-30 dB, whatever). Generate another sample of it and add it to the first—still sound white? (Obviously, it will be twice the peak amplitude, but it should still sound white.)

Set its level for a given bit depth as discussed. Listen (still white) and measure it again to make sure it's the level you think.

Add it to the signal. Not much to go wrong with that, but you can listen again.

Truncate. Listen. It should sound the same as that last listen, as far as your ears can tell. Have a silent passage in your original signal, you'll see just the lsb flipping positive and negative (and zero) randomly. That will confirm you added the right amount of dither.

Now subtract the original, full-resolution signal from that dithered signal—you should get a low level (plus/minus one lsb of the reduced signal) signal that sounds white. No obvious correlation with the original signal, just a steady white sound.

If something goes wrong with any of those steps, it will be obvious, and you'll know where the problem lies.
My audio DSP blog: earlevel.com

Post

Fender19 wrote: Tue Sep 15, 2020 6:10 am
earlevel wrote: Tue Sep 15, 2020 4:17 am First, what mystran and Bert (both comments) said.
Thank you for the reply however Mystran sent me some code that I compiled and tested and it does the exact same thing as my code. It does not sound like the "flat, TPDF with noise shaping turned off" dither that my DAW produces. It takes more of it yet produces lower quality results than the DAW's dither.
This really suggests that the problem is not with the dither noise, but rather something else, because there really isn't anything wrong with the noise itself.

Assuming the plugin itself really doesn't do anything else, then my best bet is that there is some additional processing being done in the DAW between your dither and the truncation. The first thing I would sanity check is whether rendering a 0dBfs sinewave will give you a full-scale 16-bit output. If it doesn't then at least some additional gain is being applied.

Another thing you can do for debugging is to truncate the signal yourself, record in 32-bit float (or boost it up so that the truncation in rendering is no longer relevant) and normalize to see what the results look like. If this works and rendering in DAW doesn't, then again you know that the truncation is not being done as expected.

Post

Here is auto-correlation plot for the dither from my code (before truncation) using the approach that takes a high quality 32-bit hash of a counter, splits it into two 16-bit values, scales each to floating point unity and then subtracts one from the other (so DC offsets cancel):
Screen Shot 2020-09-15 at 11.57.39.png
This is one channel from generating stereo with interleaved hashes, but mono version or the other channel looks exactly the same (other than the slight noise in the plot obviously being different). So the quality of the noise is certainly not a problem either.
You do not have the required permissions to view the files attached to this post.

Post

mystran wrote: Tue Sep 15, 2020 9:02 am Here is auto-correlation plot for the dither from my code (before truncation) using the approach that takes a high quality 32-bit hash of a counter, splits it into two 16-bit values, scales each to floating point unity and then subtracts one from the other (so DC offsets cancel):

Screen Shot 2020-09-15 at 11.57.39.png

This is one channel from generating stereo with interleaved hashes, but mono version or the other channel looks exactly the same (other than the slight noise in the plot obviously being different). So the quality of the noise is certainly not a problem either.
Well, that is some very nice looking noise!

Post

mystran wrote: Tue Sep 15, 2020 8:45 am Assuming the plugin itself really doesn't do anything else, then my best bet is that there is some additional processing being done in the DAW between your dither and the truncation. The first thing I would sanity check is whether rendering a 0dBfs sinewave will give you a full-scale 16-bit output. If it doesn't then at least some additional gain is being applied.
The plugin I am testing this dither code in is an I/O shell that does nothing else. ProcessDoubleReplacing(nFrames) takes the input -> sends it directly to the dither code -> then returns it directly to the output.

I have tested other plugins that produce dither and they all work properly in my test setup in Wavelab. So yes, there must be something wrong somewhere in MY plugin. However the measured output level from my dither plugin running in Wavelab is -90.3dBFS which is exactly the same as the measured output from the DAW dither plugin (-90.3dBFS) - yet one produces perfect dithering while the other barely nicks the signal. If I turn off the dither signal in my plugin - allowing just the audio to pass through - it returns unity gain. So there does not appear to be a level error anywhere in my plugin or the DAW interface.

I'm baffled.

In the meantime, I have noted that many commercial dither plugins offer options for dither LEVEL - (not noise shaping level, DITHER level). One plugin, from Goodhertz, offers THREE different levels:

1) "Low - Does not fully eliminate quantization distortion or dither modulation, but can be a good choice for audio that already contains some natural noise."
2) "Optimal - Excellent quantization performance with a lower noise floor. Recommended for most situations."
3) "High - Complete elimination of quantization distortion with a slightly higher noise floor."

So maybe what Mystran and others have presented here is the "low" dither option - the mathematical minimum for signal recovery below 1 lsb - whereas I am listening for complete dither removal (the "High" option)? I have found that flat dither we are discussing here does not "completely remove" the quantization noise unless it's peak level is at or above -84dBFS.

But again, that doesn't explain the Steinberg "flat, TPDF" dither that produces a -90.3dBFS peak signal yet completely removes quantization noise (even with noise shaping turned off). How is that possible? Are there "noise shaping/cancellation" methods that reduce quantization noise but do not alter the spectrum? Maybe THAT's what they're doing?

I agree, none of this makes sense. I have written dozens of plugins and never come across a weird level issue like this. I'm baffled.
Last edited by Fender19 on Tue Sep 15, 2020 10:11 pm, edited 1 time in total.

Post

Fender19 wrote: Tue Sep 15, 2020 7:42 pm So maybe what Mystran and others here have presented here is the "low" dither option
No. It's the correct TPDF dither (and likely what these plugins call "high"), but some people are misguided and insist that having either some quantization noise or at least noise modulation left is somehow supposed to be "better" than having a consistent correct noise floor, so there are a bunch of plugins that provide such options.

Mathematically RPDF at 1lsb is required to make the first moment (mean) of the quantization error independent of the input signal and TPDF at 2lsb is required to make the second moment (variance) independent. Higher moments can be similarly treated, but research on the topic has concluded that neither human sight nor hearing are sensitive to such higher moments and therefore TPDF can be considered optimal dither for both images and audio. Whether you then want to shape that noise further is an orthogonal subject.

Either way, at this point I feel like we've established that it probably isn't the dither itself that is the actual problem. Sadly without access to neither the plugin or the complete source code, it is somewhat difficult for anyone to help you further.

Have you looked at the output of your plugin in a spectrum analyzer before the actual truncation takes place? At this point there should not be any quantization distortion, but rather just a smooth noise-floor about 112dB below full-scale. It might also make sense to check the output in oscilloscope (also before quantization) to make sure that the noise itself looks smooth.

Post Reply

Return to “DSP and Plugin Development”