/* there might be a straightforward one-line way to do the below * that's portable and totally safe against roundoff, but I haven't * thought of it. Therefore, we opt on the side of caution */ public static long _book_maptype1_quantvals(static_codebook b) { long vals; if (b.entries < 1) { return(0); } vals = (long)Floor(Pow((float)b.entries, 1f / b.dim)); /* the above *should* be reliable, but we'll not assume that FP is * ever reliable when bitstream sync is at stake; verify via integer * means that vals really is the greatest value of dim for which * vals^b.bim <= b.entries */ /* treat the above as an initial guess */ if (vals < 1) { vals = 1; } while (true) { long acc = 1; long acc1 = 1; int i; for (i = 0; i < b.dim; i++) { if (b.entries / vals < acc) { break; } acc *= vals; if (long.MaxValue / (vals + 1) < acc1) { acc1 = long.MaxValue; } else { acc1 *= vals + 1; } } if (i >= b.dim && acc <= b.entries && acc1 > b.entries) { return(vals); } else { if (i < b.dim || acc > b.entries) { vals--; } else { vals++; } } } }
public static void vorbis_staticbook_destroy(static_codebook b) { if (b.allocedp != 0) { if (b.quantlist != null) { b.quantlist = null; //_ogg_free(b.quantlist); } if (b.lengthlist != null) { b.lengthlist = null; // _ogg_free(b.lengthlist); } //memset(b, 0, sizeof(*b)); //_ogg_free(b); } /* otherwise, it is in static memory */ }
/* unpacks a codebook from the packet buffer into the codebook struct, * readies the codebook auxiliary structures for decode *************/ public static static_codebook vorbis_staticbook_unpack(oggpack_buffer opb) { long i, j; static_codebook s = new static_codebook(); //_ogg_calloc(1, sizeof(*s)); s.allocedp = 1; /* make sure alignment is correct */ if (oggpack_read(opb, 24) != 0x564342) { goto _eofout; } /* first the basic parameters */ s.dim = oggpack_read(opb, 16); s.entries = oggpack_read(opb, 24); if (s.entries == -1) { goto _eofout; } if (ov_ilog((uint)s.dim) + ov_ilog((uint)s.entries) > 24) { goto _eofout; } /* codeword ordering.... length ordered or unordered? */ switch ((int)oggpack_read(opb, 1)) { case 0: { long unused; /* allocated but unused entries? */ unused = oggpack_read(opb, 1); if ((s.entries * (unused != 0 ? 1 : 5) + 7) >> 3 > opb.storage - oggpack_bytes(opb)) { goto _eofout; } /* unordered */ s.lengthlist = new long[s.entries]; //_ogg_malloc(sizeof(*s.lengthlist) * s.entries); /* allocated but unused entries? */ if (unused != 0) { /* yes, unused entries */ for (i = 0; i < s.entries; i++) { if (oggpack_read(opb, 1) != 0) { long num = oggpack_read(opb, 5); if (num == -1) { goto _eofout; } s.lengthlist[i] = num + 1; } else { s.lengthlist[i] = 0; } } } else { /* all entries used; no tagging */ for (i = 0; i < s.entries; i++) { long num = oggpack_read(opb, 5); if (num == -1) { goto _eofout; } s.lengthlist[i] = num + 1; } } break; } case 1: /* ordered */ { long length = oggpack_read(opb, 5) + 1; if (length == 0) { goto _eofout; } s.lengthlist = new long[s.entries]; //_ogg_malloc(sizeof(*s.lengthlist) * s.entries); for (i = 0; i < s.entries;) { long num = oggpack_read(opb, ov_ilog((uint)(s.entries - i))); if (num == -1) { goto _eofout; } if (length > 32 || num > s.entries - i || (num > 0 && (num - 1) >> (int)(length - 1) > 1)) { goto _errout; } if (length > 32) { goto _errout; } for (j = 0; j < num; j++, i++) { s.lengthlist[i] = length; } length++; } } break; default: /* EOF */ goto _eofout; } /* Do we have a mapping to unpack? */ switch ((s.maptype = (int)oggpack_read(opb, 4))) { case 0: /* no mapping */ break; case 1: case 2: /* implicitly populated value mapping */ /* explicitly populated value mapping */ s.q_min = oggpack_read(opb, 32); s.q_delta = oggpack_read(opb, 32); s.q_quant = (int)oggpack_read(opb, 4) + 1; s.q_sequencep = (int)oggpack_read(opb, 1); if (s.q_sequencep == -1) { goto _eofout; } { int quantvals = 0; switch (s.maptype) { case 1: quantvals = (int)(s.dim == 0 ? 0 : _book_maptype1_quantvals(s)); break; case 2: quantvals = (int)(s.entries * s.dim); break; } /* quantized values */ if (((quantvals * s.q_quant + 7) >> 3) > opb.storage - oggpack_bytes(opb)) { goto _eofout; } s.quantlist = new long[quantvals]; //_ogg_malloc(sizeof(*s.quantlist) * quantvals); for (i = 0; i < quantvals; i++) { s.quantlist[i] = oggpack_read(opb, s.q_quant); } if (quantvals != 0 && s.quantlist[quantvals - 1] == -1) { goto _eofout; } } break; default: goto _errout; } /* all set */ return(s); _errout: _eofout: vorbis_staticbook_destroy(s); return(null); }