Re: CoreAudio Level Of Death
Re: CoreAudio Level Of Death
- Subject: Re: CoreAudio Level Of Death
- From: Doug Wyatt <email@hidden>
- Date: Fri, 12 Nov 2004 10:09:13 -0800
On Nov 12, 2004, at 7:16, Urs Heckmann wrote:
Am 11.11.2004 um 17:52 schrieb Doug Wyatt:
No one is actually examining the buffers and deciding that your AU
must be muted (unless it's whatever AU host you're testing with ...
not our sample code).
NaNs are the antimatter of audio, however -- once you've put one out,
it turns every other floating point number it touches into a NaN. So
if there are any filters or regenerating delays in the signal path,
one NaN will silence the chain until that DSP code is reset (unless
it's smart enough to periodically check for NaNs). It could be that
the Apple built-in drivers have some filters, I don't know offhand
and if they do, it probably depends on the sound hardware and whether
you're using the internal speakers vs. line out.
Hmmm...
I was pretty sure I could locate that silence outside of my plugin...
(the silence doesn't go away even if I bypass all filters or any
otherwise recursive structures after it happens)
Yeah, I was saying, it sounds like there is a filter (etc) somewhere in
the signal chain after your AU ... are you using built-in with the
internal speakers?
You can check for NaNs with isnan() (just be aware that it can be
pretty expensive; you probably don't want this check in shipping
code).
According to IEEE specs, all NaNs and Infinities have all bits set in
the exponent, while all denormals have an all zero exponent. Treating
the floats as unsigned integers would allow for extraction of the
exponent and creating comparison results that can be used to find
toxic floats and make them zero. Without branching, of course:
void erase_All_NaNs_Infinities_And_Denormals( float* inSamples, int&
inNumberOfSamples )
{
UInt32* inArrayOfFloats = (UInt32*) inSamples;
for ( int i = 0; i < inNumberOfSamples; i++ )
{
UInt32 sample = *inArrayOfFloats;
UInt32 exponent = sample & 0x7F800000;
// exponent != 0x7F800000 is 0 if NaN or Infinity, otherwise 1
// !exponent is 0 if denormalized, otherwise 1
*inArrayOfFloats++ = sample * ((exponent != 0x7F800000) & !exponent);
}
}
Does that look reasonable? - It could also easily prallelized for
AltiVec...
I havn't found any information about latencies when moving comparison
results from the Condition Register into an Integer Register. I guess
it's a normal 1-cycle latency move? (Or better, I hope so ;-)
Shark or amber/acid would say for sure, but that looks OK, you're not
doing any float<->int conversions. I'd also look to see if there are
hidden branches in the comparison against 0x7F800000.
I'm glad you found a reasonably fast way to do this. The last time I
tried checking every sample was with CodeWarrior's isnan() on a beige
G3 in 1997, and it brought the system to its knees. It turned out to be
sufficient to test the first sample of every buffer...
Doug
_______________________________________________
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