gosu 0.10.5.pre1 → 0.10.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/COPYING +1 -8
- data/Gosu/Version.hpp +2 -2
- data/ext/gosu/extconf.rb +1 -1
- data/ext/gosu/gosu_wrap.cxx +131 -93
- data/ext/gosu/gosu_wrap.h +1 -1
- data/src/Bitmap/BitmapIO.cpp +2 -0
- data/src/Graphics/Macro.cpp +2 -0
- data/src/stb_image.h +170 -98
- data/src/stb_image_write.h +367 -104
- data/src/stb_vorbis.c +290 -308
- metadata +8 -8
data/src/stb_vorbis.c
CHANGED
@@ -1,35 +1,43 @@
|
|
1
|
-
// Ogg Vorbis audio decoder - v1.
|
1
|
+
// Ogg Vorbis audio decoder - v1.06 - public domain
|
2
2
|
// http://nothings.org/stb_vorbis/
|
3
3
|
//
|
4
4
|
// Written by Sean Barrett in 2007, last updated in 2014
|
5
5
|
// Sponsored by RAD Game Tools.
|
6
6
|
//
|
7
|
-
//
|
8
|
-
//
|
7
|
+
// LICENSE
|
8
|
+
//
|
9
|
+
// This software is in the public domain. Where that dedication is not
|
10
|
+
// recognized, you are granted a perpetual, irrevocable license to copy,
|
11
|
+
// distribute, and modify this file as you see fit.
|
9
12
|
//
|
10
13
|
// No warranty for any purpose is expressed or implied by the author (nor
|
11
14
|
// by RAD Game Tools). Report bugs and send enhancements to the author.
|
12
15
|
//
|
13
16
|
// Limitations:
|
14
17
|
//
|
15
|
-
// - seeking not supported except manually via PUSHDATA api
|
16
18
|
// - floor 0 not supported (used in old ogg vorbis files pre-2004)
|
17
19
|
// - lossless sample-truncation at beginning ignored
|
18
20
|
// - cannot concatenate multiple vorbis streams
|
19
21
|
// - sample positions are 32-bit, limiting seekable 192Khz
|
20
22
|
// files to around 6 hours (Ogg supports 64-bit)
|
21
23
|
//
|
24
|
+
// Feature contributors:
|
25
|
+
// Dougall Johnson (sample-exact seeking)
|
26
|
+
//
|
22
27
|
// Bugfix/warning contributors:
|
23
28
|
// Terje Mathisen Niklas Frykholm Andy Hill
|
24
29
|
// Casey Muratori John Bolton Gargaj
|
25
30
|
// Laurent Gomila Marc LeBlanc Ronny Chevalier
|
26
|
-
// Bernhard Wodo Evan Balster
|
31
|
+
// Bernhard Wodo Evan Balster "alxprd"@github
|
27
32
|
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot
|
28
33
|
// (If you reported a bug but do not appear in this list, it is because
|
29
34
|
// someone else reported the bug before you. There were too many of you to
|
30
35
|
// list them all because I was lax about updating for a long time, sorry.)
|
31
36
|
//
|
32
37
|
// Partial history:
|
38
|
+
// 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson)
|
39
|
+
// some crash fixes when out of memory or with corrupt files
|
40
|
+
// fix some inappropriately signed shifts
|
33
41
|
// 1.05 - 2015/04/19 - don't define __forceinline if it's redundant
|
34
42
|
// 1.04 - 2014/08/27 - fix missing const-correct case in API
|
35
43
|
// 1.03 - 2014/08/07 - warning fixes
|
@@ -256,7 +264,6 @@ extern stb_vorbis * stb_vorbis_open_file_section(FILE *f, int close_handle_on_cl
|
|
256
264
|
|
257
265
|
extern int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number);
|
258
266
|
extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number);
|
259
|
-
// NOT WORKING YET
|
260
267
|
// these functions seek in the Vorbis file to (approximately) 'sample_number'.
|
261
268
|
// after calling seek_frame(), the next call to get_frame_*() will include
|
262
269
|
// the specified sample. after calling stb_vorbis_seek(), the next call to
|
@@ -265,8 +272,7 @@ extern int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number);
|
|
265
272
|
// you can also use seek_frame().
|
266
273
|
|
267
274
|
extern void stb_vorbis_seek_start(stb_vorbis *f);
|
268
|
-
// this function is equivalent to stb_vorbis_seek(f,0)
|
269
|
-
// actually works
|
275
|
+
// this function is equivalent to stb_vorbis_seek(f,0)
|
270
276
|
|
271
277
|
extern unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f);
|
272
278
|
extern float stb_vorbis_stream_length_in_seconds(stb_vorbis *f);
|
@@ -711,8 +717,6 @@ typedef struct
|
|
711
717
|
typedef struct
|
712
718
|
{
|
713
719
|
uint32 page_start, page_end;
|
714
|
-
uint32 after_previous_page_start;
|
715
|
-
uint32 first_decoded_sample;
|
716
720
|
uint32 last_decoded_sample;
|
717
721
|
} ProbedPage;
|
718
722
|
|
@@ -932,7 +936,7 @@ static void crc32_init(void)
|
|
932
936
|
int i,j;
|
933
937
|
uint32 s;
|
934
938
|
for(i=0; i < 256; i++) {
|
935
|
-
for (s=i<<24, j=0; j < 8; ++j)
|
939
|
+
for (s=(uint32) i << 24, j=0; j < 8; ++j)
|
936
940
|
s = (s << 1) ^ (s >= (1U<<31) ? CRC32_POLY : 0);
|
937
941
|
crc_table[i] = s;
|
938
942
|
}
|
@@ -1033,7 +1037,7 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)
|
|
1033
1037
|
add_entry(c, 0, k, m++, len[k], values);
|
1034
1038
|
// add all available leaves
|
1035
1039
|
for (i=1; i <= len[k]; ++i)
|
1036
|
-
available[i] =
|
1040
|
+
available[i] = 1U << (32-i);
|
1037
1041
|
// note that the above code treats the first case specially,
|
1038
1042
|
// but it's really the same as the following code, so they
|
1039
1043
|
// could probably be combined (except the initial code is 0,
|
@@ -1049,7 +1053,7 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)
|
|
1049
1053
|
// trivial to prove, but it seems true and the assert never
|
1050
1054
|
// fires, so!
|
1051
1055
|
while (z > 0 && !available[z]) --z;
|
1052
|
-
if (z == 0) {
|
1056
|
+
if (z == 0) { return FALSE; }
|
1053
1057
|
res = available[z];
|
1054
1058
|
available[z] = 0;
|
1055
1059
|
add_entry(c, bit_reverse(res), i, m++, len[i], values);
|
@@ -1289,7 +1293,7 @@ static uint32 get32(vorb *f)
|
|
1289
1293
|
x = get8(f);
|
1290
1294
|
x += get8(f) << 8;
|
1291
1295
|
x += get8(f) << 16;
|
1292
|
-
x += get8(f) << 24;
|
1296
|
+
x += (uint32) get8(f) << 24;
|
1293
1297
|
return x;
|
1294
1298
|
}
|
1295
1299
|
|
@@ -1420,8 +1424,6 @@ static int start_page_no_capturepattern(vorb *f)
|
|
1420
1424
|
len += 27 + f->segment_count;
|
1421
1425
|
p.page_start = f->first_audio_page_offset;
|
1422
1426
|
p.page_end = p.page_start + len;
|
1423
|
-
p.after_previous_page_start = p.page_start;
|
1424
|
-
p.first_decoded_sample = 0;
|
1425
1427
|
p.last_decoded_sample = loc0;
|
1426
1428
|
f->p_first = p;
|
1427
1429
|
}
|
@@ -1564,7 +1566,7 @@ static __forceinline void prep_huffman(vorb *f)
|
|
1564
1566
|
if (f->last_seg && !f->bytes_in_seg) return;
|
1565
1567
|
z = get8_packet_raw(f);
|
1566
1568
|
if (z == EOP) return;
|
1567
|
-
f->acc += z << f->valid_bits;
|
1569
|
+
f->acc += (unsigned) z << f->valid_bits;
|
1568
1570
|
f->valid_bits += 8;
|
1569
1571
|
} while (f->valid_bits <= 24);
|
1570
1572
|
}
|
@@ -3136,7 +3138,8 @@ static int do_floor(vorb *f, Mapping *map, int i, int n, float *target, YTYPE *f
|
|
3136
3138
|
{
|
3137
3139
|
int hy = finalY[j] * g->floor1_multiplier;
|
3138
3140
|
int hx = g->Xlist[j];
|
3139
|
-
|
3141
|
+
if (lx != hx)
|
3142
|
+
draw_line(target, lx,ly, hx,hy, n2);
|
3140
3143
|
lx = hx, ly = hy;
|
3141
3144
|
}
|
3142
3145
|
}
|
@@ -3428,9 +3431,15 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
|
|
3428
3431
|
f->current_loc_valid = TRUE;
|
3429
3432
|
f->first_decode = FALSE;
|
3430
3433
|
} else if (f->discard_samples_deferred) {
|
3431
|
-
|
3432
|
-
|
3433
|
-
|
3434
|
+
if (f->discard_samples_deferred >= right_start - left_start) {
|
3435
|
+
f->discard_samples_deferred -= (right_start - left_start);
|
3436
|
+
left_start = right_start;
|
3437
|
+
*p_left = left_start;
|
3438
|
+
} else {
|
3439
|
+
left_start += f->discard_samples_deferred;
|
3440
|
+
*p_left = left_start;
|
3441
|
+
f->discard_samples_deferred = 0;
|
3442
|
+
}
|
3434
3443
|
} else if (f->previous_length == 0 && f->current_loc_valid) {
|
3435
3444
|
// we're recovering from a seek... that means we're going to discard
|
3436
3445
|
// the samples from this packet even though we know our position from
|
@@ -3739,6 +3748,7 @@ static int start_decoder(vorb *f)
|
|
3739
3748
|
f->setup_temp_memory_required = c->entries;
|
3740
3749
|
|
3741
3750
|
c->codeword_lengths = (uint8 *) setup_malloc(f, c->entries);
|
3751
|
+
if (c->codeword_lengths == NULL) return error(f, VORBIS_outofmem);
|
3742
3752
|
memcpy(c->codeword_lengths, lengths, c->entries);
|
3743
3753
|
setup_temp_free(f, lengths, c->entries); // note this is only safe if there have been no intervening temp mallocs!
|
3744
3754
|
lengths = c->codeword_lengths;
|
@@ -3786,10 +3796,13 @@ static int start_decoder(vorb *f)
|
|
3786
3796
|
if (c->sorted_entries) {
|
3787
3797
|
// allocate an extra slot for sentinels
|
3788
3798
|
c->sorted_codewords = (uint32 *) setup_malloc(f, sizeof(*c->sorted_codewords) * (c->sorted_entries+1));
|
3799
|
+
if (c->sorted_codewords == NULL) return error(f, VORBIS_outofmem);
|
3789
3800
|
// allocate an extra slot at the front so that c->sorted_values[-1] is defined
|
3790
3801
|
// so that we can catch that case without an extra if
|
3791
3802
|
c->sorted_values = ( int *) setup_malloc(f, sizeof(*c->sorted_values ) * (c->sorted_entries+1));
|
3792
|
-
if (c->sorted_values
|
3803
|
+
if (c->sorted_values == NULL) return error(f, VORBIS_outofmem);
|
3804
|
+
++c->sorted_values;
|
3805
|
+
c->sorted_values[-1] = -1;
|
3793
3806
|
compute_sorted_huffman(c, lengths, values);
|
3794
3807
|
}
|
3795
3808
|
|
@@ -3859,6 +3872,7 @@ static int start_decoder(vorb *f)
|
|
3859
3872
|
#endif
|
3860
3873
|
{
|
3861
3874
|
c->multiplicands = (codetype *) setup_malloc(f, sizeof(c->multiplicands[0]) * c->lookup_values);
|
3875
|
+
if (c->multiplicands == NULL) { setup_temp_free(f, mults,sizeof(mults[0])*c->lookup_values); return error(f, VORBIS_outofmem); }
|
3862
3876
|
#ifndef STB_VORBIS_CODEBOOK_FLOATS
|
3863
3877
|
memcpy(c->multiplicands, mults, sizeof(c->multiplicands[0]) * c->lookup_values);
|
3864
3878
|
#else
|
@@ -3892,6 +3906,7 @@ static int start_decoder(vorb *f)
|
|
3892
3906
|
// Floors
|
3893
3907
|
f->floor_count = get_bits(f, 6)+1;
|
3894
3908
|
f->floor_config = (Floor *) setup_malloc(f, f->floor_count * sizeof(*f->floor_config));
|
3909
|
+
if (f->floor_config == NULL) return error(f, VORBIS_outofmem);
|
3895
3910
|
for (i=0; i < f->floor_count; ++i) {
|
3896
3911
|
f->floor_types[i] = get_bits(f, 16);
|
3897
3912
|
if (f->floor_types[i] > 1) return error(f, VORBIS_invalid_setup);
|
@@ -3963,7 +3978,9 @@ static int start_decoder(vorb *f)
|
|
3963
3978
|
|
3964
3979
|
// Residue
|
3965
3980
|
f->residue_count = get_bits(f, 6)+1;
|
3966
|
-
f->residue_config = (Residue *) setup_malloc(f, f->residue_count * sizeof(
|
3981
|
+
f->residue_config = (Residue *) setup_malloc(f, f->residue_count * sizeof(f->residue_config[0]));
|
3982
|
+
if (f->residue_config == NULL) return error(f, VORBIS_outofmem);
|
3983
|
+
memset(f->residue_config, 0, f->residue_count * sizeof(f->residue_config[0]));
|
3967
3984
|
for (i=0; i < f->residue_count; ++i) {
|
3968
3985
|
uint8 residue_cascade[64];
|
3969
3986
|
Residue *r = f->residue_config+i;
|
@@ -3982,6 +3999,7 @@ static int start_decoder(vorb *f)
|
|
3982
3999
|
residue_cascade[j] = high_bits*8 + low_bits;
|
3983
4000
|
}
|
3984
4001
|
r->residue_books = (short (*)[8]) setup_malloc(f, sizeof(r->residue_books[0]) * r->classifications);
|
4002
|
+
if (r->residue_books == NULL) return error(f, VORBIS_outofmem);
|
3985
4003
|
for (j=0; j < r->classifications; ++j) {
|
3986
4004
|
for (k=0; k < 8; ++k) {
|
3987
4005
|
if (residue_cascade[j] & (1 << k)) {
|
@@ -4001,6 +4019,7 @@ static int start_decoder(vorb *f)
|
|
4001
4019
|
int classwords = f->codebooks[r->classbook].dimensions;
|
4002
4020
|
int temp = j;
|
4003
4021
|
r->classdata[j] = (uint8 *) setup_malloc(f, sizeof(r->classdata[j][0]) * classwords);
|
4022
|
+
if (r->classdata[j] == NULL) return error(f, VORBIS_outofmem);
|
4004
4023
|
for (k=classwords-1; k >= 0; --k) {
|
4005
4024
|
r->classdata[j][k] = temp % r->classifications;
|
4006
4025
|
temp /= r->classifications;
|
@@ -4010,11 +4029,14 @@ static int start_decoder(vorb *f)
|
|
4010
4029
|
|
4011
4030
|
f->mapping_count = get_bits(f,6)+1;
|
4012
4031
|
f->mapping = (Mapping *) setup_malloc(f, f->mapping_count * sizeof(*f->mapping));
|
4032
|
+
if (f->mapping == NULL) return error(f, VORBIS_outofmem);
|
4033
|
+
memset(f->mapping, 0, f->mapping_count * sizeof(*f->mapping));
|
4013
4034
|
for (i=0; i < f->mapping_count; ++i) {
|
4014
4035
|
Mapping *m = f->mapping + i;
|
4015
4036
|
int mapping_type = get_bits(f,16);
|
4016
4037
|
if (mapping_type != 0) return error(f, VORBIS_invalid_setup);
|
4017
4038
|
m->chan = (MappingChannel *) setup_malloc(f, f->channels * sizeof(*m->chan));
|
4039
|
+
if (m->chan == NULL) return error(f, VORBIS_outofmem);
|
4018
4040
|
if (get_bits(f,1))
|
4019
4041
|
m->submaps = get_bits(f,4)+1;
|
4020
4042
|
else
|
@@ -4075,8 +4097,10 @@ static int start_decoder(vorb *f)
|
|
4075
4097
|
f->channel_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1);
|
4076
4098
|
f->previous_window[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2);
|
4077
4099
|
f->finalY[i] = (int16 *) setup_malloc(f, sizeof(int16) * longest_floorlist);
|
4100
|
+
if (f->channel_buffers[i] == NULL || f->previous_window[i] == NULL || f->finalY[i] == NULL) return error(f, VORBIS_outofmem);
|
4078
4101
|
#ifdef STB_VORBIS_NO_DEFER_FLOOR
|
4079
4102
|
f->floor_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2);
|
4103
|
+
if (f->floor_buffers[i] == NULL) return error(f, VORBIS_outofmem);
|
4080
4104
|
#endif
|
4081
4105
|
}
|
4082
4106
|
|
@@ -4134,14 +4158,16 @@ static int start_decoder(vorb *f)
|
|
4134
4158
|
static void vorbis_deinit(stb_vorbis *p)
|
4135
4159
|
{
|
4136
4160
|
int i,j;
|
4137
|
-
|
4138
|
-
|
4139
|
-
|
4140
|
-
|
4141
|
-
|
4142
|
-
|
4161
|
+
if (p->residue_config) {
|
4162
|
+
for (i=0; i < p->residue_count; ++i) {
|
4163
|
+
Residue *r = p->residue_config+i;
|
4164
|
+
if (r->classdata) {
|
4165
|
+
for (j=0; j < p->codebooks[r->classbook].entries; ++j)
|
4166
|
+
setup_free(p, r->classdata[j]);
|
4167
|
+
setup_free(p, r->classdata);
|
4168
|
+
}
|
4169
|
+
setup_free(p, r->residue_books);
|
4143
4170
|
}
|
4144
|
-
setup_free(p, r->residue_books);
|
4145
4171
|
}
|
4146
4172
|
|
4147
4173
|
if (p->codebooks) {
|
@@ -4158,10 +4184,12 @@ static void vorbis_deinit(stb_vorbis *p)
|
|
4158
4184
|
}
|
4159
4185
|
setup_free(p, p->floor_config);
|
4160
4186
|
setup_free(p, p->residue_config);
|
4161
|
-
|
4162
|
-
|
4163
|
-
|
4164
|
-
|
4187
|
+
if (p->mapping) {
|
4188
|
+
for (i=0; i < p->mapping_count; ++i)
|
4189
|
+
setup_free(p, p->mapping[i].chan);
|
4190
|
+
setup_free(p, p->mapping);
|
4191
|
+
}
|
4192
|
+
for (i=0; i < p->channels && i < STB_VORBIS_MAX_CHANNELS; ++i) {
|
4165
4193
|
setup_free(p, p->channel_buffers[i]);
|
4166
4194
|
setup_free(p, p->previous_window[i]);
|
4167
4195
|
#ifdef STB_VORBIS_NO_DEFER_FLOOR
|
@@ -4467,7 +4495,7 @@ static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last)
|
|
4467
4495
|
int n;
|
4468
4496
|
if (f->eof) return 0;
|
4469
4497
|
n = get8(f);
|
4470
|
-
if (n == 0x4f) { // page header
|
4498
|
+
if (n == 0x4f) { // page header candidate
|
4471
4499
|
unsigned int retry_loc = stb_vorbis_get_file_offset(f);
|
4472
4500
|
int i;
|
4473
4501
|
// check if we're off the end of a file_section stream
|
@@ -4531,37 +4559,30 @@ static uint32 vorbis_find_page(stb_vorbis *f, uint32 *end, uint32 *last)
|
|
4531
4559
|
}
|
4532
4560
|
}
|
4533
4561
|
|
4534
|
-
// seek is implemented with 'interpolation search'--this is like
|
4535
|
-
// binary search, but we use the data values to estimate the likely
|
4536
|
-
// location of the data item (plus a bit of a bias so when the
|
4537
|
-
// estimation is wrong we don't waste overly much time)
|
4538
4562
|
|
4539
4563
|
#define SAMPLE_unknown 0xffffffff
|
4540
4564
|
|
4565
|
+
// seeking is implemented with a binary search, which narrows down the range to
|
4566
|
+
// 64K, before using a linear search (because finding the synchronization
|
4567
|
+
// pattern can be expensive, and the chance we'd find the end page again is
|
4568
|
+
// relatively high for small ranges)
|
4569
|
+
//
|
4570
|
+
// two initial interpolation-style probes are used at the start of the search
|
4571
|
+
// to try to bound either side of the binary search sensibly, while still
|
4572
|
+
// working in O(log n) time if they fail.
|
4541
4573
|
|
4542
|
-
|
4543
|
-
// information about the sample at the END of the page.
|
4544
|
-
// therefore we COULD have the data we need in the current
|
4545
|
-
// page, and not know it. we could just use the end location
|
4546
|
-
// as our only knowledge for bounds, seek back, and eventually
|
4547
|
-
// the binary search finds it. or we can try to be smart and
|
4548
|
-
// not waste time trying to locate more pages. we try to be
|
4549
|
-
// smart, since this data is already in memory anyway, so
|
4550
|
-
// doing needless I/O would be crazy!
|
4551
|
-
static int vorbis_analyze_page(stb_vorbis *f, ProbedPage *z)
|
4574
|
+
static int get_seek_page_info(stb_vorbis *f, ProbedPage *z)
|
4552
4575
|
{
|
4553
4576
|
uint8 header[27], lacing[255];
|
4554
|
-
uint8 packet_type[255];
|
4555
|
-
int num_packet, packet_start;
|
4556
4577
|
int i,len;
|
4557
|
-
uint32 samples;
|
4558
4578
|
|
4559
4579
|
// record where the page starts
|
4560
4580
|
z->page_start = stb_vorbis_get_file_offset(f);
|
4561
4581
|
|
4562
4582
|
// parse the header
|
4563
4583
|
getn(f, header, 27);
|
4564
|
-
|
4584
|
+
if (header[0] != 'O' || header[1] != 'g' || header[2] != 'g' || header[3] != 'S')
|
4585
|
+
return 0;
|
4565
4586
|
getn(f, lacing, header[26]);
|
4566
4587
|
|
4567
4588
|
// determine the length of the payload
|
@@ -4573,304 +4594,265 @@ static int vorbis_analyze_page(stb_vorbis *f, ProbedPage *z)
|
|
4573
4594
|
z->page_end = z->page_start + 27 + header[26] + len;
|
4574
4595
|
|
4575
4596
|
// read the last-decoded sample out of the data
|
4576
|
-
z->last_decoded_sample = header[6] + (header[7] << 8) + (header[8] << 16) + (header[9] <<
|
4597
|
+
z->last_decoded_sample = header[6] + (header[7] << 8) + (header[8] << 16) + (header[9] << 24);
|
4577
4598
|
|
4578
|
-
|
4579
|
-
|
4580
|
-
|
4581
|
-
|
4582
|
-
set_file_offset(f, z->page_start);
|
4583
|
-
return 1;
|
4584
|
-
}
|
4585
|
-
|
4586
|
-
// scan through the frames to determine the sample-count of each one...
|
4587
|
-
// our goal is the sample # of the first fully-decoded sample on the
|
4588
|
-
// page, which is the first decoded sample of the 2nd packet
|
4599
|
+
// restore file state to where we were
|
4600
|
+
set_file_offset(f, z->page_start);
|
4601
|
+
return 1;
|
4602
|
+
}
|
4589
4603
|
|
4590
|
-
|
4604
|
+
// rarely used function to seek back to the preceeding page while finding the
|
4605
|
+
// start of a packet
|
4606
|
+
static int go_to_page_before(stb_vorbis *f, unsigned int limit_offset)
|
4607
|
+
{
|
4608
|
+
unsigned int previous_safe, end;
|
4591
4609
|
|
4592
|
-
|
4610
|
+
// now we want to seek back 64K from the limit
|
4611
|
+
if (limit_offset >= 65536 && limit_offset-65536 >= f->first_audio_page_offset)
|
4612
|
+
previous_safe = limit_offset - 65536;
|
4613
|
+
else
|
4614
|
+
previous_safe = f->first_audio_page_offset;
|
4593
4615
|
|
4594
|
-
|
4595
|
-
if (packet_start) {
|
4596
|
-
uint8 n,b;
|
4597
|
-
if (lacing[i] == 0) goto bail; // trying to read from zero-length packet
|
4598
|
-
n = get8(f);
|
4599
|
-
// if bottom bit is non-zero, we've got corruption
|
4600
|
-
if (n & 1) goto bail;
|
4601
|
-
n >>= 1;
|
4602
|
-
b = ilog(f->mode_count-1);
|
4603
|
-
n &= (1 << b)-1;
|
4604
|
-
if (n >= f->mode_count) goto bail;
|
4605
|
-
packet_type[num_packet++] = f->mode_config[n].blockflag;
|
4606
|
-
skip(f, lacing[i]-1);
|
4607
|
-
} else
|
4608
|
-
skip(f, lacing[i]);
|
4609
|
-
packet_start = (lacing[i] < 255);
|
4610
|
-
}
|
4611
|
-
|
4612
|
-
// now that we know the sizes of all the pages, we can start determining
|
4613
|
-
// how much sample data there is.
|
4614
|
-
|
4615
|
-
samples = 0;
|
4616
|
-
|
4617
|
-
// for the last packet, we step by its whole length, because the definition
|
4618
|
-
// is that we encoded the end sample loc of the 'last packet completed',
|
4619
|
-
// where 'completed' refers to packets being split, and we are left to guess
|
4620
|
-
// what 'end sample loc' means. we assume it means ignoring the fact that
|
4621
|
-
// the last half of the data is useless without windowing against the next
|
4622
|
-
// packet... (so it's not REALLY complete in that sense)
|
4623
|
-
if (num_packet > 1)
|
4624
|
-
samples += f->blocksize[packet_type[num_packet-1]];
|
4625
|
-
|
4626
|
-
for (i=num_packet-2; i >= 1; --i) {
|
4627
|
-
// now, for this packet, how many samples do we have that
|
4628
|
-
// do not overlap the following packet?
|
4629
|
-
if (packet_type[i] == 1)
|
4630
|
-
if (packet_type[i+1] == 1)
|
4631
|
-
samples += f->blocksize_1 >> 1;
|
4632
|
-
else
|
4633
|
-
samples += ((f->blocksize_1 - f->blocksize_0) >> 2) + (f->blocksize_0 >> 1);
|
4634
|
-
else
|
4635
|
-
samples += f->blocksize_0 >> 1;
|
4636
|
-
}
|
4637
|
-
// now, at this point, we've rewound to the very beginning of the
|
4638
|
-
// _second_ packet. if we entirely discard the first packet after
|
4639
|
-
// a seek, this will be exactly the right sample number. HOWEVER!
|
4640
|
-
// we can't as easily compute this number for the LAST page. The
|
4641
|
-
// only way to get the sample offset of the LAST page is to use
|
4642
|
-
// the end loc from the previous page. But what that returns us
|
4643
|
-
// is _exactly_ the place where we get our first non-overlapped
|
4644
|
-
// sample. (I think. Stupid spec for being ambiguous.) So for
|
4645
|
-
// consistency it's better to do that here, too. However, that
|
4646
|
-
// will then require us to NOT discard all of the first frame we
|
4647
|
-
// decode, in some cases, which means an even weirder frame size
|
4648
|
-
// and extra code. what a fucking pain.
|
4649
|
-
|
4650
|
-
// we're going to discard the first packet if we
|
4651
|
-
// start the seek here, so we don't care about it. (we could actually
|
4652
|
-
// do better; if the first packet is long, and the previous packet
|
4653
|
-
// is short, there's actually data in the first half of the first
|
4654
|
-
// packet that doesn't need discarding... but not worth paying the
|
4655
|
-
// effort of tracking that of that here and in the seeking logic)
|
4656
|
-
// except crap, if we infer it from the _previous_ packet's end
|
4657
|
-
// location, we DO need to use that definition... and we HAVE to
|
4658
|
-
// infer the start loc of the LAST packet from the previous packet's
|
4659
|
-
// end location. fuck you, ogg vorbis.
|
4660
|
-
|
4661
|
-
z->first_decoded_sample = z->last_decoded_sample - samples;
|
4616
|
+
set_file_offset(f, previous_safe);
|
4662
4617
|
|
4663
|
-
|
4664
|
-
|
4665
|
-
|
4618
|
+
while (vorbis_find_page(f, &end, NULL)) {
|
4619
|
+
if (end >= limit_offset && stb_vorbis_get_file_offset(f) < limit_offset)
|
4620
|
+
return 1;
|
4621
|
+
set_file_offset(f, end);
|
4622
|
+
}
|
4666
4623
|
|
4667
|
-
// restore file state to where we were
|
4668
|
-
bail:
|
4669
|
-
set_file_offset(f, z->page_start);
|
4670
4624
|
return 0;
|
4671
4625
|
}
|
4672
4626
|
|
4673
|
-
|
4674
|
-
|
4675
|
-
|
4676
|
-
|
4677
|
-
|
4678
|
-
|
4627
|
+
// implements the search logic for finding a page and starting decoding. if
|
4628
|
+
// the function succeeds, current_loc_valid will be true and current_loc will
|
4629
|
+
// be less than or equal to the provided sample number (the closer the
|
4630
|
+
// better).
|
4631
|
+
static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
|
4632
|
+
{
|
4633
|
+
ProbedPage left, right, mid;
|
4634
|
+
int i, start_seg_with_known_loc, end_pos, page_start;
|
4635
|
+
uint32 delta, stream_length, padding;
|
4636
|
+
double offset, bytes_per_sample;
|
4637
|
+
int probe = 0;
|
4638
|
+
|
4639
|
+
// find the last page and validate the target sample
|
4640
|
+
stream_length = stb_vorbis_stream_length_in_samples(f);
|
4641
|
+
if (stream_length == 0) return error(f, VORBIS_seek_without_length);
|
4642
|
+
if (sample_number > stream_length) return error(f, VORBIS_seek_invalid);
|
4643
|
+
|
4644
|
+
// this is the maximum difference between the window-center (which is the
|
4645
|
+
// actual granule position value), and the right-start (which the spec
|
4646
|
+
// indicates should be the granule position (give or take one)).
|
4647
|
+
padding = ((f->blocksize_1 - f->blocksize_0) >> 2);
|
4648
|
+
if (sample_number < padding)
|
4649
|
+
sample_number = 0;
|
4650
|
+
else
|
4651
|
+
sample_number -= padding;
|
4679
4652
|
|
4680
|
-
|
4681
|
-
|
4682
|
-
|
4683
|
-
|
4653
|
+
left = f->p_first;
|
4654
|
+
while (left.last_decoded_sample == ~0U) {
|
4655
|
+
// (untested) the first page does not have a 'last_decoded_sample'
|
4656
|
+
set_file_offset(f, left.page_end);
|
4657
|
+
if (!get_seek_page_info(f, &left)) goto error;
|
4658
|
+
}
|
4684
4659
|
|
4685
|
-
|
4660
|
+
right = f->p_last;
|
4661
|
+
assert(right.last_decoded_sample != ~0U);
|
4686
4662
|
|
4687
|
-
|
4688
|
-
|
4689
|
-
|
4690
|
-
|
4663
|
+
// starting from the start is handled differently
|
4664
|
+
if (sample_number <= left.last_decoded_sample) {
|
4665
|
+
stb_vorbis_seek_start(f);
|
4666
|
+
return 1;
|
4667
|
+
}
|
4691
4668
|
|
4669
|
+
while (left.page_end != right.page_start) {
|
4670
|
+
assert(left.page_end < right.page_start);
|
4671
|
+
// search range in bytes
|
4672
|
+
delta = right.page_start - left.page_end;
|
4673
|
+
if (delta <= 65536) {
|
4674
|
+
// there's only 64K left to search - handle it linearly
|
4675
|
+
set_file_offset(f, left.page_end);
|
4676
|
+
} else {
|
4677
|
+
if (probe < 2) {
|
4678
|
+
if (probe == 0) {
|
4679
|
+
// first probe (interpolate)
|
4680
|
+
double data_bytes = right.page_end - left.page_start;
|
4681
|
+
bytes_per_sample = data_bytes / right.last_decoded_sample;
|
4682
|
+
offset = left.page_start + bytes_per_sample * (sample_number - left.last_decoded_sample);
|
4683
|
+
} else {
|
4684
|
+
// second probe (try to bound the other side)
|
4685
|
+
double error = ((double) sample_number - mid.last_decoded_sample) * bytes_per_sample;
|
4686
|
+
if (error >= 0 && error < 8000) error = 8000;
|
4687
|
+
if (error < 0 && error > -8000) error = -8000;
|
4688
|
+
offset += error * 2;
|
4689
|
+
}
|
4692
4690
|
|
4693
|
-
|
4694
|
-
|
4695
|
-
|
4696
|
-
|
4697
|
-
|
4691
|
+
// ensure the offset is valid
|
4692
|
+
if (offset < left.page_end)
|
4693
|
+
offset = left.page_end;
|
4694
|
+
if (offset > right.page_start - 65536)
|
4695
|
+
offset = right.page_start - 65536;
|
4698
4696
|
|
4699
|
-
|
4700
|
-
|
4697
|
+
set_file_offset(f, (unsigned int) offset);
|
4698
|
+
} else {
|
4699
|
+
// binary search for large ranges (offset by 32K to ensure
|
4700
|
+
// we don't hit the right page)
|
4701
|
+
set_file_offset(f, left.page_end + (delta / 2) - 32768);
|
4702
|
+
}
|
4701
4703
|
|
4702
|
-
|
4703
|
-
|
4704
|
-
else
|
4705
|
-
start = left_start;
|
4704
|
+
if (!vorbis_find_page(f, NULL, NULL)) goto error;
|
4705
|
+
}
|
4706
4706
|
|
4707
|
-
|
4708
|
-
|
4709
|
-
|
4710
|
-
|
4707
|
+
for (;;) {
|
4708
|
+
if (!get_seek_page_info(f, &mid)) goto error;
|
4709
|
+
if (mid.last_decoded_sample != ~0U) break;
|
4710
|
+
// (untested) no frames end on this page
|
4711
|
+
set_file_offset(f, mid.page_end);
|
4712
|
+
assert(mid.page_start < right.page_start);
|
4713
|
+
}
|
4711
4714
|
|
4712
|
-
|
4713
|
-
|
4714
|
-
|
4715
|
+
// if we've just found the last page again then we're in a tricky file,
|
4716
|
+
// and we're close enough.
|
4717
|
+
if (mid.page_start == right.page_start)
|
4718
|
+
break;
|
4715
4719
|
|
4716
|
-
|
4720
|
+
if (sample_number < mid.last_decoded_sample)
|
4721
|
+
right = mid;
|
4722
|
+
else
|
4723
|
+
left = mid;
|
4717
4724
|
|
4718
|
-
++
|
4725
|
+
++probe;
|
4719
4726
|
}
|
4720
4727
|
|
4721
|
-
//
|
4728
|
+
// seek back to start of the last packet
|
4729
|
+
page_start = left.page_start;
|
4730
|
+
set_file_offset(f, page_start);
|
4731
|
+
if (!start_page(f)) return error(f, VORBIS_seek_failed);
|
4732
|
+
end_pos = f->end_seg_with_known_loc;
|
4733
|
+
assert(end_pos >= 0);
|
4722
4734
|
|
4723
|
-
|
4724
|
-
|
4725
|
-
|
4726
|
-
|
4727
|
-
// so, if we have to handle that case for the first frame, we might
|
4728
|
-
// as well handle it for all of them, so:
|
4729
|
-
if (target_sample > frame_start + (left_end - left_start)) {
|
4730
|
-
// so what we want to do is go ahead and just immediately decode
|
4731
|
-
// this frame, but then make it so the next get_frame_float() uses
|
4732
|
-
// this already-decoded data? or do we want to go ahead and rewind,
|
4733
|
-
// and leave a flag saying to skip the first N data? let's do that
|
4734
|
-
frames_to_skip = frame; // if this is frame #1, skip 1 frame (#0)
|
4735
|
-
data_to_skip = left_end - left_start;
|
4736
|
-
} else {
|
4737
|
-
// otherwise, we want to skip frames 0, 1, 2, ... frame-2
|
4738
|
-
// (which means frame-2+1 total frames) then decode frame-1,
|
4739
|
-
// then leave frame pending
|
4740
|
-
frames_to_skip = frame - 1;
|
4741
|
-
assert(frames_to_skip >= 0);
|
4742
|
-
data_to_skip = -1;
|
4743
|
-
}
|
4735
|
+
for (;;) {
|
4736
|
+
for (i = end_pos; i > 0; --i)
|
4737
|
+
if (f->segments[i-1] != 255)
|
4738
|
+
break;
|
4744
4739
|
|
4745
|
-
|
4746
|
-
f->next_seg = - 1; // force page resync
|
4740
|
+
start_seg_with_known_loc = i;
|
4747
4741
|
|
4748
|
-
|
4749
|
-
|
4750
|
-
flush_packet(f);
|
4751
|
-
}
|
4742
|
+
if (start_seg_with_known_loc > 0 || !(f->page_flag & PAGEFLAG_continued_packet))
|
4743
|
+
break;
|
4752
4744
|
|
4753
|
-
|
4754
|
-
|
4755
|
-
|
4756
|
-
|
4757
|
-
|
4758
|
-
|
4759
|
-
f->
|
4760
|
-
frame_start += data_to_skip;
|
4761
|
-
} else {
|
4762
|
-
f->previous_length = 0;
|
4763
|
-
vorbis_pump_first_frame(f);
|
4764
|
-
}
|
4765
|
-
|
4766
|
-
// at this point, the NEXT decoded frame will generate the desired sample
|
4767
|
-
if (fine) {
|
4768
|
-
// so if we're doing sample accurate streaming, we want to go ahead and decode it!
|
4769
|
-
if (target_sample != frame_start) {
|
4770
|
-
int n;
|
4771
|
-
stb_vorbis_get_frame_float(f, &n, NULL);
|
4772
|
-
assert(target_sample > frame_start);
|
4773
|
-
assert(f->channel_buffer_start + (int) (target_sample-frame_start) < f->channel_buffer_end);
|
4774
|
-
f->channel_buffer_start += (target_sample - frame_start);
|
4775
|
-
}
|
4745
|
+
// (untested) the final packet begins on an earlier page
|
4746
|
+
if (!go_to_page_before(f, page_start))
|
4747
|
+
goto error;
|
4748
|
+
|
4749
|
+
page_start = stb_vorbis_get_file_offset(f);
|
4750
|
+
if (!start_page(f)) goto error;
|
4751
|
+
end_pos = f->segment_count - 1;
|
4776
4752
|
}
|
4777
4753
|
|
4778
|
-
|
4754
|
+
// prepare to start decoding
|
4755
|
+
f->current_loc_valid = FALSE;
|
4756
|
+
f->last_seg = FALSE;
|
4757
|
+
f->valid_bits = 0;
|
4758
|
+
f->packet_bytes = 0;
|
4759
|
+
f->bytes_in_seg = 0;
|
4760
|
+
f->previous_length = 0;
|
4761
|
+
f->next_seg = start_seg_with_known_loc;
|
4762
|
+
|
4763
|
+
for (i = 0; i < start_seg_with_known_loc; i++)
|
4764
|
+
skip(f, f->segments[i]);
|
4765
|
+
|
4766
|
+
// start decoding (optimizable - this frame is generally discarded)
|
4767
|
+
vorbis_pump_first_frame(f);
|
4768
|
+
return 1;
|
4769
|
+
|
4770
|
+
error:
|
4771
|
+
// try to restore the file to a valid state
|
4772
|
+
stb_vorbis_seek_start(f);
|
4773
|
+
return error(f, VORBIS_seek_failed);
|
4779
4774
|
}
|
4780
4775
|
|
4781
|
-
|
4776
|
+
// the same as vorbis_decode_initial, but without advancing
|
4777
|
+
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)
|
4782
4778
|
{
|
4783
|
-
|
4784
|
-
if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing);
|
4779
|
+
int bits_read, bytes_read;
|
4785
4780
|
|
4786
|
-
|
4787
|
-
|
4788
|
-
uint32 z = stb_vorbis_stream_length_in_samples(f);
|
4789
|
-
if (z == 0) return error(f, VORBIS_cant_find_last_page);
|
4790
|
-
}
|
4781
|
+
if (!vorbis_decode_initial(f, p_left_start, p_left_end, p_right_start, p_right_end, mode))
|
4782
|
+
return 0;
|
4791
4783
|
|
4792
|
-
|
4793
|
-
|
4784
|
+
// either 1 or 2 bytes were read, figure out which so we can rewind
|
4785
|
+
bits_read = 1 + ilog(f->mode_count-1);
|
4786
|
+
if (f->mode_config[*mode].blockflag)
|
4787
|
+
bits_read += 2;
|
4788
|
+
bytes_read = (bits_read + 7) / 8;
|
4789
|
+
|
4790
|
+
f->bytes_in_seg += bytes_read;
|
4791
|
+
f->packet_bytes -= bytes_read;
|
4792
|
+
skip(f, -bytes_read);
|
4793
|
+
if (f->next_seg == -1)
|
4794
|
+
f->next_seg = f->segment_count - 1;
|
4795
|
+
else
|
4796
|
+
f->next_seg--;
|
4797
|
+
f->valid_bits = 0;
|
4794
4798
|
|
4795
|
-
|
4796
|
-
|
4799
|
+
return 1;
|
4800
|
+
}
|
4797
4801
|
|
4798
|
-
|
4799
|
-
|
4800
|
-
|
4801
|
-
} else {
|
4802
|
-
int attempts=0;
|
4803
|
-
while (p[0].page_end < p[1].page_start) {
|
4804
|
-
uint32 probe;
|
4805
|
-
uint32 start_offset, end_offset;
|
4806
|
-
uint32 start_sample, end_sample;
|
4807
|
-
|
4808
|
-
// copy these into local variables so we can tweak them
|
4809
|
-
// if any are unknown
|
4810
|
-
start_offset = p[0].page_end;
|
4811
|
-
end_offset = p[1].after_previous_page_start; // an address known to seek to page p[1]
|
4812
|
-
start_sample = p[0].last_decoded_sample;
|
4813
|
-
end_sample = p[1].last_decoded_sample;
|
4814
|
-
|
4815
|
-
// currently there is no such tweaking logic needed/possible?
|
4816
|
-
if (start_sample == SAMPLE_unknown || end_sample == SAMPLE_unknown)
|
4817
|
-
return error(f, VORBIS_seek_failed);
|
4818
|
-
|
4819
|
-
// now we want to lerp between these for the target samples...
|
4820
|
-
|
4821
|
-
// step 1: we need to bias towards the page start...
|
4822
|
-
if (start_offset + 4000 < end_offset)
|
4823
|
-
end_offset -= 4000;
|
4824
|
-
|
4825
|
-
// now compute an interpolated search loc
|
4826
|
-
probe = start_offset + (int) floor((float) (end_offset - start_offset) / (end_sample - start_sample) * (sample_number - start_sample));
|
4827
|
-
|
4828
|
-
// next we need to bias towards binary search...
|
4829
|
-
// code is a little wonky to allow for full 32-bit unsigned values
|
4830
|
-
if (attempts >= 4) {
|
4831
|
-
uint32 probe2 = start_offset + ((end_offset - start_offset) >> 1);
|
4832
|
-
if (attempts >= 8)
|
4833
|
-
probe = probe2;
|
4834
|
-
else if (probe < probe2)
|
4835
|
-
probe = probe + ((probe2 - probe) >> 1);
|
4836
|
-
else
|
4837
|
-
probe = probe2 + ((probe - probe2) >> 1);
|
4838
|
-
}
|
4839
|
-
++attempts;
|
4802
|
+
int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number)
|
4803
|
+
{
|
4804
|
+
uint32 max_frame_samples;
|
4840
4805
|
|
4841
|
-
|
4842
|
-
if (!vorbis_find_page(f, NULL, NULL)) return error(f, VORBIS_seek_failed);
|
4843
|
-
if (!vorbis_analyze_page(f, &q)) return error(f, VORBIS_seek_failed);
|
4844
|
-
q.after_previous_page_start = probe;
|
4806
|
+
if (IS_PUSH_MODE(f)) return error(f, VORBIS_invalid_api_mixing);
|
4845
4807
|
|
4846
|
-
|
4847
|
-
|
4848
|
-
|
4849
|
-
continue;
|
4850
|
-
}
|
4808
|
+
// fast page-level search
|
4809
|
+
if (!seek_to_sample_coarse(f, sample_number))
|
4810
|
+
return 0;
|
4851
4811
|
|
4852
|
-
|
4853
|
-
|
4854
|
-
else
|
4855
|
-
p[0] = q;
|
4856
|
-
}
|
4812
|
+
assert(f->current_loc_valid);
|
4813
|
+
assert(f->current_loc <= sample_number);
|
4857
4814
|
|
4858
|
-
|
4859
|
-
|
4860
|
-
|
4815
|
+
// linear search for the relevant packet
|
4816
|
+
max_frame_samples = (f->blocksize_1*3 - f->blocksize_0) >> 2;
|
4817
|
+
while (f->current_loc < sample_number) {
|
4818
|
+
int left_start, left_end, right_start, right_end, mode, frame_samples;
|
4819
|
+
if (!peek_decode_initial(f, &left_start, &left_end, &right_start, &right_end, &mode))
|
4820
|
+
return error(f, VORBIS_seek_failed);
|
4821
|
+
// calculate the number of samples returned by the next frame
|
4822
|
+
frame_samples = right_start - left_start;
|
4823
|
+
if (f->current_loc + frame_samples > sample_number) {
|
4824
|
+
return 1; // the next frame will contain the sample
|
4825
|
+
} else if (f->current_loc + frame_samples + max_frame_samples > sample_number) {
|
4826
|
+
// there's a chance the frame after this could contain the sample
|
4827
|
+
vorbis_pump_first_frame(f);
|
4828
|
+
} else {
|
4829
|
+
// this frame is too early to be relevant
|
4830
|
+
f->current_loc += frame_samples;
|
4831
|
+
f->previous_length = 0;
|
4832
|
+
maybe_start_packet(f);
|
4833
|
+
flush_packet(f);
|
4861
4834
|
}
|
4862
|
-
return error(f, VORBIS_seek_failed);
|
4863
4835
|
}
|
4864
|
-
|
4865
|
-
|
4866
|
-
|
4867
|
-
{
|
4868
|
-
return vorbis_seek_base(f, sample_number, FALSE);
|
4836
|
+
// the next frame will start with the sample
|
4837
|
+
assert(f->current_loc == sample_number);
|
4838
|
+
return 1;
|
4869
4839
|
}
|
4870
4840
|
|
4871
4841
|
int stb_vorbis_seek(stb_vorbis *f, unsigned int sample_number)
|
4872
4842
|
{
|
4873
|
-
|
4843
|
+
if (!stb_vorbis_seek_frame(f, sample_number))
|
4844
|
+
return 0;
|
4845
|
+
|
4846
|
+
if (sample_number != f->current_loc) {
|
4847
|
+
int n;
|
4848
|
+
uint32 frame_start = f->current_loc;
|
4849
|
+
stb_vorbis_get_frame_float(f, &n, NULL);
|
4850
|
+
assert(sample_number > frame_start);
|
4851
|
+
assert(f->channel_buffer_start + (int) (sample_number-frame_start) <= f->channel_buffer_end);
|
4852
|
+
f->channel_buffer_start += (sample_number - frame_start);
|
4853
|
+
}
|
4854
|
+
|
4855
|
+
return 1;
|
4874
4856
|
}
|
4875
4857
|
|
4876
4858
|
void stb_vorbis_seek_start(stb_vorbis *f)
|
@@ -4951,8 +4933,6 @@ unsigned int stb_vorbis_stream_length_in_samples(stb_vorbis *f)
|
|
4951
4933
|
f->p_last.page_start = last_page_loc;
|
4952
4934
|
f->p_last.page_end = end;
|
4953
4935
|
f->p_last.last_decoded_sample = lo;
|
4954
|
-
f->p_last.first_decoded_sample = SAMPLE_unknown;
|
4955
|
-
f->p_last.after_previous_page_start = previous_safe;
|
4956
4936
|
|
4957
4937
|
done:
|
4958
4938
|
set_file_offset(f, restore_offset);
|
@@ -5412,6 +5392,8 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in
|
|
5412
5392
|
#endif // STB_VORBIS_NO_PULLDATA_API
|
5413
5393
|
|
5414
5394
|
/* Version history
|
5395
|
+
1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson)
|
5396
|
+
some crash fixes when out of memory or with corrupt files
|
5415
5397
|
1.05 - 2015/04/19 - don't define __forceinline if it's redundant
|
5416
5398
|
1.04 - 2014/08/27 - fix missing const-correct case in API
|
5417
5399
|
1.03 - 2014/08/07 - Warning fixes
|