AIFF's 80-bit sample rate value

Apr 11, 2009 at 4:59pm

AIFF's 80-bit sample rate value

Hi everyone,

Using Javascript’s File functions I’m trying to extract the sample rate from the AIFF file COMM chunk. Looking at the AIFF specification (http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/AIFF/Docs/AIFF-1.3.pdf) this value is stored as an extended 80-bit float. Having done some digging around on the subject I have found that this value is formatted with the first 16-bits representing the exponent and the remaining 64-bits representing the mantissa (as documented here: http://www.cs.trinity.edu/About/The_Courses/cs2321/ieee-fp.html).

Using the readfloat16() and readfloat64() functions I can get the two values. But how do I combine them into one float? And, staying in the JS environment, is there a simpler method?

Thanks,

Adam Jansch

#43317
Apr 11, 2009 at 7:17pm

Just an update…

I should be reading the values in as ints, not floats. But of course Javascript doesn’t work with 64-bit ints at this point (hence the lack of a readint64() function), and so even reading the 64-bit significand value in as two 32-values and adding while bitshifting won’t get me out of this one so easily.

I found a slightly better source regarding these 80-bit monsters, here it is for posterity: http://www.mactech.com/articles/mactech/Vol.06/06.01/SANENormalized/

Adam Jansch

#155352
May 5, 2009 at 10:24am

It has been over a month and I finally figured out how to do this (let it be noted that I haven’t spent the whole month working on this problem!). I am posting my solution for anyone mad enough to want to do the same.

Using info from here (http://www.mactech.com/articles/mactech/Vol.06/06.01/SANENormalized/) I figured out that the first 16-bit block of the 80 represents the bit depth of the second 16-bit block… a little bit of explanation required:

For 44100Hz and 48000Hz files the first 16-bits is always 16398. When 16382 is subtracted from this the result is the bit length of the value that holds the sample rate – in this case 16. For 96000Hz this value is 16399 and for 192000Hz it is 16400.

The next 16-bit value of the 80 represents the base sample rate. As an unsigned 16-bit int it would be 44100 for 44100, 88200 and 176400Hz files, and 48000 for 48000, 96000 and 192000Hz files. This value must be read in via the readbytes() command and reconstructed in Javascript using bit shifting (as readint16() only reads in as signed values).

This is the interesting part… you use the first value retrieved to create a lowest-significant-bit pad for the second value, thus allowing it scale up into the higher sample rates: subtracting 16398 from the first value creates the number of bits of the pad, the bit shift (to the left) the second value by the first and you have the correct file sample rate!

A quick example: for a 96000Hz file the first 16-bit value is 16399. Subtract 16398 from this to get your LSB pad, in this case 1.

Read the second 16-bit as 2 bytes (readbytes(2)), in this case the values 187 and 128. Bit shift 187 left by 8 bits (187 < < 8 = 47872) and add the 128 (48000).

Then bit shift that value using the LSB pad, so 48000 < < 1 = 96000.

The code for this is attached.

#155353
May 5, 2009 at 10:31am

wow this is convoluted… I think there is an interesting historical coding study to do here, to find the motivation of such a convoluted way of doing things…

in all case, bravo!

pa

#155354

You must be logged in to reply to this topic.