Re: Native Device Formats
Re: Native Device Formats
- Subject: Re: Native Device Formats
- From: "Mikael Hakman" <email@hidden>
- Date: Tue, 10 Jun 2008 16:40:38 +0200
- Organization: Datakonsulten AB
On Monday, June 09, 2008 10:25 PM, Brian Willoughby wrote:
Your desire to rid yourself of this unfortunate fact while converting
into the float representation is a futile and moot exercise.
Interesting to know what in your opinion is an enlightening fact-based
discussion...
That is not true. There is no lossless mapping from CDDA to float [-1.0,
+1.0], although it is sometimes possible to recreate the lost data under
carefully controlled conditions.
Nonsense! There is nothing special about CD Audio. The signal is represented
by simple plain 16-bit integers that can be lossless mapped into [-1.0,
+1.0] Float32 range. The same is true for 24-bit integers. Lossless means
that you can convert forth and back and then get back the original values,
for all the values in range. The exact bit content of float values, as well
any use of round, modulus, or other functions within the conversion
algorithm is irrelevant. I wrote one possible version of such an algorithm
myself.
I explained that your mapping would result in quantization noise. You
must consider that float does not have infinite resolution. A 32- bit
float has only 24 bits of mantissa. The standard mapping to [-1.0, +1.0)
does not create any extra bits, thus none are lost in the converrsion.
Your mapping creates quantization noise because very long bit sequences
are generated by the conversion, and the intermediate results are
truncated in the float. You're lucky that the conversion back to integer
involves rounding back to the original values, but any processing in the
float world could easily bake in the quantization noise with no hope of
reversing it.
The standard mapping used in the industry, and used by CoreAudio,
involves dividing the integer values by a value like 0x800000, with no
offset. The reason that there is no quantization noise introduced by the
standard mapping is that there is only one significant bit in the
conversion factor, and thus it is equivalent to a bit shift. This also
happens to allow for faster optimizations of the conversion, but it's not
the only reason to choose the standard mapping.
Your mapping involves dividing by 0x7FFFFF as well as adding in an offset
of 1.0/0x800000. Either or both of these operations result in more
significant bits than will fit into a 32-bit float, and many sample
values won't even fit into a 64-bit float. What results is a signal in
the float representation which has quantization distortion, and very
likely also has nonlinear distortion, depending upon whether you apply an
offset and how you do that. Your testing only succeeds because you can
recreate and cancel the quantization noise (and any nonlinear distortion)
that you introduced, but even a simple gain fader applied to the float
values would prevent your paired nonlinear conversions from remaining
lossless. Your suggested mapping is incredibly fragile, and only works
if no processing at all is done to the float values. There's no point in
converting to float if you are not able to apply any processing without
distorting the original signal. Keep in mind that performing math on a
signal which has nonlinear distortion will not produce valid results -
e.g. frequency modulation, FFT, etc.
We are talking about mapping from Float32 to integers for the purpose of
outputting known bit patterns onto the digital wire and for the purpose of
inputting these patterns unchanged. This is because CoreAudio doesn't give
you simple unambiguous integer format by means of which the digital content
on the wire could be controlled and read without the need for any
conversions, neither in applications nor in the drivers. This is what you
get when using ASIO, and such precise control is required in many scientific
and engineering applications.
When using the numbers for computations and processing you should use double
precision values (Float64) in which case all your talk about quantization
distortion is irrelevant. BTW, it's not quantization distortion but loss of
precision due to inadequate bit-width of Float32. It is well know fact, for
at least 50 years, that you should use much better precision in computations
that the final precision required.
I think you misunderstood the purpose of my three examples. They were
not meant as proof of suitability of any given mapping. I was merely
illustrating how to successfully use the standard mapping which CoreAudio
requires.
The proof is in the mathematical representation. The algorithms I
described are all based on the fact that we use the standard mapping, and
once you accept the standard mapping for the reasons above, then you are
forced to use these algorithms, or something basically equivalent.
My intent was to show that the standard mapping is only marginally
unsuitable for digitally-generated signals and dynamics processors which
attempt to avoid clipping. In those cases, I gave examples of algorithms
which work within the constraints of the standard mapping. In other
words, I suggest that you accept the standard mapping, and find ways to
work within the standard without clipping.
Rubbish! "The proof is that if you believe then you are a believer otherwise
your aren't"
By the word "standard" you actually mean current design of CoreAudio. Yes, I
will have to accept that if I decide to port my tools from ASIO to CA. My
question was *why* they designed it in this way.
You're right, Richard does touch on some of the advantages. But those
are mostly beneficial side-effects of the real reason for using the
standard mapping, which I outlined above: To avoid quantization. (Your
belief that your mapping does not introduce quantization noise is
mistaken).
You didn't outline any real reason. You talk much but you don't say anything
relevant.
The important fact is that all DAC and A/D chips use twos-complement
binary integers. As such, all signals have exactly one negative code
which cannot be converted to a positive code. Your desire to rid
yourself of this unfortunate fact while converting into the float
representation is a futile and moot exercise. If anything, you are
exchanging one problem for another, worse problem. Your mapping offers
+1.0 as a valid sample value for synthesized signals, but loses a precise
value for 0. You seem to think this isn't important, but you've not
considered the machine code necessary to work with such numbers.
Standard math libraries are just not going to work with a signal
representation where zero does not have a code value of 0. That alone
puts your mapping at a significant disadvantage to the standard mapping.
We all know that most current DACs use two-complement binary integers, at
least at their external input interface. We also know that there is an even
number of possible bit combination in an integer. This means that you either
accept signal value 0 being between 2 integer values, or you don't use the
most negative value, or you accept that signal covering all values will be
slightly distorted. I asked you, which one interpretation do you prefer, and
which one interpretation do you think is used internally within DAC chips.
As an answer you start calling me names. Thank you.
In other words, I don't see how you have clearly shown your mapping to be
more "intuitive." At first, you asked for a simple [-1.0, +1.0] range,
which I will admit is quite intuitive. But then you modified this to
represent the integer range from 0x800000..0x7FFFFF, which results in a
quite different float world. In the former example, zero is 0.0, but in
your latter example zero is not 0. I don't see how the latter is
intuitive in the least.
Obviously you didn't read what I wrote. 0x8000000 and 0x7FFFFF are
integers - the ones to be sent on the wire.
That represents a signal which is completely impossible in the analog
domain. All proper DACs must implement a filter which has no output at
>fs/2. Your digitally-generated signal has maximum amplitude at fs/2,
which would require an ideal filter that transitions from maximum
amplitude to minimum amplitude instantaneously in the frequency domain.
This is impossible in actual filters in both the digital and analog
domain. Sorry.
Oh please! This was an example selected in such a way that there would be
only few distinct values to show. You can select any frequency you want and
it want change the logic of the example, only that you will have more
distinct values to compute, write and comprehend.
We scientists work often in this way. Logically we extrapolate things to
their limits in order to clearly see or show the effects and consequences,
not because these extreme cases are very probable. I'm sorry you didn't get
that.
But if you were to reduce the frequency of this signal significantly, I
still don't see the importance. The set of signals which can be
represented only by [-1.0, +1.0], but not by [-1.0, +1.0), is
infinitesimal compared to the vast set of real-world signals that people
are working with. Gaining the ability to represent this infinitesimal
set of marginally useful signals in a distorted format has no hope of
outweighing the advantages of the undistorted standard mapping.
The importance or rather relevance is that you can assign value +1.0 to a
variable but it is much more difficult and error prone to assign a value
infinitesimally less than that. Actually it is not infinitesimally less; it
is less by 2 least significant bits from the value +1.0. Furthermore when
using [-1.0, +1.0] mapping the signal value 0 has float representation 0.0
which is good for computations. When using current [-1.0, +0.99999988]
mapping, the signal value 0 is a small negative number.
To a certain extent, I understand your desire for a rigorous proof.
However, I hardly think that the CoreAudio mailing list is an appropriate
place to have the expectation of such a multidisciplinary proof. It is
not possible to prove based on logic alone. An understanding of
mathematics, binary representations, processor machine code, and even
analog circuit analysis is required for complete proof. You're on your
own in those respects.
I asked for a rational explanation why they choose [-1.0, +0.99999988]
mapping instead of more intuitive [-1.0, +1.0]. I have such understanding of
mathematics, binary representations, processor machine code, and even analog
circuit analysis you require. Don't forget to add numerical analysis to the
list. So far a get the following rational explanation:
1. It was done because internal Float32 bit patterns are more elegant when
using [-1.0, 0.99999988] mapping. This explanation isn't good enough for me.
2. The conversion algorithm can be made more efficient (faster) when using
this asymmetrical mapping. This one I can buy.
But then, if you want to give me performance, then give me integer format
not needing any conversions at all. There are a lot of applications and
algorithms that do not need floats at all. Why force all to use float just
because some find it convenient?
/Mikael
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden