dither on export (bug 22)

Effects, Recipes, Interfacing with other software, etc.
Forum rules
If you require help using Audacity, please post on the forum board relevant to your operating system:
Windows
Mac OS X
GNU/Linux and Unix-like
bgravato
Posts: 2080
Joined: Wed Jan 13, 2010 8:56 pm
Operating System: Please select

Re: dither on export (bug 22)

Post by bgravato » Wed Mar 07, 2012 11:22 pm

Converting from float to int by truncating sounds wrong on many levels :) I can't properly understand what truncate means in this context...
Include as much details as you can in your post (Audacity version, Operating System, Equipment used, etc).
Please post your question in the appropriate forum (regarding audacity version and operating system).

steve
Site Admin
Posts: 80677
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu

Re: dither on export (bug 22)

Post by steve » Thu Mar 08, 2012 12:25 am

bgravato wrote:I can't properly understand what truncate means in this context...
rounding down.
9/10 questions are answered in the FREQUENTLY ASKED QUESTIONS (FAQ)

bgravato
Posts: 2080
Joined: Wed Jan 13, 2010 8:56 pm
Operating System: Please select

Re: dither on export (bug 22)

Post by bgravato » Thu Mar 08, 2012 2:11 am

I understand the "idea", my failure to understand is in terms of programming/computing... what could it mean to truncate a float and get an int without float->int conversion?
But never mind I'm just being picky about languistics (Ed influences? hehe)
Include as much details as you can in your post (Audacity version, Operating System, Equipment used, etc).
Please post your question in the appropriate forum (regarding audacity version and operating system).

steve
Site Admin
Posts: 80677
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu

Re: dither on export (bug 22)

Post by steve » Thu Mar 08, 2012 3:07 am

bgravato wrote:what could it mean to truncate a float and get an int without float->int conversion?
It's something like:

Multiply the original 32 bit float value by 2^23 then round down to get the signed 24 bit integer.
In 32 bit float notation, 0 dB is +/- 1
In 24 bit integer notation, 0 dB is +/- 2^23
9/10 questions are answered in the FREQUENTLY ASKED QUESTIONS (FAQ)

bgravato
Posts: 2080
Joined: Wed Jan 13, 2010 8:56 pm
Operating System: Please select

Re: dither on export (bug 22)

Post by bgravato » Thu Mar 08, 2012 3:24 am

steve wrote:
bgravato wrote:what could it mean to truncate a float and get an int without float->int conversion?
It's something like:

Multiply the original 32 bit float value by 2^23 then round down to get the signed 24 bit integer.
In 32 bit float notation, 0 dB is +/- 1
In 24 bit integer notation, 0 dB is +/- 2^23
Multiplying and rounding is not truncating... it's multiplying and rounding ;)
Include as much details as you can in your post (Audacity version, Operating System, Equipment used, etc).
Please post your question in the appropriate forum (regarding audacity version and operating system).

Gale Andrews
Quality Assurance
Posts: 41761
Joined: Fri Jul 27, 2007 12:02 am
Operating System: Windows 10

Re: dither on export (bug 22)

Post by Gale Andrews » Thu Mar 08, 2012 5:04 am

steve wrote:
Gale Andrews wrote:From ImportPCM.cpp:

Code: Select all

// In general, go with the user's preferences.  However, if
// the file is higher-quality, go with a format which preserves
// the quality of the original file.

   if (mFormat != floatSample &&
       sf_subtype_more_than_16_bits(mInfo.format))
      mFormat = floatSample;
It looks like that was written at a time when there was no 24 bit option. Has there ever been such a time?
Those lines were last modified in 2002 (around the time of 1.0.0) when there was no sample format preference. 1.2.0 (2004) had the 24-bit format preference.

