1 /****************************************************************************
3 * Copyright (C) 2014, Andrew Ward <afward@gmail.com> *
5 * See COPYING for license terms (Ms-PL). *
7 ***************************************************************************/
12 static internal int ilog(int x)
18 x >>= 1; // this is safe because we'll never get here if the sign bit is set
23 static internal uint BitReverse(uint n)
25 return BitReverse(n, 32);
28 static internal uint BitReverse(uint n, int bits)
30 n = ((n & 0xAAAAAAAA) >> 1) | ((n & 0x55555555) << 1);
31 n = ((n & 0xCCCCCCCC) >> 2) | ((n & 0x33333333) << 2);
32 n = ((n & 0xF0F0F0F0) >> 4) | ((n & 0x0F0F0F0F) << 4);
33 n = ((n & 0xFF00FF00) >> 8) | ((n & 0x00FF00FF) << 8);
34 return ((n >> 16) | (n << 16)) >> (32 - bits);
37 // make it so we can twiddle bits in a float...
38 [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)]
41 [System.Runtime.InteropServices.FieldOffset(0)]
43 [System.Runtime.InteropServices.FieldOffset(0)]
47 static internal float ClipValue(float value, ref bool clipped)
50 * There is some magic happening here... IEEE 754 single precision floats are built such that:
51 * 1) The only difference between x and -x is the sign bit (31)
52 * 2) If x is further from 0 than y, the bitwise value of x is greater than the bitwise value of y (ignoring the sign bit)
54 * With those assumptions, we can just look for the bitwise magnitude to be too large...
61 // as a courtesy to those writing out 24-bit and 16-bit samples, our full scale is 0.99999994 instead of 1.0
62 if ((fb.Bits & 0x7FFFFFFF) > 0x3f7fffff) // 0x3f7fffff == 0.99999994f
65 fb.Bits = 0x3f7fffff | (fb.Bits & 0x80000000);
70 static internal float ConvertFromVorbisFloat32(uint bits)
72 // do as much as possible with bit tricks in integer math
73 var sign = ((int)bits >> 31); // sign-extend to the full 32-bits
74 var exponent = (double)((int)((bits & 0x7fe00000) >> 21) - 788); // grab the exponent, remove the bias, store as double (for the call to System.Math.Pow(...))
75 var mantissa = (float)(((bits & 0x1fffff) ^ sign) + (sign & 1)); // grab the mantissa and apply the sign bit. store as float
77 // NB: We could use bit tricks to calc the exponent, but it can't be more than 63 in either direction.
78 // This creates an issue, since the exponent field allows for a *lot* more than that.
79 // On the flip side, larger exponent values don't seem to be used by the Vorbis codebooks...
80 // Either way, we'll play it safe and let the BCL calculate it.
82 // now switch to single-precision and calc the return value
83 return mantissa * (float)System.Math.Pow(2.0, exponent);
86 // this is a no-allocation way to sum an int queue
87 static internal int Sum(System.Collections.Generic.Queue<int> queue)
90 for (int i = 0; i < queue.Count; i++)
92 var temp = queue.Dequeue();