-// Ogg Vorbis audio decoder - v1.19 - public domain
+// Ogg Vorbis audio decoder - v1.22 - public domain
// http://nothings.org/stb_vorbis/
//
// Original version written by Sean Barrett in 2007.
// Bernhard Wodo Evan Balster github:alxprd
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot
// Phillip Bennefall Rohit Thiago Goulart
-// github:manxorist saga musix github:infatum
+// github:manxorist Saga Musix github:infatum
// Timur Gagiev Maxwell Koo Peter Waller
-// github:audinowho Dougall Johnson
+// github:audinowho Dougall Johnson David Reid
+// github:Clownacy Pedro J. Estebanez Remi Verschelde
+// AnthoFoxo github:morlat Gabriel Ravier
//
// Partial history:
+// 1.22 - 2021-07-11 - various small fixes
+// 1.21 - 2021-07-02 - fix bug for files with no comments
+// 1.20 - 2020-07-11 - several small fixes
// 1.19 - 2020-02-05 - warnings
// 1.18 - 2020-02-02 - fix seek bugs; parse header comments; misc warnings etc.
// 1.17 - 2019-07-08 - fix CVE-2019-13217..CVE-2019-13223 (by ForAllSecure)
// channel. In other words, (*output)[0][0] contains the first sample from
// the first channel, and (*output)[1][0] contains the first sample from
// the second channel.
+//
+// *output points into stb_vorbis's internal output buffer storage; these
+// buffers are owned by stb_vorbis and application code should not free
+// them or modify their contents. They are transient and will be overwritten
+// once you ask for more data to get decoded, so be sure to grab any data
+// you need before then.
extern void stb_vorbis_flush_pushdata(stb_vorbis *f);
// inform stb_vorbis that your next datablock will not be contiguous with
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <malloc.h>
#endif
- #if defined(__linux__) || defined(__linux) || defined(__EMSCRIPTEN__)
+ #if defined(__linux__) || defined(__linux) || defined(__sun__) || defined(__EMSCRIPTEN__) || defined(__NEWLIB__)
#include <alloca.h>
#endif
#else // STB_VORBIS_NO_CRT
#undef __forceinline
#endif
#define __forceinline
- #ifdef alloca
- #undef alloca
- #endif
+ #ifndef alloca
#define alloca __builtin_alloca
+ #endif
#elif !defined(_MSC_VER)
#if __GNUC__
#define __forceinline inline
typedef float codetype;
+#ifdef _MSC_VER
+#define STBV_NOTUSED(v) (void)(v)
+#else
+#define STBV_NOTUSED(v) (void)sizeof(v)
+#endif
+
// @NOTE
//
// Some arrays below are tagged "//varies", which means it's actually
static void setup_temp_free(vorb *f, void *p, int sz)
{
if (f->alloc.alloc_buffer) {
- f->temp_offset += (sz+3)&~3;
+ f->temp_offset += (sz+7)&~7;
return;
}
free(p);
uint32 sign = x & 0x80000000;
uint32 exp = (x & 0x7fe00000) >> 21;
double res = sign ? -(double)mantissa : (double)mantissa;
- return (float) ldexp((float)res, exp-788);
+ return (float) ldexp((float)res, (int)exp-788);
}
// find the first entry
for (k=0; k < n; ++k) if (len[k] < NO_CODE) break;
if (k == n) { assert(c->sorted_entries == 0); return TRUE; }
+ assert(len[k] < 32); // no error return required, code reading lens checks this
// add to the list
add_entry(c, 0, k, m++, len[k], values);
// add all available leaves
uint32 res;
int z = len[i], y;
if (z == NO_CODE) continue;
+ assert(z < 32); // no error return required, code reading lens checks this
// find lowest available leaf (should always be earliest,
// which is what the specification calls for)
// note that this property, and the fact we can never have
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);
// propagate 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));
f->valid_bits += 8;
}
}
- if (f->valid_bits < 0) return 0;
+
+ assert(f->valid_bits >= n);
z = f->acc & ((1 << n)-1);
f->acc >>= n;
f->valid_bits -= n;
while (z > base) {
float k00,k11;
-
- k00 = z[-0] - z[-8];
- k11 = z[-1] - z[-9];
- z[-0] = z[-0] + z[-8];
- z[-1] = z[-1] + z[-9];
- z[-8] = k00;
- z[-9] = k11 ;
-
- k00 = z[ -2] - z[-10];
- k11 = z[ -3] - z[-11];
- z[ -2] = z[ -2] + z[-10];
- z[ -3] = z[ -3] + z[-11];
- z[-10] = (k00+k11) * A2;
- z[-11] = (k11-k00) * A2;
-
- k00 = z[-12] - z[ -4]; // reverse to avoid a unary negation
+ float l00,l11;
+
+ k00 = z[-0] - z[ -8];
+ k11 = z[-1] - z[ -9];
+ l00 = z[-2] - z[-10];
+ l11 = z[-3] - z[-11];
+ z[ -0] = z[-0] + z[ -8];
+ z[ -1] = z[-1] + z[ -9];
+ z[ -2] = z[-2] + z[-10];
+ z[ -3] = z[-3] + z[-11];
+ z[ -8] = k00;
+ z[ -9] = k11;
+ z[-10] = (l00+l11) * A2;
+ z[-11] = (l11-l00) * A2;
+
+ k00 = z[ -4] - z[-12];
k11 = z[ -5] - z[-13];
+ l00 = z[ -6] - z[-14];
+ l11 = z[ -7] - z[-15];
z[ -4] = z[ -4] + z[-12];
z[ -5] = z[ -5] + z[-13];
- z[-12] = k11;
- z[-13] = k00;
-
- k00 = z[-14] - z[ -6]; // reverse to avoid a unary negation
- k11 = z[ -7] - z[-15];
z[ -6] = z[ -6] + z[-14];
z[ -7] = z[ -7] + z[-15];
- z[-14] = (k00+k11) * A2;
- z[-15] = (k00-k11) * A2;
+ z[-12] = k11;
+ z[-13] = -k00;
+ z[-14] = (l11-l00) * A2;
+ z[-15] = (l00+l11) * -A2;
iter_54(z);
iter_54(z-8);
for (q=1; q < g->values; ++q) {
j = g->sorted_order[q];
#ifndef STB_VORBIS_NO_DEFER_FLOOR
+ STBV_NOTUSED(step2_flag);
if (finalY[j] >= 0)
#else
if (step2_flag[j])
// WINDOWING
+ STBV_NOTUSED(left_end);
n = f->blocksize[m->blockflag];
map = &f->mapping[m->mapping];
// this isn't to spec, but spec would require us to read ahead
// and decode the size of all current frames--could be done,
// but presumably it's not a commonly used feature
- f->current_loc = -n2; // start of first frame is positioned for discard
+ f->current_loc = 0u - n2; // start of first frame is positioned for discard (NB this is an intentional unsigned overflow/wrap-around)
// we might have to discard samples "from" the next frame too,
// if we're lapping a large block then a small at the start?
f->discard_samples_deferred = n - right_end;
//file vendor
len = get32_packet(f);
f->vendor = (char*)setup_malloc(f, sizeof(char) * (len+1));
+ if (f->vendor == NULL) return error(f, VORBIS_outofmem);
for(i=0; i < len; ++i) {
f->vendor[i] = get8_packet(f);
}
f->vendor[len] = (char)'\0';
//user comments
f->comment_list_length = get32_packet(f);
- f->comment_list = (char**)setup_malloc(f, sizeof(char*) * (f->comment_list_length));
+ f->comment_list = NULL;
+ if (f->comment_list_length > 0)
+ {
+ f->comment_list = (char**) setup_malloc(f, sizeof(char*) * (f->comment_list_length));
+ if (f->comment_list == NULL) return error(f, VORBIS_outofmem);
+ }
for(i=0; i < f->comment_list_length; ++i) {
len = get32_packet(f);
f->comment_list[i] = (char*)setup_malloc(f, sizeof(char) * (len+1));
+ if (f->comment_list[i] == NULL) return error(f, VORBIS_outofmem);
for(j=0; j < len; ++j) {
f->comment_list[i][j] = get8_packet(f);
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;
+ float val = mults[off]*c->delta_value + c->minimum_value + last;
c->multiplicands[j*c->dimensions + k] = val;
if (c->sequence_p)
last = val;
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;
+ g->subclass_books[j][k] = (int16)get_bits(f,8)-1;
if (g->subclass_books[j][k] >= f->codebook_count) return error(f, VORBIS_invalid_setup);
}
}
memset(p, 0, sizeof(*p)); // NULL out all malloc'd pointers to start
if (z) {
p->alloc = *z;
- p->alloc.alloc_buffer_length_in_bytes = (p->alloc.alloc_buffer_length_in_bytes+3) & ~3;
+ p->alloc.alloc_buffer_length_in_bytes &= ~7;
p->temp_offset = p->alloc.alloc_buffer_length_in_bytes;
}
p->eof = 0;
*error = VORBIS_need_more_data;
else
*error = p.error;
+ vorbis_deinit(&p);
return NULL;
}
f = vorbis_alloc(&p);
header[i] = get8(f);
if (f->eof) return 0;
if (header[4] != 0) goto invalid;
- goal = header[22] + (header[23] << 8) + (header[24]<<16) + (header[25]<<24);
+ goal = header[22] + (header[23] << 8) + (header[24]<<16) + ((uint32)header[25]<<24);
for (i=22; i < 26; ++i)
header[i] = 0;
crc = 0;
// set. whoops!
break;
}
- previous_safe = last_page_loc+1;
+ //previous_safe = last_page_loc+1; // NOTE: not used after this point, but note for debugging
last_page_loc = stb_vorbis_get_file_offset(f);
}
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;
+ if (!data) {
+ if (error) *error = VORBIS_unexpected_eof;
+ return NULL;
+ }
vorbis_init(&p, alloc);
p.stream = (uint8 *) data;
p.stream_end = (uint8 *) data + len;
static void compute_samples(int mask, short *output, int num_c, float **data, int d_offset, int len)
{
- #define BUFFER_SIZE 32
- float buffer[BUFFER_SIZE];
- int i,j,o,n = BUFFER_SIZE;
+ #define STB_BUFFER_SIZE 32
+ float buffer[STB_BUFFER_SIZE];
+ int i,j,o,n = STB_BUFFER_SIZE;
check_endianness();
- for (o = 0; o < len; o += BUFFER_SIZE) {
+ for (o = 0; o < len; o += STB_BUFFER_SIZE) {
memset(buffer, 0, sizeof(buffer));
if (o + n > len) n = len - o;
for (j=0; j < num_c; ++j) {
output[o+i] = v;
}
}
+ #undef STB_BUFFER_SIZE
}
static void compute_stereo_samples(short *output, int num_c, float **data, int d_offset, int len)
{
- #define BUFFER_SIZE 32
- float buffer[BUFFER_SIZE];
- int i,j,o,n = BUFFER_SIZE >> 1;
+ #define STB_BUFFER_SIZE 32
+ float buffer[STB_BUFFER_SIZE];
+ int i,j,o,n = STB_BUFFER_SIZE >> 1;
// o is the offset in the source data
check_endianness();
- for (o = 0; o < len; o += BUFFER_SIZE >> 1) {
+ for (o = 0; o < len; o += STB_BUFFER_SIZE >> 1) {
// o2 is the offset in the output data
int o2 = o << 1;
memset(buffer, 0, sizeof(buffer));
output[o2+i] = v;
}
}
+ #undef STB_BUFFER_SIZE
}
static void convert_samples_short(int buf_c, short **buffer, int b_offset, int data_c, float **data, int d_offset, int samples)
float **outputs;
int len = num_shorts / channels;
int n=0;
- int z = f->channels;
- if (z > channels) z = channels;
while (n < len) {
int k = f->channel_buffer_end - f->channel_buffer_start;
if (n+k >= len) k = len - n;
{
float **outputs;
int n=0;
- int z = f->channels;
- if (z > channels) z = channels;
while (n < len) {
int k = f->channel_buffer_end - f->channel_buffer_start;
if (n+k >= len) k = len - n;