steve wrote:It looks to me like 24 bit files are converted to 32 bit float (surprising perhaps, but perhaps not a "bad" thing), but then on Export to 24 bit, the sample values are truncated to 24 bit. Export should properly convert to 24 bit (with dither if enabled) and not just truncated to 24 bit.
Is it possible to be a bit more definitive e.g. by testing this in 1.2.6 and HEAD and comparing sample values like for like?
steve wrote:@Gale - I vaguely recall some fuss a long time ago about something in the manual that said that converting from 32 bit float to 24 bit integer was done by truncating. Do you remember that? Does it relate to this issue?
I think all that was about the Manual stating that Audacity "by default" processed internally at 32-bit, when in truth it always does that irrespective of the sample format of the audio - there is no option.


Gale
________________________________________FOR INSTANT HELP: (Click on Link below)
* * * * * Tips * * * * * Tutorials * * * * * Quick Start Guide * * * * * Audacity Manual

steve
Site Admin
Posts: 80677
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu

Re: dither on export (bug 22)

Post by steve » Thu Mar 08, 2012 3:14 pm

Gale Andrews wrote:Is it possible to be a bit more definitive
Yes, certainly.
Gale Andrews wrote: e.g. by testing this in 1.2.6 and HEAD and comparing sample values like for like?
Sadly no, because there was a different bug in early versions of Audacity that caused 24 bit sample values to be calculated incorrectly and that didn't get fixed until well into 1.3.x versions.


Nyquist code to generate a sequence of every 24 bit sample value (about 6 min 20 seconds duration):

Code: Select all

;; generate ramp with one sample at each 24 bit value
(abs-env 
  (control-srate-abs *sound-srate* 
    (pwlv -1 (/ (power 2 24) *sound-srate*) 1)))

Nyquist code to read sample values in 24 bit format. All values should be integers. The sample values are displayed with one decimal place just to show that they are integers.

Code: Select all

;; print 24 bit value for x number of sample
(setq x 20)
(setq *float-format* "%1.1f")
(setq output "")
(dotimes (i x)
(setq output 
  (format nil "~a~%~a" output
    (* (power 2 23)(snd-fetch s)))))
(print output)
Note: Nyquist runs in 32 bit float. If dither is enabled and the track that it is generating into is less than 32 bit float, the output will be dithered.

Test results:

1) Generate samples into a 32 bit float track.
The samples test as sequential integer values. Example output from 4min into the track :

Code: Select all

2195392.0
2195393.0
2195394.0
2195395.0
2195396.0
2195397.0
2195398.0
2195399.0
2195400.0
2195401.0
2) Generate samples into a 24 bit track, dither = none.
Same results as 1 (as expected). Example output from 1 min into the track:

Code: Select all

-5742608.0
-5742607.0
-5742606.0
-5742605.0
-5742604.0
-5742603.0
-5742602.0
-5742601.0
-5742600.0
-5742599.0
3) Generate samples into a 24 bit track, dither = triangle.
Sample values are still integers (as they must be for 24 bit) but there is a degree of random variation in the values due to the triangle dither.
Example output from 4min into the track :

Code: Select all

2195392.0
2195393.0
2195394.0
2195394.0
2195396.0
2195398.0
2195398.0
2195399.0
2195400.0
2195400.0
4) Generate samples into a 32 bit float track. (the sample values are in sequence).
Export as 24 bit with dither = none.
Import the track and test the sample values.
The sample values are still integers in sequence as expected.
Example output from 4min into the track :

Code: Select all

2195392.0
2195393.0
2195394.0
2195395.0
2195396.0
2195397.0
2195398.0
2195399.0
2195400.0
2195401.0
5) Generate samples into a 32 bit float track. (the sample values are in sequence).
Export as 24 bit with dither = triangle.
Import the track and test the sample values.
The sample values are still integers in sequence. Dither has not been applied.
Example output from 4min into the track (Note that the sample values are identical to test number 4) :

Code: Select all

2195392.0
2195393.0
2195394.0
2195395.0
2195396.0
2195397.0
2195398.0
2195399.0
2195400.0
2195401.0
6) Modify the generator code so that we get some fractional values:

Code: Select all

;; generate ramp from -0.25 to +0.25
(abs-env
  (control-srate-abs *sound-srate* 
      (pwlv -0.25 (/ (power 2 24) *sound-srate*) 0.25)))
