diff options
Diffstat (limited to 'src/stb_vorbis.c')
| -rw-r--r-- | src/stb_vorbis.c | 844 |
1 files changed, 426 insertions, 418 deletions
diff --git a/src/stb_vorbis.c b/src/stb_vorbis.c index e2700157..0510edc7 100644 --- a/src/stb_vorbis.c +++ b/src/stb_vorbis.c @@ -107,14 +107,8 @@ // trade off storage for speed. //#define STB_VORBIS_DIVIDES_IN_CODEBOOK -// STB_VORBIS_CODEBOOK_SHORTS -// The vorbis file format encodes VQ codebook floats as ax+b where a and -// b are floating point per-codebook constants, and x is a 16-bit int. -// Normally, stb_vorbis decodes them to floats rather than leaving them -// as 16-bit ints and computing ax+b while decoding. This is a speed/space -// tradeoff; you can save space by defining this flag. -#ifndef STB_VORBIS_CODEBOOK_SHORTS -#define STB_VORBIS_CODEBOOK_FLOATS +#ifdef STB_VORBIS_CODEBOOK_SHORTS +#error "STB_VORBIS_CODEBOOK_SHORTS is no longer supported as it produced incorrect results for some input formats" #endif // STB_VORBIS_DIVIDE_TABLE @@ -175,11 +169,26 @@ #if !(defined(__APPLE__) || defined(MACOSX) || defined(macintosh) || defined(Macintosh)) #include <malloc.h> #endif -#else +#else // STB_VORBIS_NO_CRT #define NULL 0 -#endif - -#if !defined(_MSC_VER) && !(defined(__MINGW32__) && defined(__forceinline)) +#define malloc(s) 0 +#define free(s) ((void) 0) +#define realloc(s) 0 +#endif // STB_VORBIS_NO_CRT + +#include <limits.h> + +#ifdef __MINGW32__ + // eff you mingw: + // "fixed": + // http://sourceforge.net/p/mingw-w64/mailman/message/32882927/ + // "no that broke the build, reverted, who cares about C": + // http://sourceforge.net/p/mingw-w64/mailman/message/32890381/ + #ifdef __forceinline + #undef __forceinline + #endif + #define __forceinline +#elif !defined(_MSC_VER) #if __GNUC__ #define __forceinline inline #else @@ -196,6 +205,13 @@ #endif +#if 0 +#include <crtdbg.h> +#define CHECK(f) _CrtIsValidHeapPointer(f->channel_buffers[1]) +#else +#define CHECK(f) ((void) 0) +#endif + #define MAX_BLOCKSIZE_LOG 13 // from specification #define MAX_BLOCKSIZE (1 << MAX_BLOCKSIZE_LOG) @@ -212,11 +228,7 @@ typedef signed int int32; #define FALSE 0 #endif -#ifdef STB_VORBIS_CODEBOOK_FLOATS typedef float codetype; -#else -typedef uint16 codetype; -#endif // @NOTE // @@ -336,8 +348,6 @@ typedef struct typedef struct { uint32 page_start, page_end; - uint32 after_previous_page_start; - uint32 first_decoded_sample; uint32 last_decoded_sample; } ProbedPage; @@ -452,13 +462,6 @@ struct stb_vorbis int channel_buffer_end; }; -extern int my_prof(int slot); -//#define stb_prof my_prof - -#ifndef stb_prof -#define stb_prof(x) ((void) 0) -#endif - #if defined(STB_VORBIS_NO_PUSHDATA_API) #define IS_PUSH_MODE(f) FALSE #elif defined(STB_VORBIS_NO_PULLDATA_API) @@ -525,7 +528,7 @@ static void *setup_malloc(vorb *f, int sz) static void setup_free(vorb *f, void *p) { - if (f->alloc.alloc_buffer) return; // do nothing; setup mem is not a stack + if (f->alloc.alloc_buffer) return; // do nothing; setup mem is a stack free(p); } @@ -557,7 +560,7 @@ static void crc32_init(void) int i,j; uint32 s; for(i=0; i < 256; i++) { - for (s=i<<24, j=0; j < 8; ++j) + for (s=(uint32) i << 24, j=0; j < 8; ++j) s = (s << 1) ^ (s >= (1U<<31) ? CRC32_POLY : 0); crc_table[i] = s; } @@ -658,7 +661,7 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values) add_entry(c, 0, k, m++, len[k], values); // add all available leaves for (i=1; i <= len[k]; ++i) - available[i] = 1 << (32-i); + available[i] = 1U << (32-i); // note that the above code treats the first case specially, // but it's really the same as the following code, so they // could probably be combined (except the initial code is 0, @@ -674,12 +677,14 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values) // trivial to prove, but it seems true and the assert never // fires, so! while (z > 0 && !available[z]) --z; - if (z == 0) { assert(0); return FALSE; } + if (z == 0) { return FALSE; } res = available[z]; + assert(z >= 0 && z < 32); available[z] = 0; add_entry(c, bit_reverse(res), i, m++, len[i], values); // propogate availability up the tree if (z != len[i]) { + assert(len[i] >= 0 && len[i] < 32); for (y=len[i]; y > z; --y) { assert(available[y] == 0); available[y] = res + (1 << (32-y)); @@ -914,7 +919,7 @@ static uint32 get32(vorb *f) x = get8(f); x += get8(f) << 8; x += get8(f) << 16; - x += get8(f) << 24; + x += (uint32) get8(f) << 24; return x; } @@ -1045,8 +1050,6 @@ static int start_page_no_capturepattern(vorb *f) len += 27 + f->segment_count; p.page_start = f->first_audio_page_offset; p.page_end = p.page_start + len; - p.after_previous_page_start = p.page_start; - p.first_decoded_sample = 0; p.last_decoded_sample = loc0; f->p_first = p; } @@ -1189,7 +1192,7 @@ static __forceinline void prep_huffman(vorb *f) if (f->last_seg && !f->bytes_in_seg) return; z = get8_packet_raw(f); if (z == EOP) return; - f->acc += z << f->valid_bits; + f->acc += (unsigned) z << f->valid_bits; f->valid_bits += 8; } while (f->valid_bits <= 24); } @@ -1199,7 +1202,7 @@ enum { VORBIS_packet_id = 1, VORBIS_packet_comment = 3, - VORBIS_packet_setup = 5, + VORBIS_packet_setup = 5 }; static int codebook_decode_scalar_raw(vorb *f, Codebook *c) @@ -1207,7 +1210,9 @@ static int codebook_decode_scalar_raw(vorb *f, Codebook *c) int i; prep_huffman(f); - assert(c->sorted_codewords || c->codewords); + if (c->codewords == NULL && c->sorted_codewords == NULL) + return -1; + // cases to use binary search: sorted_codewords && !c->codewords // sorted_codewords && c->entries > 8 if (c->entries > 8 ? c->sorted_codewords!=NULL : !c->codewords) { @@ -1315,15 +1320,9 @@ static int codebook_decode_scalar(vorb *f, Codebook *c) // CODEBOOK_ELEMENT_FAST is an optimization for the CODEBOOK_FLOATS case // where we avoid one addition -#ifndef STB_VORBIS_CODEBOOK_FLOATS - #define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off] * c->delta_value + c->minimum_value) - #define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off] * c->delta_value) - #define CODEBOOK_ELEMENT_BASE(c) (c->minimum_value) -#else - #define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off]) - #define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off]) - #define CODEBOOK_ELEMENT_BASE(c) (0) -#endif +#define CODEBOOK_ELEMENT(c,off) (c->multiplicands[off]) +#define CODEBOOK_ELEMENT_FAST(c,off) (c->multiplicands[off]) +#define CODEBOOK_ELEMENT_BASE(c) (0) static int codebook_decode_start(vorb *f, Codebook *c) { @@ -1515,7 +1514,6 @@ static int codebook_decode_deinterleave_repeat_2(vorb *f, Codebook *c, float **o { z *= c->dimensions; - stb_prof(11); if (c->sequence_p) { // haven't optimized this case because I don't have any examples for (i=0; i < effective; ++i) { @@ -1527,7 +1525,7 @@ static int codebook_decode_deinterleave_repeat_2(vorb *f, Codebook *c, float **o } } else { i=0; - if (c_inter == 1) { + if (c_inter == 1 && i < effective) { float val = CODEBOOK_ELEMENT_FAST(c,z+i) + last; if (outputs[c_inter]) outputs[c_inter][p_inter] += val; @@ -1699,15 +1697,17 @@ static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y #endif ady -= abs(base) * adx; if (x1 > n) x1 = n; - LINE_OP(output[x], inverse_db_table[y]); - for (++x; x < x1; ++x) { - err += ady; - if (err >= adx) { - err -= adx; - y += sy; - } else - y += base; + if (x < x1) { LINE_OP(output[x], inverse_db_table[y]); + for (++x; x < x1; ++x) { + err += ady; + if (err >= adx) { + err -= adx; + y += sy; + } else + y += base; + LINE_OP(output[x], inverse_db_table[y]); + } } } @@ -1746,7 +1746,8 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int int **classifications = (int **) temp_block_array(f,f->channels, part_read * sizeof(**classifications)); #endif - stb_prof(2); + CHECK(f); + for (i=0; i < ch; ++i) if (!do_not_decode[i]) memset(residue_buffers[i], 0, sizeof(float) * n); @@ -1758,11 +1759,9 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int if (j == ch) goto done; - stb_prof(3); for (pass=0; pass < 8; ++pass) { int pcount = 0, class_set = 0; if (ch == 2) { - stb_prof(13); while (pcount < part_read) { int z = r->begin + pcount*r->part_size; int c_inter = (z & 1), p_inter = z>>1; @@ -1780,7 +1779,6 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int } #endif } - stb_prof(5); for (i=0; i < classwords && pcount < part_read; ++i, ++pcount) { int z = r->begin + pcount*r->part_size; #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE @@ -1791,23 +1789,20 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int int b = r->residue_books[c][pass]; if (b >= 0) { Codebook *book = f->codebooks + b; - stb_prof(20); // accounts for X time #ifdef STB_VORBIS_DIVIDES_IN_CODEBOOK if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) goto done; #else // saves 1% - if (!codebook_decode_deinterleave_repeat_2(f, book, residue_buffers, &c_inter, &p_inter, n, r->part_size)) + if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) goto done; #endif - stb_prof(7); } else { z += r->part_size; c_inter = z & 1; p_inter = z >> 1; } } - stb_prof(8); #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE ++class_set; #endif @@ -1840,10 +1835,8 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int int b = r->residue_books[c][pass]; if (b >= 0) { Codebook *book = f->codebooks + b; - stb_prof(22); if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) goto done; - stb_prof(3); } else { z += r->part_size; c_inter = 0; @@ -1882,10 +1875,8 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int int b = r->residue_books[c][pass]; if (b >= 0) { Codebook *book = f->codebooks + b; - stb_prof(22); if (!codebook_decode_deinterleave_repeat(f, book, residue_buffers, ch, &c_inter, &p_inter, n, r->part_size)) goto done; - stb_prof(3); } else { z += r->part_size; c_inter = z % ch; @@ -1900,7 +1891,7 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int } goto done; } - stb_prof(9); + CHECK(f); for (pass=0; pass < 8; ++pass) { int pcount = 0, class_set=0; @@ -1949,7 +1940,7 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int } } done: - stb_prof(0); + CHECK(f); temp_alloc_restore(f,temp_alloc_point); } @@ -2761,18 +2752,36 @@ static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *f { int hy = finalY[j] * g->floor1_multiplier; int hx = g->Xlist[j]; - draw_line(target, lx,ly, hx,hy, n2); + if (lx != hx) + draw_line(target, lx,ly, hx,hy, n2); + CHECK(f); lx = hx, ly = hy; } } - if (lx < n2) + if (lx < n2) { // optimization of: draw_line(target, lx,ly, n,ly, n2); for (j=lx; j < n2; ++j) LINE_OP(target[j], inverse_db_table[ly]); + CHECK(f); + } } return TRUE; } +// The meaning of "left" and "right" +// +// For a given frame: +// we compute samples from 0..n +// window_center is n/2 +// we'll window and mix the samples from left_start to left_end with data from the previous frame +// all of the samples from left_end to right_start can be output without mixing; however, +// this interval is 0-length except when transitioning between short and long frames +// all of the samples from right_start to right_end need to be mixed with the next frame, +// which we don't have, so those get saved in a buffer +// frame N's right_end-right_start, the number of samples to mix with the next frame, +// has to be the same as frame N+1's left_end-left_start (which they are by +// construction) + static int vorbis_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode) { Mode *m; @@ -2825,6 +2834,7 @@ static int vorbis_decode_initial(vorb *f, int *p_left_start, int *p_left_end, in *p_right_start = window_center; *p_right_end = n; } + return TRUE; } @@ -2843,7 +2853,8 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, // FLOORS n2 = n >> 1; - stb_prof(1); + CHECK(f); + for (i=0; i < f->channels; ++i) { int s = map->chan[i].mux, floor; zero_channel[i] = FALSE; @@ -2935,7 +2946,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, // at this point we've decoded the floor into buffer } } - stb_prof(0); + CHECK(f); // at this point we've decoded all floors if (f->alloc.alloc_buffer) @@ -2948,6 +2959,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, zero_channel[map->chan[i].magnitude] = zero_channel[map->chan[i].angle] = FALSE; } + CHECK(f); // RESIDUE DECODE for (i=0; i < map->submaps; ++i) { float *residue_buffers[STB_VORBIS_MAX_CHANNELS]; @@ -2972,9 +2984,9 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, if (f->alloc.alloc_buffer) assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); + CHECK(f); // INVERSE COUPLING - stb_prof(14); for (i = map->coupling_steps-1; i >= 0; --i) { int n2 = n >> 1; float *m = f->channel_buffers[map->chan[i].magnitude]; @@ -2995,10 +3007,10 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, a[j] = a2; } } + CHECK(f); // finish decoding the floors #ifndef STB_VORBIS_NO_DEFER_FLOOR - stb_prof(15); for (i=0; i < f->channels; ++i) { if (really_zero_channel[i]) { memset(f->channel_buffers[i], 0, sizeof(*f->channel_buffers[i]) * n2); @@ -3018,10 +3030,10 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, #endif // INVERSE MDCT - stb_prof(16); + CHECK(f); for (i=0; i < f->channels; ++i) inverse_mdct(f->channel_buffers[i], n, f, m->blockflag); - stb_prof(0); + CHECK(f); // this shouldn't be necessary, unless we exited on an error // and want to flush to get to the next packet @@ -3039,9 +3051,15 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, f->current_loc_valid = TRUE; f->first_decode = FALSE; } else if (f->discard_samples_deferred) { - left_start += f->discard_samples_deferred; - *p_left = left_start; - f->discard_samples_deferred = 0; + if (f->discard_samples_deferred >= right_start - left_start) { + f->discard_samples_deferred -= (right_start - left_start); + left_start = right_start; + *p_left = left_start; + } else { + left_start += f->discard_samples_deferred; + *p_left = left_start; + f->discard_samples_deferred = 0; + } } else if (f->previous_length == 0 && f->current_loc_valid) { // we're recovering from a seek... that means we're going to discard // the samples from this packet even though we know our position from @@ -3057,7 +3075,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) { uint32 current_end = f->known_loc_for_packet - (n-right_end); // then let's infer the size of the (probably) short final frame - if (current_end < f->current_loc + right_end) { + if (current_end < f->current_loc + (right_end-left_start)) { if (current_end < f->current_loc) { // negative truncation, that's impossible! *len = 0; @@ -3065,6 +3083,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, *len = current_end - f->current_loc; } *len += left_start; + if (*len > right_end) *len = right_end; // this should never happen f->current_loc += *len; return TRUE; } @@ -3082,6 +3101,8 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, if (f->alloc.alloc_buffer) assert(f->alloc.alloc_buffer_length_in_bytes == f->temp_offset); *len = right_end; // ignore samples after the window goes to 0 + CHECK(f); + return TRUE; } @@ -3247,14 +3268,15 @@ static int start_decoder(vorb *f) 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); + { + 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 @@ -3303,6 +3325,7 @@ static int start_decoder(vorb *f) 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); @@ -3314,6 +3337,8 @@ static int start_decoder(vorb *f) 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 @@ -3338,6 +3363,8 @@ static int start_decoder(vorb *f) 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; } @@ -3350,6 +3377,7 @@ static int start_decoder(vorb *f) 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; @@ -3371,6 +3399,7 @@ static int start_decoder(vorb *f) 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); @@ -3397,10 +3426,13 @@ static int start_decoder(vorb *f) 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) { ++c->sorted_values; c->sorted_values[-1] = -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); } @@ -3413,6 +3445,7 @@ static int start_decoder(vorb *f) 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) { @@ -3426,6 +3459,7 @@ static int start_decoder(vorb *f) } 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) { @@ -3437,6 +3471,7 @@ static int start_decoder(vorb *f) #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; @@ -3446,21 +3481,22 @@ static int start_decoder(vorb *f) 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) { - int z = sparse ? c->sorted_values[j] : j, div=1; + 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; - c->multiplicands[j*c->dimensions + k] = - #ifndef STB_VORBIS_CODEBOOK_FLOATS - mults[off]; - #else - mults[off]*c->delta_value + c->minimum_value; - // in this case (and this case only) we could pre-expand c->sequence_p, - // and throw away the decode logic for it; have to ALSO do - // it in the case below, but it can only be done if - // STB_VORBIS_CODEBOOK_FLOATS - // !STB_VORBIS_DIVIDES_IN_CODEBOOK - #endif - 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); @@ -3469,27 +3505,25 @@ static int start_decoder(vorb *f) else #endif { + float last=0; + CHECK(f); c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values); - #ifndef STB_VORBIS_CODEBOOK_FLOATS - memcpy(c->multiplicands, mults, sizeof(c->multiplicands[0]) * c->lookup_values); - #else - for (j=0; j < (int) c->lookup_values; ++j) - c->multiplicands[j] = mults[j] * c->delta_value + c->minimum_value; - #endif + 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 - #ifdef STB_VORBIS_CODEBOOK_FLOATS - if (c->lookup_type == 2 && c->sequence_p) { - for (j=1; j < (int) c->lookup_values; ++j) - c->multiplicands[j] = c->multiplicands[j-1]; - c->sequence_p = 0; - } - #endif + CHECK(f); } + CHECK(f); } // time domain transfers (notused) @@ -3503,6 +3537,7 @@ static int start_decoder(vorb *f) // 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); @@ -3574,7 +3609,9 @@ static int start_decoder(vorb *f) // Residue f->residue_count = get_bits(f, 6)+1; - f->residue_config = (Residue *) setup_malloc(f, f->residue_count * sizeof(*f->residue_config)); + 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; @@ -3582,9 +3619,11 @@ static int start_decoder(vorb *f) 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); @@ -3593,6 +3632,7 @@ static int start_decoder(vorb *f) 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)) { @@ -3612,6 +3652,7 @@ static int start_decoder(vorb *f) 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; @@ -3621,11 +3662,14 @@ static int start_decoder(vorb *f) 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 @@ -3686,8 +3730,10 @@ static int start_decoder(vorb *f) 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 } @@ -3745,17 +3791,20 @@ static int start_decoder(vorb *f) static void vorbis_deinit(stb_vorbis *p) { int i,j; - for (i=0; i < p->residue_count; ++i) { - Residue *r = p->residue_config+i; - if (r->classdata) { - for (j=0; j < p->codebooks[r->classbook].entries; ++j) - setup_free(p, r->classdata[j]); - setup_free(p, r->classdata); + if (p->residue_config) { + for (i=0; i < p->residue_count; ++i) { + Residue *r = p->residue_config+i; + if (r->classdata) { + for (j=0; j < p->codebooks[r->classbook].entries; ++j) + setup_free(p, r->classdata[j]); + setup_free(p, r->classdata); + } + setup_free(p, r->residue_books); } - setup_free(p, r->residue_books); } if (p->codebooks) { + CHECK(p); for (i=0; i < p->codebook_count; ++i) { Codebook *c = p->codebooks + i; setup_free(p, c->codeword_lengths); @@ -3769,10 +3818,13 @@ static void vorbis_deinit(stb_vorbis *p) } setup_free(p, p->floor_config); setup_free(p, p->residue_config); - for (i=0; i < p->mapping_count; ++i) - setup_free(p, p->mapping[i].chan); - setup_free(p, p->mapping); - for (i=0; i < p->channels; ++i) { + if (p->mapping) { + for (i=0; i < p->mapping_count; ++i) + setup_free(p, p->mapping[i].chan); + setup_free(p, p->mapping); + } + CHECK(p); + for (i=0; i < p->channels && i < STB_VORBIS_MAX_CHANNELS; ++i) { setup_free(p, p->channel_buffers[i]); setup_free(p, p->previous_window[i]); #ifdef STB_VORBIS_NO_DEFER_FLOOR @@ -3799,7 +3851,7 @@ void stb_vorbis_close(stb_vorbis *p) setup_free(p,p); } -static void vorbis_init(stb_vorbis *p, stb_vorbis_alloc *z) +static void vorbis_init(stb_vorbis *p, const stb_vorbis_alloc *z) { memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start if (z) { @@ -3957,11 +4009,11 @@ static int vorbis_search_for_page_pushdata(vorb *f, uint8 *data, int data_len) // return value: number of bytes we used int stb_vorbis_decode_frame_pushdata( - stb_vorbis *f, // the file we're decoding - uint8 *data, int data_len, // the memory available for decoding - int *channels, // place to write number of float * buffers - float ***output, // place to write float ** array of float * buffers - int *samples // place to write number of output samples + stb_vorbis *f, // the file we're decoding + const uint8 *data, int data_len, // the memory available for decoding + int *channels, // place to write number of float * buffers + float ***output, // place to write float ** array of float * buffers + int *samples // place to write number of output samples ) { int i; @@ -3971,11 +4023,11 @@ int stb_vorbis_decode_frame_pushdata( if (f->page_crc_tests >= 0) { *samples = 0; - return vorbis_search_for_page_pushdata(f, data, data_len); + return vorbis_search_for_page_pushdata(f, (uint8 *) data, data_len); } - f->stream = data; - f->stream_end = data + data_len; + f->stream = (uint8 *) data; + f->stream_end = (uint8 *) data + data_len; f->error = VORBIS__no_error; // check that we have the entire packet in memory @@ -4027,14 +4079,14 @@ int stb_vorbis_decode_frame_pushdata( } stb_vorbis *stb_vorbis_open_pushdata( - unsigned char *data, int data_len, // the memory available for decoding + const unsigned char *data, int data_len, // the memory available for decoding int *data_used, // only defined if result is not NULL - int *error, stb_vorbis_alloc *alloc) + int *error, const stb_vorbis_alloc *alloc) { stb_vorbis *f, p; vorbis_init(&p, alloc); - p.stream = data; - p.stream_end = data + data_len; + p.stream = (uint8 *) data; + p.stream_end = (uint8 *) data + data_len; p.push_mode = TRUE; if (!start_decoder(&p)) { if (p.eof) @@ -4078,7 +4130,7 @@ static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last) int n; if (f->eof) return 0; n = get8(f); - if (n == 0x4f) { // page header + if (n == 0x4f) { // page header candidate unsigned int retry_loc = stb_vorbis_get_file_offset(f); int i; // check if we're off the end of a file_section stream @@ -4142,37 +4194,30 @@ static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last) } } -// seek is implemented with 'interpolation search'--this is like -// binary search, but we use the data values to estimate the likely -// location of the data item (plus a bit of a bias so when the -// estimation is wrong we don't waste overly much time) #define SAMPLE_unknown 0xffffffff +// seeking is implemented with a binary search, which narrows down the range to +// 64K, before using a linear search (because finding the synchronization +// pattern can be expensive, and the chance we'd find the end page again is +// relatively high for small ranges) +// +// two initial interpolation-style probes are used at the start of the search +// to try to bound either side of the binary search sensibly, while still +// working in O(log n) time if they fail. -// ogg vorbis, in its insane infinite wisdom, only provides -// information about the sample at the END of the page. -// therefore we COULD have the data we need in the current -// page, and not know it. we could just use the end location -// as our only knowledge for bounds, seek back, and eventually -// the binary search finds it. or we can try to be smart and -// not waste time trying to locate more pages. we try to be -// smart, since this data is already in memory anyway, so -// doing needless I/O would be crazy! -static int vorbis_analyze_page(stb_vorbis *f, ProbedPage *z) +static int get_seek_page_info(stb_vorbis *f, ProbedPage *z) { uint8 header[27], lacing[255]; - uint8 packet_type[255]; - int num_packet, packet_start; int i,len; - uint32 samples; // record where the page starts z->page_start = stb_vorbis_get_file_offset(f); // parse the header getn(f, header, 27); - assert(header[0] == 'O' && header[1] == 'g' && header[2] == 'g' && header[3] == 'S'); + if (header[0] != 'O' || header[1] != 'g' || header[2] != 'g' || header[3] != 'S') + return 0; getn(f, lacing, header[26]); // determine the length of the payload @@ -4184,304 +4229,265 @@ static int vorbis_analyze_page(stb_vorbis *f, ProbedPage *z) z->page_end = z->page_start + 27 + header[26] + len; // read the last-decoded sample out of the data - z->last_decoded_sample = header[6] + (header[7] << 8) + (header[8] << 16) + (header[9] << 16); + z->last_decoded_sample = header[6] + (header[7] << 8) + (header[8] << 16) + (header[9] << 24); - if (header[5] & 4) { - // if this is the last page, it's not possible to work - // backwards to figure out the first sample! whoops! fuck. - z->first_decoded_sample = SAMPLE_unknown; - set_file_offset(f, z->page_start); - return 1; - } - - // scan through the frames to determine the sample-count of each one... - // our goal is the sample # of the first fully-decoded sample on the - // page, which is the first decoded sample of the 2nd packet + // restore file state to where we were + set_file_offset(f, z->page_start); + return 1; +} - num_packet=0; +// rarely used function to seek back to the preceeding page while finding the +// start of a packet +static int go_to_page_before(stb_vorbis *f, unsigned int limit_offset) +{ + unsigned int previous_safe, end; - packet_start = ((header[5] & 1) == 0); + // now we want to seek back 64K from the limit + if (limit_offset >= 65536 && limit_offset-65536 >= f->first_audio_page_offset) + previous_safe = limit_offset - 65536; + else + previous_safe = f->first_audio_page_offset; - for (i=0; i < header[26]; ++i) { - if (packet_start) { - uint8 n,b; - if (lacing[i] == 0) goto bail; // trying to read from zero-length packet - n = get8(f); - // if bottom bit is non-zero, we've got corruption - if (n & 1) goto bail; - n >>= 1; - b = ilog(f->mode_count-1); - n &= (1 << b)-1; - if (n >= f->mode_count) goto bail; - packet_type[num_packet++] = f->mode_config[n].blockflag; - skip(f, lacing[i]-1); - } else - skip(f, lacing[i]); - packet_start = (lacing[i] < 255); - } - - // now that we know the sizes of all the pages, we can start determining - // how much sample data there is. - - samples = 0; - - // for the last packet, we step by its whole length, because the definition - // is that we encoded the end sample loc of the 'last packet completed', - // where 'completed' refers to packets being split, and we are left to guess - // what 'end sample loc' means. we assume it means ignoring the fact that - // the last half of the data is useless without windowing against the next - // packet... (so it's not REALLY complete in that sense) - if (num_packet > 1) - samples += f->blocksize[packet_type[num_packet-1]]; - - for (i=num_packet-2; i >= 1; --i) { - // now, for this packet, how many samples do we have that - // do not overlap the following packet? - if (packet_type[i] == 1) - if (packet_type[i+1] == 1) - samples += f->blocksize_1 >> 1; - else - samples += ((f->blocksize_1 - f->blocksize_0) >> 2) + (f->blocksize_0 >> 1); - else - samples += f->blocksize_0 >> 1; - } - // now, at this point, we've rewound to the very beginning of the - // _second_ packet. if we entirely discard the first packet after - // a seek, this will be exactly the right sample number. HOWEVER! - // we can't as easily compute this number for the LAST page. The - // only way to get the sample offset of the LAST page is to use - // the end loc from the previous page. But what that returns us - // is _exactly_ the place where we get our first non-overlapped - // sample. (I think. Stupid spec for being ambiguous.) So for - // consistency it's better to do that here, too. However, that - // will then require us to NOT discard all of the first frame we - // decode, in some cases, which means an even weirder frame size - // and extra code. what a fucking pain. - - // we're going to discard the first packet if we - // start the seek here, so we don't care about it. (we could actually - // do better; if the first packet is long, and the previous packet - // is short, there's actually data in the first half of the first - // packet that doesn't need discarding... but not worth paying the - // effort of tracking that of that here and in the seeking logic) - // except crap, if we infer it from the _previous_ packet's end - // location, we DO need to use that definition... and we HAVE to - // infer the start loc of the LAST packet from the previous packet's - // end location. fuck you, ogg vorbis. - - z->first_decoded_sample = z->last_decoded_sample - samples; + set_file_offset(f, previous_safe); - // restore file state to where we were - set_file_offset(f, z->page_start); - return 1; + while (vorbis_find_page(f, &end, NULL)) { + if (end >= limit_offset && stb_vorbis_get_file_offset(f) < limit_offset) + return 1; + set_file_offset(f, end); + } - // restore file state to where we were - bail: - set_file_offset(f, z->page_start); return 0; } -static int vorbis_seek_frame_from_page(stb_vorbis *f, uint32 page_start, uint32 first_sample, uint32 target_sample, int fine) -{ - int left_start, left_end, right_start, right_end, mode,i; - int frame=0; - uint32 frame_start; - int frames_to_skip, data_to_skip; +// implements the search logic for finding a page and starting decoding. if +// the function succeeds, current_loc_valid will be true and current_loc will +// be less than or equal to the provided sample number (the closer the +// better). +static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number) +{ + ProbedPage left, right, mid; + int i, start_seg_with_known_loc, end_pos, page_start; + uint32 delta, stream_length, padding; + double offset, bytes_per_sample; + int probe = 0; + + // find the last page and validate the target sample + stream_length = stb_vorbis_stream_length_in_samples(f); + if (stream_length == 0) return error(f, VORBIS_seek_without_length); + if (sample_number > stream_length) return error(f, VORBIS_seek_invalid); + + // this is the maximum difference between the window-center (which is the + // actual granule position value), and the right-start (which the spec + // indicates should be the granule position (give or take one)). + padding = ((f->blocksize_1 - f->blocksize_0) >> 2); + if (sample_number < padding) + sample_number = 0; + else + sample_number -= padding; - // first_sample is the sample # of the first sample that doesn't - // overlap the previous page... note that this requires us to - // _partially_ discard the first packet! bleh. - set_file_offset(f, page_start); + left = f->p_first; + while (left.last_decoded_sample == ~0U) { + // (untested) the first page does not have a 'last_decoded_sample' + set_file_offset(f, left.page_end); + if (!get_seek_page_info(f, &left)) goto error; + } - f->next_seg = -1; // force page resync + right = f->p_last; + assert(right.last_decoded_sample != ~0U); - frame_start = first_sample; - // frame start is where the previous packet's last decoded sample - // was, which corresponds to left_end... EXCEPT if the previous - // packet was long and this packet is short? Probably a bug here. + // starting from the start is handled differently + if (sample_number <= left.last_decoded_sample) { + stb_vorbis_seek_start(f); + return 1; + } + while (left.page_end != right.page_start) { + assert(left.page_end < right.page_start); + // search range in bytes + delta = right.page_start - left.page_end; + if (delta <= 65536) { + // there's only 64K left to search - handle it linearly + set_file_offset(f, left.page_end); + } else { + if (probe < 2) { + if (probe == 0) { + // first probe (interpolate) + double data_bytes = right.page_end - left.page_start; + bytes_per_sample = data_bytes / right.last_decoded_sample; + offset = left.page_start + bytes_per_sample * (sample_number - left.last_decoded_sample); + } else { + // second probe (try to bound the other side) + double error = ((double) sample_number - mid.last_decoded_sample) * bytes_per_sample; + if (error >= 0 && error < 8000) error = 8000; + if (error < 0 && error > -8000) error = -8000; + offset += error * 2; + } - // now, we can start decoding frames... we'll only FAKE decode them, - // until we find the frame that contains our sample; then we'll rewind, - // and try again - for (;;) { - int start; + // ensure the offset is valid + if (offset < left.page_end) + offset = left.page_end; + if (offset > right.page_start - 65536) + offset = right.page_start - 65536; - if (!vorbis_decode_initial(f, &left_start, &left_end, &right_start, &right_end, &mode)) - return error(f, VORBIS_seek_failed); + set_file_offset(f, (unsigned int) offset); + } else { + // binary search for large ranges (offset by 32K to ensure + // we don't hit the right page) + set_file_offset(f, left.page_end + (delta / 2) - 32768); + } - if (frame == 0) - start = left_end; - else - start = left_start; + if (!vorbis_find_page(f, NULL, NULL)) goto error; + } - // the window starts at left_start; the last valid sample we generate - // before the next frame's window start is right_start-1 - if (target_sample < frame_start + right_start-start) - break; + for (;;) { + if (!get_seek_page_info(f, &mid)) goto error; + if (mid.last_decoded_sample != ~0U) break; + // (untested) no frames end on this page + set_file_offset(f, mid.page_end); + assert(mid.page_start < right.page_start); + } - flush_packet(f); - if (f->eof) - return error(f, VORBIS_seek_failed); + // if we've just found the last page again then we're in a tricky file, + // and we're close enough. + if (mid.page_start == right.page_start) + break; - frame_start += right_start - start; + if (sample_number < mid.last_decoded_sample) + right = mid; + else + left = mid; - ++frame; + ++probe; } - // ok, at this point, the sample we want is contained in frame #'frame' + // seek back to start of the last packet + page_start = left.page_start; + set_file_offset(f, page_start); + if (!start_page(f)) return error(f, VORBIS_seek_failed); + end_pos = f->end_seg_with_known_loc; + assert(end_pos >= 0); - // to decode frame #'frame' normally, we have to decode the - // previous frame first... but if it's the FIRST frame of the page - // we can't. if it's the first frame, it means it falls in the part - // of the first frame that doesn't overlap either of the other frames. - // so, if we have to handle that case for the first frame, we might - // as well handle it for all of them, so: - if (target_sample > frame_start + (left_end - left_start)) { - // so what we want to do is go ahead and just immediately decode - // this frame, but then make it so the next get_frame_float() uses - // this already-decoded data? or do we want to go ahead and rewind, - // and leave a flag saying to skip the first N data? let's do that - frames_to_skip = frame; // if this is frame #1, skip 1 frame (#0) - data_to_skip = left_end - left_start; - } else { - // otherwise, we want to skip frames 0, 1, 2, ... frame-2 - // (which means frame-2+1 total frames) then decode frame-1, - // then leave frame pending - frames_to_skip = frame - 1; - assert(frames_to_skip >= 0); - data_to_skip = -1; - } + for (;;) { + for (i = end_pos; i > 0; --i) + if (f->segments[i-1] != 255) + break; - set_file_offset(f, page_start); - f->next_seg = - 1; // force page resync + start_seg_with_known_loc = i; - for (i=0; i < frames_to_skip; ++i) { - maybe_start_packet(f); - flush_packet(f); - } + if (start_seg_with_known_loc > 0 || !(f->page_flag & PAGEFLAG_continued_packet)) + break; - if (data_to_skip >= 0) { - int i,j,n = f->blocksize_0 >> 1; - f->discard_samples_deferred = data_to_skip; - for (i=0; i < f->channels; ++i) - for (j=0; j < n; ++j) - f->previous_window[i][j] = 0; - f->previous_length = n; - frame_start += data_to_skip; - } else { - f->previous_length = 0; - vorbis_pump_first_frame(f); - } - - // at this point, the NEXT decoded frame will generate the desired sample - if (fine) { - // so if we're doing sample accurate streaming, we want to go ahead and decode it! - if (target_sample != frame_start) { - int n; - stb_vorbis_get_frame_float(f, &n, NULL); - assert(target_sample > frame_start); - assert(f->channel_buffer_start + (int) (target_sample-frame_start) < f->channel_buffer_end); - f->channel_buffer_start += (target_sample - frame_start); - } + // (untested) the final packet begins on an earlier page + if (!go_to_page_before(f, page_start)) + goto error; + + page_start = stb_vorbis_get_file_offset(f); + if (!start_page(f)) goto error; + end_pos = f->segment_count - 1; } - return 0; + // prepare to start decoding + f->current_loc_valid = FALSE; + f->last_seg = FALSE; + f->valid_bits = 0; + f->packet_bytes = 0; + f->bytes_in_seg = 0; + f->previous_length = 0; + f->next_seg = start_seg_with_known_loc; + + for (i = 0; i < start_seg_with_known_loc; i++) + skip(f, f->segments[i]); + + // start decoding (optimizable - this frame is generally discarded) + vorbis_pump_first_frame(f); + return 1; + +error: + // try to restore the file to a valid state + stb_vorbis_seek_start(f); + return error(f, VORBIS_seek_failed); } -static int vorbis_seek_base(stb_vorbis *f, unsigned int sample_number, int fine) +// the same as vorbis_decode_initial, but without advancing +static int peek_decode_initial(vorb *f, int *p_left_start, int *p_left_end, int *p_right_start, int *p_right_end, int *mode) { - ProbedPage p[2],q; - if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); + int bits_read, bytes_read; - // do we know the location of the last page? - if (f->p_last.page_start == 0) { - uint32 z = stb_vorbis_stream_length_in_samples(f); - if (z == 0) return error(f, VORBIS_cant_find_last_page); - } + if (!vorbis_decode_initial(f, p_left_start, p_left_end, p_right_start, p_right_end, mode)) + return 0; - p[0] = f->p_first; - p[1] = f->p_last; + // either 1 or 2 bytes were read, figure out which so we can rewind + bits_read = 1 + ilog(f->mode_count-1); + if (f->mode_config[*mode].blockflag) + bits_read += 2; + bytes_read = (bits_read + 7) / 8; + + f->bytes_in_seg += bytes_read; + f->packet_bytes -= bytes_read; + skip(f, -bytes_read); + if (f->next_seg == -1) + f->next_seg = f->segment_count - 1; + else + f->next_seg--; + f->valid_bits = 0; - if (sample_number >= f->p_last.last_decoded_sample) - sample_number = f->p_last.last_decoded_sample-1; + return 1; +} - if (sample_number < f->p_first.last_decoded_sample) { - vorbis_seek_frame_from_page(f, p[0].page_start, 0, sample_number, fine); - return 0; - } else { - int attempts=0; - while (p[0].page_end < p[1].page_start) { - uint32 probe; - uint32 start_offset, end_offset; - uint32 start_sample, end_sample; - - // copy these into local variables so we can tweak them - // if any are unknown - start_offset = p[0].page_end; - end_offset = p[1].after_previous_page_start; // an address known to seek to page p[1] - start_sample = p[0].last_decoded_sample; - end_sample = p[1].last_decoded_sample; - - // currently there is no such tweaking logic needed/possible? - if (start_sample == SAMPLE_unknown || end_sample == SAMPLE_unknown) - return error(f, VORBIS_seek_failed); - - // now we want to lerp between these for the target samples... - - // step 1: we need to bias towards the page start... - if (start_offset + 4000 < end_offset) - end_offset -= 4000; - - // now compute an interpolated search loc - probe = start_offset + (int) floor((float) (end_offset - start_offset) / (end_sample - start_sample) * (sample_number - start_sample)); - - // next we need to bias towards binary search... - // code is a little wonky to allow for full 32-bit unsigned values - if (attempts >= 4) { - uint32 probe2 = start_offset + ((end_offset - start_offset) >> 1); - if (attempts >= 8) - probe = probe2; - else if (probe < probe2) - probe = probe + ((probe2 - probe) >> 1); - else - probe = probe2 + ((probe - probe2) >> 1); - } - ++attempts; +int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number) +{ + uint32 max_frame_samples; - set_file_offset(f, probe); - if (!vorbis_find_page(f, NULL, NULL)) return error(f, VORBIS_seek_failed); - if (!vorbis_analyze_page(f, &q)) return error(f, VORBIS_seek_failed); - q.after_previous_page_start = probe; + if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing); - // it's possible we've just found the last page again - if (q.page_start == p[1].page_start) { - p[1] = q; - continue; - } + // fast page-level search + if (!seek_to_sample_coarse(f, sample_number)) + return 0; - if (sample_number < q.last_decoded_sample) - p[1] = q; - else - p[0] = q; - } + assert(f->current_loc_valid); + assert(f->current_loc <= sample_number); - if (p[0].last_decoded_sample <= sample_number && sample_number < p[1].last_decoded_sample) { - vorbis_seek_frame_from_page(f, p[1].page_start, p[0].last_decoded_sample, sample_number, fine); - return 0; + // linear search for the relevant packet + max_frame_samples = (f->blocksize_1*3 - f->blocksize_0) >> 2; + while (f->current_loc < sample_number) { + int left_start, left_end, right_start, right_end, mode, frame_samples; + if (!peek_decode_initial(f, &left_start, &left_end, &right_start, &right_end, &mode)) + return error(f, VORBIS_seek_failed); + // calculate the number of samples returned by the next frame + frame_samples = right_start - left_start; + if (f->current_loc + frame_samples > sample_number) { + return 1; // the next frame will contain the sample + } else if (f->current_loc + frame_samples + max_frame_samples > sample_number) { + // there's a chance the frame after this could contain the sample + vorbis_pump_first_frame(f); + } else { + // this frame is too early to be relevant + f->current_loc += frame_samples; + f->previous_length = 0; + maybe_start_packet(f); + flush_packet(f); } - return error(f, VORBIS_seek_failed); } -} - -int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number) -{ - return vorbis_seek_base(f, sample_number, FALSE); + // the next frame will start with the sample + assert(f->current_loc == sample_number); + return 1; } int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number) { - return vorbis_seek_base(f, sample_number, TRUE); + if (!stb_vorbis_seek_frame(f, sample_number)) + return 0; + + if (sample_number != f->current_loc) { + int n; + uint32 frame_start = f->current_loc; + stb_vorbis_get_frame_float(f, &n, NULL); + assert(sample_number > frame_start); + assert(f->channel_buffer_start + (int) (sample_number-frame_start) <= f->channel_buffer_end); + f->channel_buffer_start += (sample_number - frame_start); + } + + return 1; } void stb_vorbis_seek_start(stb_vorbis *f) @@ -4562,8 +4568,6 @@ unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f) f->p_last.page_start = last_page_loc; f->p_last.page_end = end; f->p_last.last_decoded_sample = lo; - f->p_last.first_decoded_sample = SAMPLE_unknown; - f->p_last.after_previous_page_start = previous_safe; done: set_file_offset(f, restore_offset); @@ -4602,7 +4606,7 @@ int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***output) #ifndef STB_VORBIS_NO_STDIO -stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *error, stb_vorbis_alloc *alloc, unsigned int length) +stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc, unsigned int length) { stb_vorbis *f, p; vorbis_init(&p, alloc); @@ -4623,7 +4627,7 @@ stb_vorbis * stb_vorbis_open_file_section(FILE *file, int close_on_free, int *er return NULL; } -stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, stb_vorbis_alloc *alloc) +stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, const stb_vorbis_alloc *alloc) { unsigned int len, start; start = ftell(file); @@ -4633,7 +4637,7 @@ stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, stb return stb_vorbis_open_file_section(file, close_on_free, error, alloc, len); } -stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, stb_vorbis_alloc *alloc) +stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc) { FILE *f = fopen(filename, "rb"); if (f) @@ -4643,7 +4647,7 @@ stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, stb_vorb } #endif // STB_VORBIS_NO_STDIO -stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, stb_vorbis_alloc *alloc) +stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, int *error, const stb_vorbis_alloc *alloc) { stb_vorbis *f, p; if (data == NULL) return NULL; @@ -5023,6 +5027,10 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in #endif // STB_VORBIS_NO_PULLDATA_API /* Version history + 1.07 - 2015/01/16 - fixed some warnings, fix mingw, const-correct API + some more crash fixes when out of memory or with corrupt files + 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) + some crash fixes when out of memory or with corrupt files 1.05 - 2015/04/19 - don't define __forceinline if it's redundant 1.04 - 2014/08/27 - fix missing const-correct case in API 1.03 - 2014/08/07 - Warning fixes |
