|
|
|
@ -1,8 +1,11 @@ |
|
|
|
|
// Ogg Vorbis audio decoder - v1.06 - public domain
|
|
|
|
|
// Ogg Vorbis audio decoder - v1.07 - public domain
|
|
|
|
|
// http://nothings.org/stb_vorbis/
|
|
|
|
|
//
|
|
|
|
|
// Written by Sean Barrett in 2007, last updated in 2014
|
|
|
|
|
// Sponsored by RAD Game Tools.
|
|
|
|
|
// Original version written by Sean Barrett in 2007.
|
|
|
|
|
//
|
|
|
|
|
// Originally sponsored by RAD Game Tools. Seeking sponsored
|
|
|
|
|
// by Phillip Bennefall, Marc Andersen, Aaron Baker, Elias Software,
|
|
|
|
|
// Aras Pranckevicius, and Sean Barrett.
|
|
|
|
|
//
|
|
|
|
|
// LICENSE
|
|
|
|
|
//
|
|
|
|
@ -30,11 +33,10 @@ |
|
|
|
|
// Laurent Gomila Marc LeBlanc Ronny Chevalier
|
|
|
|
|
// Bernhard Wodo Evan Balster "alxprd"@github
|
|
|
|
|
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot
|
|
|
|
|
// (If you reported a bug but do not appear in this list, it is because
|
|
|
|
|
// someone else reported the bug before you. There were too many of you to
|
|
|
|
|
// list them all because I was lax about updating for a long time, sorry.)
|
|
|
|
|
// Phillip Bennefall Rohit
|
|
|
|
|
//
|
|
|
|
|
// Partial history:
|
|
|
|
|
// 1.07 - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const
|
|
|
|
|
// 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson)
|
|
|
|
|
// some crash fixes when out of memory or with corrupt files
|
|
|
|
|
// fix some inappropriately signed shifts
|
|
|
|
@ -45,8 +47,6 @@ |
|
|
|
|
// 1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float (interleaved was correct)
|
|
|
|
|
// 1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in >2-channel;
|
|
|
|
|
// (API change) report sample rate for decode-full-file funcs
|
|
|
|
|
// 0.99996 - - bracket #include <malloc.h> for macintosh compilation
|
|
|
|
|
// 0.99995 - - avoid alias-optimization issue in float-to-int conversion
|
|
|
|
|
//
|
|
|
|
|
// See end of file for full version history.
|
|
|
|
|
|
|
|
|
@ -155,10 +155,10 @@ extern unsigned int stb_vorbis_get_file_offset(stb_vorbis *f); |
|
|
|
|
// specification does not bound the size of an individual frame.
|
|
|
|
|
|
|
|
|
|
extern stb_vorbis *stb_vorbis_open_pushdata( |
|
|
|
|
unsigned char *datablock, int datablock_length_in_bytes, |
|
|
|
|
const unsigned char * datablock, int datablock_length_in_bytes, |
|
|
|
|
int *datablock_memory_consumed_in_bytes, |
|
|
|
|
int *error, |
|
|
|
|
stb_vorbis_alloc *alloc_buffer); |
|
|
|
|
const stb_vorbis_alloc *alloc_buffer); |
|
|
|
|
// create a vorbis decoder by passing in the initial data block containing
|
|
|
|
|
// the ogg&vorbis headers (you don't need to do parse them, just provide
|
|
|
|
|
// the first N bytes of the file--you're told if it's not enough, see below)
|
|
|
|
@ -169,7 +169,8 @@ extern stb_vorbis *stb_vorbis_open_pushdata( |
|
|
|
|
// incomplete and you need to pass in a larger block from the start of the file
|
|
|
|
|
|
|
|
|
|
extern int stb_vorbis_decode_frame_pushdata( |
|
|
|
|
stb_vorbis *f, unsigned char *datablock, int datablock_length_in_bytes, |
|
|
|
|
stb_vorbis *f, |
|
|
|
|
const unsigned char *datablock, int datablock_length_in_bytes, |
|
|
|
|
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
|
|
|
|
@ -233,18 +234,18 @@ extern int stb_vorbis_decode_memory(const unsigned char *mem, int len, int *chan |
|
|
|
|
// When you're done with it, just free() the pointer returned in *output.
|
|
|
|
|
|
|
|
|
|
extern stb_vorbis * stb_vorbis_open_memory(const unsigned char *data, int len, |
|
|
|
|
int *error, stb_vorbis_alloc *alloc_buffer); |
|
|
|
|
int *error, const stb_vorbis_alloc *alloc_buffer); |
|
|
|
|
// create an ogg vorbis decoder from an ogg vorbis stream in memory (note
|
|
|
|
|
// this must be the entire stream!). on failure, returns NULL and sets *error
|
|
|
|
|
|
|
|
|
|
#ifndef STB_VORBIS_NO_STDIO |
|
|
|
|
extern stb_vorbis * stb_vorbis_open_filename(const char *filename, |
|
|
|
|
int *error, stb_vorbis_alloc *alloc_buffer); |
|
|
|
|
int *error, const stb_vorbis_alloc *alloc_buffer); |
|
|
|
|
// create an ogg vorbis decoder from a filename via fopen(). on failure,
|
|
|
|
|
// returns NULL and sets *error (possibly to VORBIS_file_open_failure).
|
|
|
|
|
|
|
|
|
|
extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close, |
|
|
|
|
int *error, stb_vorbis_alloc *alloc_buffer); |
|
|
|
|
int *error, const stb_vorbis_alloc *alloc_buffer); |
|
|
|
|
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
|
|
|
|
|
// the _current_ seek point (ftell). on failure, returns NULL and sets *error.
|
|
|
|
|
// note that stb_vorbis must "own" this stream; if you seek it in between
|
|
|
|
@ -254,7 +255,7 @@ extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close, |
|
|
|
|
// function, stb_vorbis_open_file_section(), to limit it.
|
|
|
|
|
|
|
|
|
|
extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_close, |
|
|
|
|
int *error, stb_vorbis_alloc *alloc_buffer, unsigned int len); |
|
|
|
|
int *error, const stb_vorbis_alloc *alloc_buffer, unsigned int len); |
|
|
|
|
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
|
|
|
|
|
// the _current_ seek point (ftell); the stream will be of length 'len' bytes.
|
|
|
|
|
// on failure, returns NULL and sets *error. note that stb_vorbis must "own"
|
|
|
|
@ -292,15 +293,17 @@ extern int stb_vorbis_get_frame_float(stb_vorbis *f, int *channels, float ***out |
|
|
|
|
extern int stb_vorbis_get_frame_short_interleaved(stb_vorbis *f, int num_c, short *buffer, int num_shorts); |
|
|
|
|
extern int stb_vorbis_get_frame_short (stb_vorbis *f, int num_c, short **buffer, int num_samples); |
|
|
|
|
#endif |
|
|
|
|
// decode the next frame and return the number of samples per channel. the
|
|
|
|
|
// data is coerced to the number of channels you request according to the
|
|
|
|
|
// decode the next frame and return the number of *samples* per channel.
|
|
|
|
|
// Note that for interleaved data, you pass in the number of shorts (the
|
|
|
|
|
// size of your array), but the return value is the number of samples per
|
|
|
|
|
// channel, not the total number of samples.
|
|
|
|
|
//
|
|
|
|
|
// The data is coerced to the number of channels you request according to the
|
|
|
|
|
// channel coercion rules (see below). You must pass in the size of your
|
|
|
|
|
// buffer(s) so that stb_vorbis will not overwrite the end of the buffer.
|
|
|
|
|
// The maximum buffer size needed can be gotten from get_info(); however,
|
|
|
|
|
// the Vorbis I specification implies an absolute maximum of 4096 samples
|
|
|
|
|
// per channel. Note that for interleaved data, you pass in the number of
|
|
|
|
|
// shorts (the size of your array), but the return value is the number of
|
|
|
|
|
// samples per channel, not the total number of samples.
|
|
|
|
|
// per channel.
|
|
|
|
|
|
|
|
|
|
// Channel coercion rules:
|
|
|
|
|
// Let M be the number of channels requested, and N the number of channels present,
|
|
|
|
@ -367,7 +370,7 @@ enum STBVorbisError |
|
|
|
|
VORBIS_invalid_first_page, |
|
|
|
|
VORBIS_bad_packet_type, |
|
|
|
|
VORBIS_cant_find_last_page, |
|
|
|
|
VORBIS_seek_failed, |
|
|
|
|
VORBIS_seek_failed |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -488,14 +491,8 @@ enum STBVorbisError |
|
|
|
|
// 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
|
|
|
|
@ -556,11 +553,26 @@ enum STBVorbisError |
|
|
|
|
#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 |
|
|
|
@ -577,6 +589,13 @@ enum STBVorbisError |
|
|
|
|
#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) |
|
|
|
|
|
|
|
|
@ -593,11 +612,7 @@ typedef signed int int32; |
|
|
|
|
#define FALSE 0 |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifdef STB_VORBIS_CODEBOOK_FLOATS |
|
|
|
|
typedef float codetype; |
|
|
|
|
#else |
|
|
|
|
typedef uint16 codetype; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
// @NOTE
|
|
|
|
|
//
|
|
|
|
@ -831,13 +846,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) |
|
|
|
@ -904,7 +912,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); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1055,10 +1063,12 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values) |
|
|
|
|
while (z > 0 && !available[z]) --z; |
|
|
|
|
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)); |
|
|
|
@ -1576,7 +1586,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) |
|
|
|
@ -1584,7 +1594,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) { |
|
|
|
@ -1692,15 +1704,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) |
|
|
|
|
{ |
|
|
|
@ -1892,7 +1898,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) { |
|
|
|
@ -1904,7 +1909,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; |
|
|
|
@ -2076,15 +2081,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]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -2123,7 +2130,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); |
|
|
|
@ -2135,11 +2143,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; |
|
|
|
@ -2157,7 +2163,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 |
|
|
|
@ -2168,23 +2173,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 |
|
|
|
@ -2217,10 +2219,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; |
|
|
|
@ -2259,10 +2259,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; |
|
|
|
@ -2277,7 +2275,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; |
|
|
|
@ -2326,7 +2324,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); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -3140,13 +3138,16 @@ static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *f |
|
|
|
|
int hx = g->Xlist[j]; |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
@ -3217,6 +3218,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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -3235,7 +3237,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; |
|
|
|
@ -3327,7 +3330,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) |
|
|
|
@ -3340,6 +3343,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]; |
|
|
|
@ -3364,9 +3368,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]; |
|
|
|
@ -3387,10 +3391,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); |
|
|
|
@ -3410,10 +3414,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
|
|
|
|
@ -3455,7 +3459,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; |
|
|
|
@ -3463,6 +3467,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; |
|
|
|
|
} |
|
|
|
@ -3480,6 +3485,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; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -3645,14 +3652,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
|
|
|
|
@ -3701,6 +3709,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); |
|
|
|
@ -3712,6 +3721,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 |
|
|
|
@ -3736,6 +3747,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; |
|
|
|
|
} |
|
|
|
@ -3770,6 +3783,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); |
|
|
|
@ -3815,6 +3829,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) { |
|
|
|
@ -3828,6 +3843,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) { |
|
|
|
@ -3839,6 +3855,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; |
|
|
|
@ -3848,21 +3865,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); |
|
|
|
@ -3871,28 +3889,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); |
|
|
|
|
if (c->multiplicands == NULL) { setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); } |
|
|
|
|
#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 |
|
|
|
|
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)
|
|
|
|
@ -3988,9 +4003,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); |
|
|
|
@ -4171,6 +4188,7 @@ static void vorbis_deinit(stb_vorbis *p) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (p->codebooks) { |
|
|
|
|
CHECK(p); |
|
|
|
|
for (i=0; i < p->codebook_count; ++i) { |
|
|
|
|
Codebook *c = p->codebooks + i; |
|
|
|
|
setup_free(p, c->codeword_lengths); |
|
|
|
@ -4189,6 +4207,7 @@ static void vorbis_deinit(stb_vorbis *p) |
|
|
|
|
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]); |
|
|
|
@ -4216,7 +4235,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) { |
|
|
|
@ -4374,11 +4393,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; |
|
|
|
@ -4388,11 +4407,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
|
|
|
|
@ -4444,14 +4463,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) |
|
|
|
@ -4971,7 +4990,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); |
|
|
|
@ -4992,7 +5011,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); |
|
|
|
@ -5002,7 +5021,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)
|
|
|
|
@ -5012,7 +5031,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; |
|
|
|
@ -5392,6 +5411,8 @@ 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 |
|
|
|
|