Modify the sample reading code so that we get 2 decimal places by changing (setq *float-format* "%1.1f") to (setq *float-format* "%1.2f")
Generate samples into a 32 bit float track.
The samples test as sequential half-integer values. Example output from 4min into the track :

Code: Select all

548848.00
548848.25
548848.50
548848.75
548849.00
548849.25
548849.50
548849.75
548850.00
548850.25
7) Export the track from test 6 as 24 bit with dither = none.
I would have expected integer results rounded to the nearest value but we actually get rounded down values.
Example output from 4min into the track :

Code: Select all

548848.00
548848.00
548848.00
548848.00
548849.00
548849.00
548849.00
548849.00
548850.00
548850.00
8) Export the track from test 6 as 24 bit with dither = Triangle.
We would expect integer results with a degree of randomness to the values due to the dither.
We actually get results identical to test 7 - the values are rounded down.

Code: Select all

548848.00
548848.00
548848.00
548848.00
548849.00
548849.00
548849.00
548849.00
548850.00
548850.00

9) Same as test 8 but with dither = shaped.
Again we get identical results as test 7.


10) Same as test 8 but with dither = rectangle.
Again we get identical results as test 7.


Conclusion:
Exporting 32 bit float audio to "signed 24 bit Integer PCM", using "Other uncompressed files" always rounds down the sample values and dither is never applied.
Last edited by steve on Fri Apr 24, 2015 3:55 pm, edited 2 times in total.
Reason: Correction: replaced "truncated" with "round down".
9/10 questions are answered in the FREQUENTLY ASKED QUESTIONS (FAQ)

steve
Site Admin
Posts: 80677
Joined: Sat Dec 01, 2007 11:43 am
Operating System: Linux *buntu

Re: dither on export (bug 22)

Post by steve » Thu Mar 08, 2012 3:41 pm

Results in Audacity 1.3.12 are the same as Audacity 2.0

Results in Audacity 1.3.10 are slightly different - the values appear to be rounded rather than rounded down. Dither is not applied even when selected in Preferences.
Audacity 1.3.4 also appears to round to the nearest. Dither is not applied even when selected in Preferences.
9/10 questions are answered in the FREQUENTLY ASKED QUESTIONS (FAQ)

Gale Andrews
Quality Assurance
Posts: 41761
Joined: Fri Jul 27, 2007 12:02 am
Operating System: Windows 10

Re: dither on export (bug 22)

Post by Gale Andrews » Fri Mar 09, 2012 6:13 am

steve wrote:The samples test as sequential half-integer values. Example output from 4min into the track :

Code: Select all

    548848.00
    548848.25
    548848.50
    548848.75
    548849.00
7) Export the track from test 6 as 24 bit with dither = none.
I would have expected integer results rounded to the nearest value but we actually get rounded down values.
Example output from 4min into the track :

Code: Select all

    548848.00
    548848.00
    548848.00
    548848.00
    548849.00
Thanks for the tests.

So I'm clear, what values would you expect in 7 (what direction should the rounding go in)? And 1.3.10 and 1.3.4 do this?

I tested 32-bit float silence exported to 24-bit WAV with shaped dither set in Preferences in 1.3.2, 1.3.0 and 1.2.6. All WAV's had no dither applied.

So looks like two separate bugs in addition to #22 (or three if you regard 24-bit quality setting importing 16- or 24-bit files as 32-bit as a bug).


Gale
________________________________________FOR INSTANT HELP: (Click on Link below)
* * * * * Tips * * * * * Tutorials * * * * * Quick Start Guide * * * * * Audacity Manual

PGA
Posts: 695
Joined: Thu Jan 19, 2012 9:16 pm
Operating System: Please select

Re: dither on export (bug 22)

Post by PGA » Fri Mar 09, 2012 7:24 am

Gale Andrews wrote:...what direction should the rounding go in?...
Mathematically speaking "rounding" rounds to the nearest integer. Therefore ".00" through ".49" should round down to ".00" and ".50" through ".99" should round up to next ".00"

Post Reply