in Frameworks/AudioToolbox/stb_vorbis.c [3663:4221]
static int start_decoder(vorb *f)
{
uint8 header[6], x, y;
int len, i, j, k, max_submaps = 0;
int longest_floorlist = 0;
// first page, first packet
if (!start_page(f)) return FALSE;
// validate page flag
if (!(f->page_flag & PAGEFLAG_first_page)) return error(f, VORBIS_invalid_first_page);
if (f->page_flag & PAGEFLAG_last_page) return error(f, VORBIS_invalid_first_page);
if (f->page_flag & PAGEFLAG_continued_packet) return error(f, VORBIS_invalid_first_page);
// check for expected packet length
if (f->segment_count != 1) return error(f, VORBIS_invalid_first_page);
if (f->segments[0] != 30) return error(f, VORBIS_invalid_first_page);
// read packet
// check packet header
if (get8(f) != VORBIS_packet_id) return error(f, VORBIS_invalid_first_page);
if (!getn(f, header, 6)) return error(f, VORBIS_unexpected_eof);
if (!vorbis_validate(header)) return error(f, VORBIS_invalid_first_page);
// vorbis_version
if (get32(f) != 0) return error(f, VORBIS_invalid_first_page);
f->channels = get8(f); if (!f->channels) return error(f, VORBIS_invalid_first_page);
if (f->channels > STB_VORBIS_MAX_CHANNELS) return error(f, VORBIS_too_many_channels);
f->sample_rate = get32(f); if (!f->sample_rate) return error(f, VORBIS_invalid_first_page);
get32(f); // bitrate_maximum
get32(f); // bitrate_nominal
get32(f); // bitrate_minimum
x = get8(f);
{
int log0, log1;
log0 = x & 15;
log1 = x >> 4;
f->blocksize_0 = 1 << log0;
f->blocksize_1 = 1 << log1;
if (log0 < 6 || log0 > 13) return error(f, VORBIS_invalid_setup);
if (log1 < 6 || log1 > 13) return error(f, VORBIS_invalid_setup);
if (log0 > log1) return error(f, VORBIS_invalid_setup);
}
// framing_flag
x = get8(f);
if (!(x & 1)) return error(f, VORBIS_invalid_first_page);
// second packet!
if (!start_page(f)) return FALSE;
if (!start_packet(f)) return FALSE;
do {
len = next_segment(f);
skip(f, len);
f->bytes_in_seg = 0;
} while (len);
// third packet!
if (!start_packet(f)) return FALSE;
#ifndef STB_VORBIS_NO_PUSHDATA_API
if (IS_PUSH_MODE(f)) {
if (!is_whole_packet_present(f, TRUE)) {
// convert error in ogg header to write type
if (f->error == VORBIS_invalid_stream)
f->error = VORBIS_invalid_setup;
return FALSE;
}
}
#endif
crc32_init(); // always init it, to avoid multithread race conditions
if (get8_packet(f) != VORBIS_packet_setup) return error(f, VORBIS_invalid_setup);
for (i = 0; i < 6; ++i) header[i] = get8_packet(f);
if (!vorbis_validate(header)) return error(f, VORBIS_invalid_setup);
// codebooks
f->codebook_count = get_bits(f, 8) + 1;
f->codebooks = (Codebook *)setup_malloc(f, sizeof(*f->codebooks) * f->codebook_count);
if (f->codebooks == NULL) return error(f, VORBIS_outofmem);
memset(f->codebooks, 0, sizeof(*f->codebooks) * f->codebook_count);
for (i = 0; i < f->codebook_count; ++i) {
uint32 *values;
int ordered, sorted_count;
int total = 0;
uint8 *lengths;
Codebook *c = f->codebooks + i;
CHECK(f);
x = get_bits(f, 8); if (x != 0x42) return error(f, VORBIS_invalid_setup);
x = get_bits(f, 8); if (x != 0x43) return error(f, VORBIS_invalid_setup);
x = get_bits(f, 8); if (x != 0x56) return error(f, VORBIS_invalid_setup);
x = get_bits(f, 8);
c->dimensions = (get_bits(f, 8) << 8) + x;
x = get_bits(f, 8);
y = get_bits(f, 8);
c->entries = (get_bits(f, 8) << 16) + (y << 8) + x;
ordered = get_bits(f, 1);
c->sparse = ordered ? 0 : get_bits(f, 1);
if (c->dimensions == 0 && c->entries != 0) return error(f, VORBIS_invalid_setup);
if (c->sparse)
lengths = (uint8 *)setup_temp_malloc(f, c->entries);
else
lengths = c->codeword_lengths = (uint8 *)setup_malloc(f, c->entries);
if (!lengths) return error(f, VORBIS_outofmem);
if (ordered) {
int current_entry = 0;
int current_length = get_bits(f, 5) + 1;
while (current_entry < c->entries) {
int limit = c->entries - current_entry;
int n = get_bits(f, ilog(limit));
if (current_entry + n >(int) c->entries) { return error(f, VORBIS_invalid_setup); }
memset(lengths + current_entry, current_length, n);
current_entry += n;
++current_length;
}
}
else {
for (j = 0; j < c->entries; ++j) {
int present = c->sparse ? get_bits(f, 1) : 1;
if (present) {
lengths[j] = get_bits(f, 5) + 1;
++total;
if (lengths[j] == 32)
return error(f, VORBIS_invalid_setup);
}
else {
lengths[j] = NO_CODE;
}
}
}
if (c->sparse && total >= c->entries >> 2) {
// convert sparse items to non-sparse!
if (c->entries > (int)f->setup_temp_memory_required)
f->setup_temp_memory_required = c->entries;
c->codeword_lengths = (uint8 *)setup_malloc(f, c->entries);
if (c->codeword_lengths == NULL) return error(f, VORBIS_outofmem);
memcpy(c->codeword_lengths, lengths, c->entries);
setup_temp_free(f, lengths, c->entries); // note this is only safe if there have been no intervening temp mallocs!
lengths = c->codeword_lengths;
c->sparse = 0;
}
// compute the size of the sorted tables
if (c->sparse) {
sorted_count = total;
}
else {
sorted_count = 0;
#ifndef STB_VORBIS_NO_HUFFMAN_BINARY_SEARCH
for (j = 0; j < c->entries; ++j)
if (lengths[j] > STB_VORBIS_FAST_HUFFMAN_LENGTH && lengths[j] != NO_CODE)
++sorted_count;
#endif
}
c->sorted_entries = sorted_count;
values = NULL;
CHECK(f);
if (!c->sparse) {
c->codewords = (uint32 *)setup_malloc(f, sizeof(c->codewords[0]) * c->entries);
if (!c->codewords) return error(f, VORBIS_outofmem);
}
else {
unsigned int size;
if (c->sorted_entries) {
c->codeword_lengths = (uint8 *)setup_malloc(f, c->sorted_entries);
if (!c->codeword_lengths) return error(f, VORBIS_outofmem);
c->codewords = (uint32 *)setup_temp_malloc(f, sizeof(*c->codewords) * c->sorted_entries);
if (!c->codewords) return error(f, VORBIS_outofmem);
values = (uint32 *)setup_temp_malloc(f, sizeof(*values) * c->sorted_entries);
if (!values) return error(f, VORBIS_outofmem);
}
size = c->entries + (sizeof(*c->codewords) + sizeof(*values)) * c->sorted_entries;
if (size > f->setup_temp_memory_required)
f->setup_temp_memory_required = size;
}
if (!compute_codewords(c, lengths, c->entries, values)) {
if (c->sparse) setup_temp_free(f, values, 0);
return error(f, VORBIS_invalid_setup);
}
if (c->sorted_entries) {
// allocate an extra slot for sentinels
c->sorted_codewords = (uint32 *)setup_malloc(f, sizeof(*c->sorted_codewords) * (c->sorted_entries + 1));
if (c->sorted_codewords == NULL) return error(f, VORBIS_outofmem);
// allocate an extra slot at the front so that c->sorted_values[-1] is defined
// so that we can catch that case without an extra if
c->sorted_values = (int *)setup_malloc(f, sizeof(*c->sorted_values) * (c->sorted_entries + 1));
if (c->sorted_values == NULL) return error(f, VORBIS_outofmem);
++c->sorted_values;
c->sorted_values[-1] = -1;
compute_sorted_huffman(c, lengths, values);
}
if (c->sparse) {
setup_temp_free(f, values, sizeof(*values)*c->sorted_entries);
setup_temp_free(f, c->codewords, sizeof(*c->codewords)*c->sorted_entries);
setup_temp_free(f, lengths, c->entries);
c->codewords = NULL;
}
compute_accelerated_huffman(c);
CHECK(f);
c->lookup_type = get_bits(f, 4);
if (c->lookup_type > 2) return error(f, VORBIS_invalid_setup);
if (c->lookup_type > 0) {
uint16 *mults;
c->minimum_value = float32_unpack(get_bits(f, 32));
c->delta_value = float32_unpack(get_bits(f, 32));
c->value_bits = get_bits(f, 4) + 1;
c->sequence_p = get_bits(f, 1);
if (c->lookup_type == 1) {
c->lookup_values = lookup1_values(c->entries, c->dimensions);
}
else {
c->lookup_values = c->entries * c->dimensions;
}
if (c->lookup_values == 0) return error(f, VORBIS_invalid_setup);
mults = (uint16 *)setup_temp_malloc(f, sizeof(mults[0]) * c->lookup_values);
if (mults == NULL) return error(f, VORBIS_outofmem);
for (j = 0; j < (int)c->lookup_values; ++j) {
int q = get_bits(f, c->value_bits);
if (q == EOP) { setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_invalid_setup); }
mults[j] = q;
}
#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
if (c->lookup_type == 1) {
int len, sparse = c->sparse;
float last = 0;
// pre-expand the lookup1-style multiplicands, to avoid a divide in the inner loop
if (sparse) {
if (c->sorted_entries == 0) goto skip;
c->multiplicands = (codetype *)setup_malloc(f, sizeof(c->multiplicands[0]) * c->sorted_entries * c->dimensions);
}
else
c->multiplicands = (codetype *)setup_malloc(f, sizeof(c->multiplicands[0]) * c->entries * c->dimensions);
if (c->multiplicands == NULL) { setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); }
len = sparse ? c->sorted_entries : c->entries;
for (j = 0; j < len; ++j) {
unsigned int z = sparse ? c->sorted_values[j] : j;
unsigned int div = 1;
for (k = 0; k < c->dimensions; ++k) {
int off = (z / div) % c->lookup_values;
float val = mults[off];
val = mults[off] * c->delta_value + c->minimum_value + last;
c->multiplicands[j*c->dimensions + k] = val;
if (c->sequence_p)
last = val;
if (k + 1 < c->dimensions) {
if (div > UINT_MAX / (unsigned int)c->lookup_values) {
setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values);
return error(f, VORBIS_invalid_setup);
}
div *= c->lookup_values;
}
}
}
setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values);
c->lookup_type = 2;
}
else
#endif
{
float last = 0;
CHECK(f);
c->multiplicands = (codetype *)setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values);
if (c->multiplicands == NULL) { setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); }
for (j = 0; j < (int)c->lookup_values; ++j) {
float val = mults[j] * c->delta_value + c->minimum_value + last;
c->multiplicands[j] = val;
if (c->sequence_p)
last = val;
}
setup_temp_free(f, mults, sizeof(mults[0])*c->lookup_values);
}
#ifndef STB_VORBIS_DIVIDES_IN_CODEBOOK
skip : ;
#endif
CHECK(f);
}
CHECK(f);
}
// time domain transfers (notused)
x = get_bits(f, 6) + 1;
for (i = 0; i < x; ++i) {
uint32 z = get_bits(f, 16);
if (z != 0) return error(f, VORBIS_invalid_setup);
}
// Floors
f->floor_count = get_bits(f, 6) + 1;
f->floor_config = (Floor *)setup_malloc(f, f->floor_count * sizeof(*f->floor_config));
if (f->floor_config == NULL) return error(f, VORBIS_outofmem);
for (i = 0; i < f->floor_count; ++i) {
f->floor_types[i] = get_bits(f, 16);
if (f->floor_types[i] > 1) return error(f, VORBIS_invalid_setup);
if (f->floor_types[i] == 0) {
Floor0 *g = &f->floor_config[i].floor0;
g->order = get_bits(f, 8);
g->rate = get_bits(f, 16);
g->bark_map_size = get_bits(f, 16);
g->amplitude_bits = get_bits(f, 6);
g->amplitude_offset = get_bits(f, 8);
g->number_of_books = get_bits(f, 4) + 1;
for (j = 0; j < g->number_of_books; ++j)
g->book_list[j] = get_bits(f, 8);
return error(f, VORBIS_feature_not_supported);
}
else {
Point p[31 * 8 + 2];
Floor1 *g = &f->floor_config[i].floor1;
int max_class = -1;
g->partitions = get_bits(f, 5);
for (j = 0; j < g->partitions; ++j) {
g->partition_class_list[j] = get_bits(f, 4);
if (g->partition_class_list[j] > max_class)
max_class = g->partition_class_list[j];
}
for (j = 0; j <= max_class; ++j) {
g->class_dimensions[j] = get_bits(f, 3) + 1;
g->class_subclasses[j] = get_bits(f, 2);
if (g->class_subclasses[j]) {
g->class_masterbooks[j] = get_bits(f, 8);
if (g->class_masterbooks[j] >= f->codebook_count) return error(f, VORBIS_invalid_setup);
}
for (k = 0; k < 1 << g->class_subclasses[j]; ++k) {
g->subclass_books[j][k] = get_bits(f, 8) - 1;
if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup);
}
}
g->floor1_multiplier = get_bits(f, 2) + 1;
g->rangebits = get_bits(f, 4);
g->Xlist[0] = 0;
g->Xlist[1] = 1 << g->rangebits;
g->values = 2;
for (j = 0; j < g->partitions; ++j) {
int c = g->partition_class_list[j];
for (k = 0; k < g->class_dimensions[c]; ++k) {
g->Xlist[g->values] = get_bits(f, g->rangebits);
++g->values;
}
}
// precompute the sorting
for (j = 0; j < g->values; ++j) {
p[j].x = g->Xlist[j];
p[j].y = j;
}
qsort(p, g->values, sizeof(p[0]), point_compare);
for (j = 0; j < g->values; ++j)
g->sorted_order[j] = (uint8)p[j].y;
// precompute the neighbors
for (j = 2; j < g->values; ++j) {
int low, hi;
neighbors(g->Xlist, j, &low, &hi);
g->neighbors[j][0] = low;
g->neighbors[j][1] = hi;
}
if (g->values > longest_floorlist)
longest_floorlist = g->values;
}
}
// Residue
f->residue_count = get_bits(f, 6) + 1;
f->residue_config = (Residue *)setup_malloc(f, f->residue_count * sizeof(f->residue_config[0]));
if (f->residue_config == NULL) return error(f, VORBIS_outofmem);
memset(f->residue_config, 0, f->residue_count * sizeof(f->residue_config[0]));
for (i = 0; i < f->residue_count; ++i) {
uint8 residue_cascade[64];
Residue *r = f->residue_config + i;
f->residue_types[i] = get_bits(f, 16);
if (f->residue_types[i] > 2) return error(f, VORBIS_invalid_setup);
r->begin = get_bits(f, 24);
r->end = get_bits(f, 24);
if (r->end < r->begin) return error(f, VORBIS_invalid_setup);
r->part_size = get_bits(f, 24) + 1;
r->classifications = get_bits(f, 6) + 1;
r->classbook = get_bits(f, 8);
if (r->classbook >= f->codebook_count) return error(f, VORBIS_invalid_setup);
for (j = 0; j < r->classifications; ++j) {
uint8 high_bits = 0;
uint8 low_bits = get_bits(f, 3);
if (get_bits(f, 1))
high_bits = get_bits(f, 5);
residue_cascade[j] = high_bits * 8 + low_bits;
}
r->residue_books = (short(*)[8]) setup_malloc(f, sizeof(r->residue_books[0]) * r->classifications);
if (r->residue_books == NULL) return error(f, VORBIS_outofmem);
for (j = 0; j < r->classifications; ++j) {
for (k = 0; k < 8; ++k) {
if (residue_cascade[j] & (1 << k)) {
r->residue_books[j][k] = get_bits(f, 8);
if (r->residue_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup);
}
else {
r->residue_books[j][k] = -1;
}
}
}
// precompute the classifications[] array to avoid inner-loop mod/divide
// call it 'classdata' since we already have r->classifications
r->classdata = (uint8 **)setup_malloc(f, sizeof(*r->classdata) * f->codebooks[r->classbook].entries);
if (!r->classdata) return error(f, VORBIS_outofmem);
memset(r->classdata, 0, sizeof(*r->classdata) * f->codebooks[r->classbook].entries);
for (j = 0; j < f->codebooks[r->classbook].entries; ++j) {
int classwords = f->codebooks[r->classbook].dimensions;
int temp = j;
r->classdata[j] = (uint8 *)setup_malloc(f, sizeof(r->classdata[j][0]) * classwords);
if (r->classdata[j] == NULL) return error(f, VORBIS_outofmem);
for (k = classwords - 1; k >= 0; --k) {
r->classdata[j][k] = temp % r->classifications;
temp /= r->classifications;
}
}
}
f->mapping_count = get_bits(f, 6) + 1;
f->mapping = (Mapping *)setup_malloc(f, f->mapping_count * sizeof(*f->mapping));
if (f->mapping == NULL) return error(f, VORBIS_outofmem);
memset(f->mapping, 0, f->mapping_count * sizeof(*f->mapping));
for (i = 0; i < f->mapping_count; ++i) {
Mapping *m = f->mapping + i;
int mapping_type = get_bits(f, 16);
if (mapping_type != 0) return error(f, VORBIS_invalid_setup);
m->chan = (MappingChannel *)setup_malloc(f, f->channels * sizeof(*m->chan));
if (m->chan == NULL) return error(f, VORBIS_outofmem);
if (get_bits(f, 1))
m->submaps = get_bits(f, 4) + 1;
else
m->submaps = 1;
if (m->submaps > max_submaps)
max_submaps = m->submaps;
if (get_bits(f, 1)) {
m->coupling_steps = get_bits(f, 8) + 1;
for (k = 0; k < m->coupling_steps; ++k) {
m->chan[k].magnitude = get_bits(f, ilog(f->channels - 1));
m->chan[k].angle = get_bits(f, ilog(f->channels - 1));
if (m->chan[k].magnitude >= f->channels) return error(f, VORBIS_invalid_setup);
if (m->chan[k].angle >= f->channels) return error(f, VORBIS_invalid_setup);
if (m->chan[k].magnitude == m->chan[k].angle) return error(f, VORBIS_invalid_setup);
}
}
else
m->coupling_steps = 0;
// reserved field
if (get_bits(f, 2)) return error(f, VORBIS_invalid_setup);
if (m->submaps > 1) {
for (j = 0; j < f->channels; ++j) {
m->chan[j].mux = get_bits(f, 4);
if (m->chan[j].mux >= m->submaps) return error(f, VORBIS_invalid_setup);
}
}
else
// @SPECIFICATION: this case is missing from the spec
for (j = 0; j < f->channels; ++j)
m->chan[j].mux = 0;
for (j = 0; j < m->submaps; ++j) {
get_bits(f, 8); // discard
m->submap_floor[j] = get_bits(f, 8);
m->submap_residue[j] = get_bits(f, 8);
if (m->submap_floor[j] >= f->floor_count) return error(f, VORBIS_invalid_setup);
if (m->submap_residue[j] >= f->residue_count) return error(f, VORBIS_invalid_setup);
}
}
// Modes
f->mode_count = get_bits(f, 6) + 1;
for (i = 0; i < f->mode_count; ++i) {
Mode *m = f->mode_config + i;
m->blockflag = get_bits(f, 1);
m->windowtype = get_bits(f, 16);
m->transformtype = get_bits(f, 16);
m->mapping = get_bits(f, 8);
if (m->windowtype != 0) return error(f, VORBIS_invalid_setup);
if (m->transformtype != 0) return error(f, VORBIS_invalid_setup);
if (m->mapping >= f->mapping_count) return error(f, VORBIS_invalid_setup);
}
flush_packet(f);
f->previous_length = 0;
for (i = 0; i < f->channels; ++i) {
f->channel_buffers[i] = (float *)setup_malloc(f, sizeof(float) * f->blocksize_1);
f->previous_window[i] = (float *)setup_malloc(f, sizeof(float) * f->blocksize_1 / 2);
f->finalY[i] = (int16 *)setup_malloc(f, sizeof(int16) * longest_floorlist);
if (f->channel_buffers[i] == NULL || f->previous_window[i] == NULL || f->finalY[i] == NULL) return error(f, VORBIS_outofmem);
#ifdef STB_VORBIS_NO_DEFER_FLOOR
f->floor_buffers[i] = (float *)setup_malloc(f, sizeof(float) * f->blocksize_1 / 2);
if (f->floor_buffers[i] == NULL) return error(f, VORBIS_outofmem);
#endif
}
if (!init_blocksize(f, 0, f->blocksize_0)) return FALSE;
if (!init_blocksize(f, 1, f->blocksize_1)) return FALSE;
f->blocksize[0] = f->blocksize_0;
f->blocksize[1] = f->blocksize_1;
#ifdef STB_VORBIS_DIVIDE_TABLE
if (integer_divide_table[1][1] == 0)
for (i = 0; i < DIVTAB_NUMER; ++i)
for (j = 1; j < DIVTAB_DENOM; ++j)
integer_divide_table[i][j] = i / j;
#endif
// compute how much temporary memory is needed
// 1.
{
uint32 imdct_mem = (f->blocksize_1 * sizeof(float) >> 1);
uint32 classify_mem;
int i, max_part_read = 0;
for (i = 0; i < f->residue_count; ++i) {
Residue *r = f->residue_config + i;
int n_read = r->end - r->begin;
int part_read = n_read / r->part_size;
if (part_read > max_part_read)
max_part_read = part_read;
}
#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(uint8 *));
#else
classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *));
#endif
f->temp_memory_required = classify_mem;
if (imdct_mem > f->temp_memory_required)
f->temp_memory_required = imdct_mem;
}
f->first_decode = TRUE;
if (f->alloc.alloc_buffer) {
assert(f->temp_offset == f->alloc.alloc_buffer_length_in_bytes);
// check if there's enough temp memory so we don't error later
if (f->setup_offset + sizeof(*f) + f->temp_memory_required > (unsigned)f->temp_offset)
return error(f, VORBIS_outofmem);
}
f->first_audio_page_offset = stb_vorbis_get_file_offset(f);
return TRUE;
}