Two handy functions
Mark Smith
mark at maseurope.net
Mon Jan 23 19:16:26 EST 2006
These two functions are from Mark Waddingham (I checked with him that
it was ok to make them public), the result of a 'silver support
incident' (cheap at the price). Probably not everyday must-haves, but
ended my quest to read the sample rate from AIF files.
They convert ieee 10 byte floats to ieee 8 byte floats (which
binaryDecode can cope with) and back again.
Mark
------------------------------------------------------------------------
----------------------------
-- Take a sequence of 10-bytes encoding an extended number, and return
-- a sequence of 8-bytes encoding a double number
function ieeeExtendedToDouble pExtended
local tExtendedSign, tExtendedExponent, tExtendedMantissa,
tExtendedBits
local tDoubleExponent, tDoubleMantissa, tDoubleBits
if the length of pExtended is not 10 then
throw "ieeeerr,Extended number must be 10 bytes long"
end if
-- Step 1: Split the extended number up
get binaryDecode("B80", pExtended, tExtendedBits)
put char 1 of tExtendedBits into tExtendedSign
put char 2 to 16 of tExtendedBits into tExtendedExponent
put char 17 to 80 of tExtendedBits into tExtendedMantissa
-- Step 2: Truncate the fields
-- The exponent is the trickiest because it is stored as a number
relative to
-- the smallest possible exponent which in the case of an extended
number is
-- -16383.
-- Therefore, we take the following steps:
-- . Make sure we have 16-binary digits
-- . Encode as two binary bytes
-- . Decode as a 2-byte integer, most-significant byte first
(network byte-order)
-- . Adjust and clamp to the double exponent range
local tNumericExponent
get binaryDecode("n", binaryEncode("B16", "0" &
tExtendedExponent), tNumericExponent)
subtract 16383 from tNumericExponent
put max(min(tNumericExponent, 2046), -2046) into tNumericExponent
-- IEEE Doubles actually have a normalization requirement for
representation.
-- The Mantissa is taken to be 1.F where F is the binary fraction
encoded in the
-- number. This seems subtlety different from the extended format,
which has no
-- such requirement (it appears). Therefore, we have to find the
leading '1' in the
-- extended mantissa and adjust the exponent accordingly.
-- Of course, if there is no leading 1, then the number is 0
local tLeadingOne
-- Find the leading one, and return zero if there is none
put offset("1", tExtendedMantissa) into tLeadingOne
if tLeadingOne is 0 then
return 0
end if
-- Extract 52-bits for the mantissa, and pad with zeros if we
don't have enough
put char tLeadingOne + 1 to tLeadingOne + 1 + 52 of
tExtendedMantissa into tDoubleMantissa
repeat while the length of tDoubleMantissa < 52
put "0" after tDoubleMantissa
end repeat
-- Adjust the exponent
subtract tLeadingOne - 1 from tDoubleExponent
-- Finish encoding the exponent
get binaryDecode("B16", binaryEncode("n", 1023 +
tNumericExponent), tDoubleExponent)
put char 6 to 16 of tDoubleExponent into tDoubleExponent
-- Now reconstruct the double as bits
put tExtendedSign & tDoubleExponent & tDoubleMantissa into
tDoubleBits
-- And perform the final encoding
return binaryEncode("B64", tDoubleBits)
end ieeeExtendedToDouble
------------------------------------------------------------------------
----------------------------
-- Take a sequence of 8 bytes encoding a double number, and return a
-- sequence of 10-bytes encoding an extended number
function ieeeDoubleToExtended pDouble
local tSign, tExtendedExponent, tExtendedMantissa, tExtendedBits
local tDoubleExponent, tDoubleMantissa, tDoubleBits
if the length of pDouble is not 8 then
throw "ieeeerr,Double number must be 8 bytes long"
end if
get binaryDecode("B64", pDouble, tDoubleBits)
put char 1 of tDoubleBits into tSign
put char 2 to 12 of tDoubleBits into tDoubleExponent
put char 13 to 64 of tDoubleBits into tDoubleMantissa
local tNumericExponent
get binaryDecode("n", binaryEncode("B16", "00000" &
tDoubleExponent), tNumericExponent)
if tNumericExponent is 0 then
put 0 into tNumericExponent
put tDoubleMantissa into tExtendedMantissa
else
add 16383 - 1023 to tNumericExponent
put "1" & tDoubleMantissa into tExtendedMantissa
end if
repeat while the length of tExtendedMantissa < 64
put "0" after tExtendedMantissa
end repeat
get binaryDecode("B16", binaryEncode("n", tNumericExponent),
tExtendedExponent)
put char 2 to 16 of tExtendedExponent into tExtendedExponent
put tSign & tExtendedExponent & tExtendedMantissa into tExtendedBits
return binaryEncode("B80", tExtendedBits)
end ieeeDoubleToExtended
------------------------------------------------------------------------
----------------------------
More information about the use-livecode
mailing list