Re: Canonical format max amp limits?
Re: Canonical format max amp limits?
- Subject: Re: Canonical format max amp limits?
- From: Brian Willoughby <email@hidden>
- Date: Wed, 14 Jul 2004 03:27:05 -0700
Hi Steve,
From: Steve Checkoway <email@hidden>
[ On Jul 13, 2004, at 8:13 PM, James Chandler Jr wrote:
[ > double Mul16Bit = 1.0 / 32768.0;
[ > float FloatSample = IntSample * Mul16Bit;
[ > //multiply is usually faster than divide
[ > short IntSample = FloatSample * 32768.0;
[
[ Since you are going for efficiency here, shouldn't you use a float
[ for Mul16Bit?
That wouldn't do any good. In C, all operations involving floating point
types are executed in double precision. Might as well store the full double
scalar in Mul16Bit since it's going to be promoted to double before the
multiply is executed no matter what you do.
[ Also, don't you need to deal with the fact that the range of
[ a 16 bit integer is -32768 to 32767? It seems to me that perhaps
[ something like:
[ const float Mul16BitPos = 1.0f / 32767.0f;
[ const float Mul16BitNeg = 1.0f / 32768.0f;
[ float FloatSample = IntSample * (IntSample < 0 ? Mul16BitNeg :
[ Mul16BitPos);
We've covered this exact topic already on the CoreAudio-API Mailing List.
Check the archives. Some early sample code from Apple, the Daisy example, had
this same mistaken code, and was corrected after I pointed out the error. You
can find the thread by searching for "Willoughby 32767 32768" with the Exact
match algorithm.
Your code is introducing non-linear distortion into the waveform by scaling
the positive half of the wave differently than the negative half.
[ This doesn't seem like so much of an issue for int -> float but what
[ about the other way around? Say that FloatSample = 1.0f. IntSample =
[ 1.0f * 32768.0f; Which would be 32768. Since this is a signed 16 bit
[ integer, would that not be a negative number? Not only negative, but as
[ negative as possible?
You've just proven that you cannot convert to fixed-point by clipping to +1.0f
because that exceeds the range of twos-complement numbers (when normalized as
defined). One solution is to convert to a larger fixed-point number, such as a
32-bit integer register, and then clip to the lower bit depth e.g. to 32767 if
your result is 16-bit. This is easier to handle in fixed-point, because the
actual maximum possible float value is very close to, but less than +1.0f, and
it is different for 16-bit vs. 24-bit (or 20-bit, if your interface is working
with 20-bit D/A).
One really good reason for using the AudioConverter is that you won't make
these kinds of mistakes.
[ Then again, is a difference of one such a big deal that one couldn't
[ simply divide by 32768 and multiply by 32767?
That would add really nasty quantization noise which isn't very musical at
all. Probably wouldn't hear it on your MP3 player, but professionals would run
screaming from Mac OS X and CoreAudio if it were implemented this way.
For example, if all you were doing is digital passthrough, i.e. simple 16-bit
S/P-DIF input -> CoreAudio Float32 -> 16-bit S/P-DIF output, then your code
would not be bit-accurate. Audiophiles would not accept this alteration of a
pure digital bitstream. Also, it would completely ruin Dolby Digital and DTS
bitstreams (or any other non-PCM bitstream). It's rare that a coded bitstream
would be processed this way, but there are some examples.
[ Since CoreAudio provides a generic conversion from one format to
[ another, would it not be simpler if you could tell ahead of time the
[ formats between which you were converting and if they required a simple
[ 16 bit int to 32 bit float conversion like this to simply do it
[ yourself? If the formats don't match the ones you expected then you
[ could go ahead and use the AudioConverter.
It's actually simpler to just always use the AudioConverter.
The DIY method requires that you learn a lot about optimization, and there's
no reason to believe that you'll do a better job than Apple. For example, your
code uses the C language ?: operator, which is equivalent to an if-else
construct, which really messes up the instruction cache. Your code is already
slower than the AudioConverter for that reason alone, not to mention that some
manual unrolling, or use of non-standard compiler options, is needed for top
speed. Add to all the above the fact that AltiVec optimization is not fully
automatic, and that takes performance to an entirely higher level if you know
how to write AltiVec code.
In other words, what you suggest would be a great learning opportunity, but it
is not recommended.
Brian Willoughby
Sound Consulting
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.