_source/LDandFix.c

/*
    File:       LDandFix.c
 
    Contains:   Routines demonstrating how to convert to and from long double and Fixed types.
 
    Written by: Mark Cookson    
 
    Copyright:  Copyright © 1996-1999 by Apple Computer, Inc., All Rights Reserved.
 
                You may incorporate this Apple sample source code into your program(s) without
                restriction. This Apple sample source code has been provided "AS IS" and the
                responsibility for its operation is yours. You are not permitted to redistribute
                this Apple sample source code as "Apple sample source code" after having made
                changes. If you're going to re-distribute the source, we require that you make
                it clear in the source that the code was descended from Apple sample source
                code, but that you've made changes.
 
    Change History (most recent first):
                8/31/1999   Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
                
 
*/
 
#include "LDandFix.h"
 
Fixed           ASoundLongDoubleToFix   (long double theLD)
{
/*
    A Fixed number is of the type 12345.67890.  It is 32 bits in size with the
    high order bits representing the significant value (that before the point)
    and the lower 16 bits representing the fractional part of the number.
 
    The Sound Manager further complicates matters by using Fixed numbers, but
    needing to represent numbers larger than what the Fixed is capable of.
 
    To do this the Sound Manager treats the sign bit as having the value 32768
    which will cause any number greater or equal to 32768 to look like it is
    negative.
 
    This routine is designed to "do the right thing" and convert any long double
    into the Fixed number it represents.
 
    long double is the input type because AIFF files use extended80 numbers and
    there are routines that will convert from an extended80 to a long double.
 
    A long double has far greater precision than a Fixed, so any number whose
    significant or fraction is larger than 65535 will not convert correctly.
*/
 
    unsigned long   theResult       = 0;
    unsigned short  theSignificant  = 0,
                    theFraction     = 0;
 
    if (theLD < kMaxValue) {
        theSignificant = theLD;
        theFraction = theLD - theSignificant;
        if (theFraction > kMaxValue) {
            /* Won't be able to convert */
            theSignificant  = 0;
            theFraction     = 0;
        }
    }
 
    theResult |= theSignificant;
    theResult = theResult << (sizeof (unsigned short) * kBitsPerByte);
    theResult |= theFraction;
 
    return theResult;
}
 
/*
    I'm still trying to figure out why I need the correction factor, but the
    number returned by this function is only for our own internal calculation
    of buffer sizing so we can afford to loose a little precision in the
    fraction.
*/
long double     ASoundFixToLongDouble   (Fixed theFixed)
{
    long double     theResult   = 0.0;
    unsigned short  high16Bits  = 0,
                    low16Bits   = 0;
 
    high16Bits = theFixed >> (sizeof (unsigned short) * kBitsPerByte);
    low16Bits = theFixed + 0x496E;      /* Correction factor */
 
    theResult = high16Bits + (low16Bits * kFraction);
 
    return theResult;
}