Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
M
miniaudio
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
miniaudio
Commits
6edd3cfd
Commit
6edd3cfd
authored
Feb 15, 2020
by
David Reid
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update stb_vorbis.
parent
259d8aa2
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
339 additions
and
233 deletions
+339
-233
extras/stb_vorbis.c
extras/stb_vorbis.c
+339
-233
No files found.
extras/stb_vorbis.c
View file @
6edd3cfd
// Ogg Vorbis audio decoder - v1.1
1
- public domain
// Ogg Vorbis audio decoder - v1.1
9
- public domain
// http://nothings.org/stb_vorbis/
// http://nothings.org/stb_vorbis/
//
//
// Original version written by Sean Barrett in 2007.
// Original version written by Sean Barrett in 2007.
//
//
// Originally sponsored by RAD Game Tools. Seeking
sponsored
// Originally sponsored by RAD Game Tools. Seeking
implementation
//
by Phillip Bennefall, Marc Andersen, Aaron Baker, Elias Software
,
//
sponsored by Phillip Bennefall, Marc Andersen, Aaron Baker
,
// Aras Pranckevicius, and Sean Barrett.
//
Elias Software,
Aras Pranckevicius, and Sean Barrett.
//
//
// LICENSE
// LICENSE
//
//
...
@@ -26,26 +26,36 @@
...
@@ -26,26 +26,36 @@
// Terje Mathisen Niklas Frykholm Andy Hill
// Terje Mathisen Niklas Frykholm Andy Hill
// Casey Muratori John Bolton Gargaj
// Casey Muratori John Bolton Gargaj
// Laurent Gomila Marc LeBlanc Ronny Chevalier
// Laurent Gomila Marc LeBlanc Ronny Chevalier
// Bernhard Wodo Evan Balster
alxprd@github
// Bernhard Wodo Evan Balster
github:alxprd
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot
// Tom Beaumont Ingo Leitgeb Nicolas Guillemot
// Phillip Bennefall Rohit Thiago Goulart
// Phillip Bennefall Rohit Thiago Goulart
// manxorist@github saga musix github:infatum
// github:manxorist saga musix github:infatum
// Timur Gagiev Maxwell Koo Peter Waller
// github:audinowho Dougall Johnson
//
//
// Partial history:
// Partial history:
// 1.11 - 2017/07/23 - fix MinGW compilation
// 1.19 - 2020-02-05 - warnings
// 1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory
// 1.18 - 2020-02-02 - fix seek bugs; parse header comments; misc warnings etc.
// 1.09 - 2016/04/04 - back out 'truncation of last frame' fix from previous version
// 1.17 - 2019-07-08 - fix CVE-2019-13217..CVE-2019-13223 (by ForAllSecure)
// 1.08 - 2016/04/02 - warnings; setup memory leaks; truncation of last frame
// 1.16 - 2019-03-04 - fix warnings
// 1.07 - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const
// 1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found
// 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson)
// 1.14 - 2018-02-11 - delete bogus dealloca usage
// 1.13 - 2018-01-29 - fix truncation of last frame (hopefully)
// 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files
// 1.11 - 2017-07-23 - fix MinGW compilation
// 1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory
// 1.09 - 2016-04-04 - back out 'truncation of last frame' fix from previous version
// 1.08 - 2016-04-02 - warnings; setup memory leaks; truncation of last frame
// 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
// some crash fixes when out of memory or with corrupt files
// fix some inappropriately signed shifts
// fix some inappropriately signed shifts
// 1.05 - 2015
/04/
19 - don't define __forceinline if it's redundant
// 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.04 - 2014
-08-
27 - fix missing const-correct case in API
// 1.03 - 2014
/08/
07 - warning fixes
// 1.03 - 2014
-08-
07 - warning fixes
// 1.02 - 2014
/07/
09 - declare qsort comparison as explicitly _cdecl in Windows
// 1.02 - 2014
-07-
09 - declare qsort comparison as explicitly _cdecl in Windows
// 1.01 - 2014
/06/
18 - fix stb_vorbis_get_samples_float (interleaved was correct)
// 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;
// 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
// (API change) report sample rate for decode-full-file funcs
//
//
// See end of file for full version history.
// See end of file for full version history.
...
@@ -123,9 +133,20 @@ typedef struct
...
@@ -123,9 +133,20 @@ typedef struct
int
max_frame_size
;
int
max_frame_size
;
}
stb_vorbis_info
;
}
stb_vorbis_info
;
typedef
struct
{
char
*
vendor
;
int
comment_list_length
;
char
**
comment_list
;
}
stb_vorbis_comment
;
// get general information about the file
// get general information about the file
extern
stb_vorbis_info
stb_vorbis_get_info
(
stb_vorbis
*
f
);
extern
stb_vorbis_info
stb_vorbis_get_info
(
stb_vorbis
*
f
);
// get ogg comments
extern
stb_vorbis_comment
stb_vorbis_get_comment
(
stb_vorbis
*
f
);
// get the last error detected (clears it, too)
// get the last error detected (clears it, too)
extern
int
stb_vorbis_get_error
(
stb_vorbis
*
f
);
extern
int
stb_vorbis_get_error
(
stb_vorbis
*
f
);
...
@@ -249,7 +270,7 @@ extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,
...
@@ -249,7 +270,7 @@ extern stb_vorbis * stb_vorbis_open_file(FILE *f, int close_handle_on_close,
// create an ogg vorbis decoder from an open FILE *, looking for a stream at
// 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.
// 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
// note that stb_vorbis must "own" this stream; if you seek it in between
// calls to stb_vorbis, it will become confused. Morever, if you attempt to
// calls to stb_vorbis, it will become confused. More
o
ver, if you attempt to
// perform stb_vorbis_seek_*() operations on this file, it will assume it
// perform stb_vorbis_seek_*() operations on this file, it will assume it
// owns the _entire_ rest of the file after the start point. Use the next
// owns the _entire_ rest of the file after the start point. Use the next
// function, stb_vorbis_open_file_section(), to limit it.
// function, stb_vorbis_open_file_section(), to limit it.
...
@@ -370,7 +391,8 @@ enum STBVorbisError
...
@@ -370,7 +391,8 @@ enum STBVorbisError
VORBIS_invalid_first_page
,
VORBIS_invalid_first_page
,
VORBIS_bad_packet_type
,
VORBIS_bad_packet_type
,
VORBIS_cant_find_last_page
,
VORBIS_cant_find_last_page
,
VORBIS_seek_failed
VORBIS_seek_failed
,
VORBIS_ogg_skeleton_not_supported
};
};
...
@@ -751,6 +773,10 @@ struct stb_vorbis
...
@@ -751,6 +773,10 @@ struct stb_vorbis
unsigned
int
temp_memory_required
;
unsigned
int
temp_memory_required
;
unsigned
int
setup_temp_memory_required
;
unsigned
int
setup_temp_memory_required
;
char
*
vendor
;
int
comment_list_length
;
char
**
comment_list
;
// input config
// input config
#ifndef STB_VORBIS_NO_STDIO
#ifndef STB_VORBIS_NO_STDIO
FILE
*
f
;
FILE
*
f
;
...
@@ -766,8 +792,11 @@ struct stb_vorbis
...
@@ -766,8 +792,11 @@ struct stb_vorbis
uint8
push_mode
;
uint8
push_mode
;
// the page to seek to when seeking to start, may be zero
uint32
first_audio_page_offset
;
uint32
first_audio_page_offset
;
// p_first is the page on which the first audio packet ends
// (but not necessarily the page on which it starts)
ProbedPage
p_first
,
p_last
;
ProbedPage
p_first
,
p_last
;
// memory management
// memory management
...
@@ -880,11 +909,7 @@ static int error(vorb *f, enum STBVorbisError e)
...
@@ -880,11 +909,7 @@ static int error(vorb *f, enum STBVorbisError e)
#define array_size_required(count,size) (count*(sizeof(void *)+(size)))
#define array_size_required(count,size) (count*(sizeof(void *)+(size)))
#define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : alloca(size))
#define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : alloca(size))
#ifdef dealloca
#define temp_free(f,p) (void)0
#define temp_free(f,p) (f->alloc.alloc_buffer ? 0 : dealloca(size))
#else
#define temp_free(f,p) 0
#endif
#define temp_alloc_save(f) ((f)->temp_offset)
#define temp_alloc_save(f) ((f)->temp_offset)
#define temp_alloc_restore(f,p) ((f)->temp_offset = (p))
#define temp_alloc_restore(f,p) ((f)->temp_offset = (p))
...
@@ -905,7 +930,7 @@ static void *make_block_array(void *mem, int count, int size)
...
@@ -905,7 +930,7 @@ static void *make_block_array(void *mem, int count, int size)
static
void
*
setup_malloc
(
vorb
*
f
,
int
sz
)
static
void
*
setup_malloc
(
vorb
*
f
,
int
sz
)
{
{
sz
=
(
sz
+
3
)
&
~
3
;
sz
=
(
sz
+
7
)
&
~
7
;
// round up to nearest 8 for alignment of future allocs.
f
->
setup_memory_required
+=
sz
;
f
->
setup_memory_required
+=
sz
;
if
(
f
->
alloc
.
alloc_buffer
)
{
if
(
f
->
alloc
.
alloc_buffer
)
{
void
*
p
=
(
char
*
)
f
->
alloc
.
alloc_buffer
+
f
->
setup_offset
;
void
*
p
=
(
char
*
)
f
->
alloc
.
alloc_buffer
+
f
->
setup_offset
;
...
@@ -924,7 +949,7 @@ static void setup_free(vorb *f, void *p)
...
@@ -924,7 +949,7 @@ static void setup_free(vorb *f, void *p)
static
void
*
setup_temp_malloc
(
vorb
*
f
,
int
sz
)
static
void
*
setup_temp_malloc
(
vorb
*
f
,
int
sz
)
{
{
sz
=
(
sz
+
3
)
&
~
3
;
sz
=
(
sz
+
7
)
&
~
7
;
// round up to nearest 8 for alignment of future allocs.
if
(
f
->
alloc
.
alloc_buffer
)
{
if
(
f
->
alloc
.
alloc_buffer
)
{
if
(
f
->
temp_offset
-
sz
<
f
->
setup_offset
)
return
NULL
;
if
(
f
->
temp_offset
-
sz
<
f
->
setup_offset
)
return
NULL
;
f
->
temp_offset
-=
sz
;
f
->
temp_offset
-=
sz
;
...
@@ -1073,7 +1098,7 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)
...
@@ -1073,7 +1098,7 @@ static int compute_codewords(Codebook *c, uint8 *len, int n, uint32 *values)
assert
(
z
>=
0
&&
z
<
32
);
assert
(
z
>=
0
&&
z
<
32
);
available
[
z
]
=
0
;
available
[
z
]
=
0
;
add_entry
(
c
,
bit_reverse
(
res
),
i
,
m
++
,
len
[
i
],
values
);
add_entry
(
c
,
bit_reverse
(
res
),
i
,
m
++
,
len
[
i
],
values
);
// prop
o
gate availability up the tree
// prop
a
gate availability up the tree
if
(
z
!=
len
[
i
])
{
if
(
z
!=
len
[
i
])
{
assert
(
len
[
i
]
>=
0
&&
len
[
i
]
<
32
);
assert
(
len
[
i
]
>=
0
&&
len
[
i
]
<
32
);
for
(
y
=
len
[
i
];
y
>
z
;
--
y
)
{
for
(
y
=
len
[
i
];
y
>
z
;
--
y
)
{
...
@@ -1199,8 +1224,10 @@ static int lookup1_values(int entries, int dim)
...
@@ -1199,8 +1224,10 @@ static int lookup1_values(int entries, int dim)
int
r
=
(
int
)
floor
(
exp
((
float
)
log
((
float
)
entries
)
/
dim
));
int
r
=
(
int
)
floor
(
exp
((
float
)
log
((
float
)
entries
)
/
dim
));
if
((
int
)
floor
(
pow
((
float
)
r
+
1
,
dim
))
<=
entries
)
// (int) cast for MinGW warning;
if
((
int
)
floor
(
pow
((
float
)
r
+
1
,
dim
))
<=
entries
)
// (int) cast for MinGW warning;
++
r
;
// floor() to avoid _ftol() when non-CRT
++
r
;
// floor() to avoid _ftol() when non-CRT
assert
(
pow
((
float
)
r
+
1
,
dim
)
>
entries
);
if
(
pow
((
float
)
r
+
1
,
dim
)
<=
entries
)
assert
((
int
)
floor
(
pow
((
float
)
r
,
dim
))
<=
entries
);
// (int),floor() as above
return
-
1
;
if
((
int
)
floor
(
pow
((
float
)
r
,
dim
))
>
entries
)
return
-
1
;
return
r
;
return
r
;
}
}
...
@@ -1398,6 +1425,9 @@ static int capture_pattern(vorb *f)
...
@@ -1398,6 +1425,9 @@ static int capture_pattern(vorb *f)
static
int
start_page_no_capturepattern
(
vorb
*
f
)
static
int
start_page_no_capturepattern
(
vorb
*
f
)
{
{
uint32
loc0
,
loc1
,
n
;
uint32
loc0
,
loc1
,
n
;
if
(
f
->
first_decode
&&
!
IS_PUSH_MODE
(
f
))
{
f
->
p_first
.
page_start
=
stb_vorbis_get_file_offset
(
f
)
-
4
;
}
// stream structure version
// stream structure version
if
(
0
!=
get8
(
f
))
return
error
(
f
,
VORBIS_invalid_stream_structure_version
);
if
(
0
!=
get8
(
f
))
return
error
(
f
,
VORBIS_invalid_stream_structure_version
);
// header flag
// header flag
...
@@ -1434,15 +1464,12 @@ static int start_page_no_capturepattern(vorb *f)
...
@@ -1434,15 +1464,12 @@ static int start_page_no_capturepattern(vorb *f)
}
}
if
(
f
->
first_decode
)
{
if
(
f
->
first_decode
)
{
int
i
,
len
;
int
i
,
len
;
ProbedPage
p
;
len
=
0
;
len
=
0
;
for
(
i
=
0
;
i
<
f
->
segment_count
;
++
i
)
for
(
i
=
0
;
i
<
f
->
segment_count
;
++
i
)
len
+=
f
->
segments
[
i
];
len
+=
f
->
segments
[
i
];
len
+=
27
+
f
->
segment_count
;
len
+=
27
+
f
->
segment_count
;
p
.
page_start
=
f
->
first_audio_page_offset
;
f
->
p_first
.
page_end
=
f
->
p_first
.
page_start
+
len
;
p
.
page_end
=
p
.
page_start
+
len
;
f
->
p_first
.
last_decoded_sample
=
loc0
;
p
.
last_decoded_sample
=
loc0
;
f
->
p_first
=
p
;
}
}
f
->
next_seg
=
0
;
f
->
next_seg
=
0
;
return
TRUE
;
return
TRUE
;
...
@@ -1533,6 +1560,16 @@ static int get8_packet(vorb *f)
...
@@ -1533,6 +1560,16 @@ static int get8_packet(vorb *f)
return
x
;
return
x
;
}
}
static
int
get32_packet
(
vorb
*
f
)
{
uint32
x
;
x
=
get8_packet
(
f
);
x
+=
get8_packet
(
f
)
<<
8
;
x
+=
get8_packet
(
f
)
<<
16
;
x
+=
(
uint32
)
get8_packet
(
f
)
<<
24
;
return
x
;
}
static
void
flush_packet
(
vorb
*
f
)
static
void
flush_packet
(
vorb
*
f
)
{
{
while
(
get8_packet_raw
(
f
)
!=
EOP
);
while
(
get8_packet_raw
(
f
)
!=
EOP
);
...
@@ -2010,7 +2047,7 @@ static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y
...
@@ -2010,7 +2047,7 @@ static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y
ady
-=
abs
(
base
)
*
adx
;
ady
-=
abs
(
base
)
*
adx
;
if
(
x1
>
n
)
x1
=
n
;
if
(
x1
>
n
)
x1
=
n
;
if
(
x
<
x1
)
{
if
(
x
<
x1
)
{
LINE_OP
(
output
[
x
],
inverse_db_table
[
y
]);
LINE_OP
(
output
[
x
],
inverse_db_table
[
y
&
255
]);
for
(
++
x
;
x
<
x1
;
++
x
)
{
for
(
++
x
;
x
<
x1
;
++
x
)
{
err
+=
ady
;
err
+=
ady
;
if
(
err
>=
adx
)
{
if
(
err
>=
adx
)
{
...
@@ -2018,7 +2055,7 @@ static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y
...
@@ -2018,7 +2055,7 @@ static __forceinline void draw_line(float *output, int x0, int y0, int x1, int y
y
+=
sy
;
y
+=
sy
;
}
else
}
else
y
+=
base
;
y
+=
base
;
LINE_OP
(
output
[
x
],
inverse_db_table
[
y
]);
LINE_OP
(
output
[
x
],
inverse_db_table
[
y
&
255
]);
}
}
}
}
}
}
...
@@ -2042,6 +2079,8 @@ static int residue_decode(vorb *f, Codebook *book, float *target, int offset, in
...
@@ -2042,6 +2079,8 @@ static int residue_decode(vorb *f, Codebook *book, float *target, int offset, in
return
TRUE
;
return
TRUE
;
}
}
// n is 1/2 of the blocksize --
// specification: "Correct per-vector decode length is [n]/2"
static
void
decode_residue
(
vorb
*
f
,
float
*
residue_buffers
[],
int
ch
,
int
n
,
int
rn
,
uint8
*
do_not_decode
)
static
void
decode_residue
(
vorb
*
f
,
float
*
residue_buffers
[],
int
ch
,
int
n
,
int
rn
,
uint8
*
do_not_decode
)
{
{
int
i
,
j
,
pass
;
int
i
,
j
,
pass
;
...
@@ -2049,7 +2088,10 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
...
@@ -2049,7 +2088,10 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
int
rtype
=
f
->
residue_types
[
rn
];
int
rtype
=
f
->
residue_types
[
rn
];
int
c
=
r
->
classbook
;
int
c
=
r
->
classbook
;
int
classwords
=
f
->
codebooks
[
c
].
dimensions
;
int
classwords
=
f
->
codebooks
[
c
].
dimensions
;
int
n_read
=
r
->
end
-
r
->
begin
;
unsigned
int
actual_size
=
rtype
==
2
?
n
*
2
:
n
;
unsigned
int
limit_r_begin
=
(
r
->
begin
<
actual_size
?
r
->
begin
:
actual_size
);
unsigned
int
limit_r_end
=
(
r
->
end
<
actual_size
?
r
->
end
:
actual_size
);
int
n_read
=
limit_r_end
-
limit_r_begin
;
int
part_read
=
n_read
/
r
->
part_size
;
int
part_read
=
n_read
/
r
->
part_size
;
int
temp_alloc_point
=
temp_alloc_save
(
f
);
int
temp_alloc_point
=
temp_alloc_save
(
f
);
#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
...
@@ -2119,47 +2161,7 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
...
@@ -2119,47 +2161,7 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int
++
class_set
;
++
class_set
;
#endif
#endif
}
}
}
else
if
(
ch
==
1
)
{
}
else
if
(
ch
>
2
)
{
while
(
pcount
<
part_read
)
{
int
z
=
r
->
begin
+
pcount
*
r
->
part_size
;
int
c_inter
=
0
,
p_inter
=
z
;
if
(
pass
==
0
)
{
Codebook
*
c
=
f
->
codebooks
+
r
->
classbook
;
int
q
;
DECODE
(
q
,
f
,
c
);
if
(
q
==
EOP
)
goto
done
;
#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
part_classdata
[
0
][
class_set
]
=
r
->
classdata
[
q
];
#else
for
(
i
=
classwords
-
1
;
i
>=
0
;
--
i
)
{
classifications
[
0
][
i
+
pcount
]
=
q
%
r
->
classifications
;
q
/=
r
->
classifications
;
}
#endif
}
for
(
i
=
0
;
i
<
classwords
&&
pcount
<
part_read
;
++
i
,
++
pcount
)
{
int
z
=
r
->
begin
+
pcount
*
r
->
part_size
;
#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
int
c
=
part_classdata
[
0
][
class_set
][
i
];
#else
int
c
=
classifications
[
0
][
pcount
];
#endif
int
b
=
r
->
residue_books
[
c
][
pass
];
if
(
b
>=
0
)
{
Codebook
*
book
=
f
->
codebooks
+
b
;
if
(
!
codebook_decode_deinterleave_repeat
(
f
,
book
,
residue_buffers
,
ch
,
&
c_inter
,
&
p_inter
,
n
,
r
->
part_size
))
goto
done
;
}
else
{
z
+=
r
->
part_size
;
c_inter
=
0
;
p_inter
=
z
;
}
}
#ifndef STB_VORBIS_DIVIDES_IN_RESIDUE
++
class_set
;
#endif
}
}
else
{
while
(
pcount
<
part_read
)
{
while
(
pcount
<
part_read
)
{
int
z
=
r
->
begin
+
pcount
*
r
->
part_size
;
int
z
=
r
->
begin
+
pcount
*
r
->
part_size
;
int
c_inter
=
z
%
ch
,
p_inter
=
z
/
ch
;
int
c_inter
=
z
%
ch
,
p_inter
=
z
/
ch
;
...
@@ -2632,7 +2634,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
...
@@ -2632,7 +2634,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype)
// once I combined the passes.
// once I combined the passes.
// so there's a missing 'times 2' here (for adding X to itself).
// so there's a missing 'times 2' here (for adding X to itself).
// this prop
o
gates through linearly to the end, where the numbers
// this prop
a
gates through linearly to the end, where the numbers
// are 1/2 too small, and need to be compensated for.
// are 1/2 too small, and need to be compensated for.
{
{
...
@@ -3040,7 +3042,6 @@ static float *get_window(vorb *f, int len)
...
@@ -3040,7 +3042,6 @@ static float *get_window(vorb *f, int len)
len
<<=
1
;
len
<<=
1
;
if
(
len
==
f
->
blocksize_0
)
return
f
->
window
[
0
];
if
(
len
==
f
->
blocksize_0
)
return
f
->
window
[
0
];
if
(
len
==
f
->
blocksize_1
)
return
f
->
window
[
1
];
if
(
len
==
f
->
blocksize_1
)
return
f
->
window
[
1
];
assert
(
0
);
return
NULL
;
return
NULL
;
}
}
...
@@ -3391,7 +3392,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
...
@@ -3391,7 +3392,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
if
(
f
->
last_seg_which
==
f
->
end_seg_with_known_loc
)
{
if
(
f
->
last_seg_which
==
f
->
end_seg_with_known_loc
)
{
// if we have a valid current loc, and this is final:
// if we have a valid current loc, and this is final:
if
(
f
->
current_loc_valid
&&
(
f
->
page_flag
&
PAGEFLAG_last_page
))
{
if
(
f
->
current_loc_valid
&&
(
f
->
page_flag
&
PAGEFLAG_last_page
))
{
uint32
current_end
=
f
->
known_loc_for_packet
-
(
n
-
right_end
)
;
uint32
current_end
=
f
->
known_loc_for_packet
;
// then let's infer the size of the (probably) short final frame
// then let's infer the size of the (probably) short final frame
if
(
current_end
<
f
->
current_loc
+
(
right_end
-
left_start
))
{
if
(
current_end
<
f
->
current_loc
+
(
right_end
-
left_start
))
{
if
(
current_end
<
f
->
current_loc
)
{
if
(
current_end
<
f
->
current_loc
)
{
...
@@ -3400,7 +3401,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
...
@@ -3400,7 +3401,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start,
}
else
{
}
else
{
*
len
=
current_end
-
f
->
current_loc
;
*
len
=
current_end
-
f
->
current_loc
;
}
}
*
len
+=
left_start
;
*
len
+=
left_start
;
// this doesn't seem right, but has no ill effect on my test files
if
(
*
len
>
right_end
)
*
len
=
right_end
;
// this should never happen
if
(
*
len
>
right_end
)
*
len
=
right_end
;
// this should never happen
f
->
current_loc
+=
*
len
;
f
->
current_loc
+=
*
len
;
return
TRUE
;
return
TRUE
;
...
@@ -3446,6 +3447,7 @@ static int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right)
...
@@ -3446,6 +3447,7 @@ static int vorbis_finish_frame(stb_vorbis *f, int len, int left, int right)
if
(
f
->
previous_length
)
{
if
(
f
->
previous_length
)
{
int
i
,
j
,
n
=
f
->
previous_length
;
int
i
,
j
,
n
=
f
->
previous_length
;
float
*
w
=
get_window
(
f
,
n
);
float
*
w
=
get_window
(
f
,
n
);
if
(
w
==
NULL
)
return
0
;
for
(
i
=
0
;
i
<
f
->
channels
;
++
i
)
{
for
(
i
=
0
;
i
<
f
->
channels
;
++
i
)
{
for
(
j
=
0
;
j
<
n
;
++
j
)
for
(
j
=
0
;
j
<
n
;
++
j
)
f
->
channel_buffers
[
i
][
left
+
j
]
=
f
->
channel_buffers
[
i
][
left
+
j
]
=
...
@@ -3493,7 +3495,7 @@ static int vorbis_pump_first_frame(stb_vorbis *f)
...
@@ -3493,7 +3495,7 @@ static int vorbis_pump_first_frame(stb_vorbis *f)
}
}
#ifndef STB_VORBIS_NO_PUSHDATA_API
#ifndef STB_VORBIS_NO_PUSHDATA_API
static
int
is_whole_packet_present
(
stb_vorbis
*
f
,
int
end_page
)
static
int
is_whole_packet_present
(
stb_vorbis
*
f
)
{
{
// make sure that we have the packet available before continuing...
// make sure that we have the packet available before continuing...
// this requires a full ogg parse, but we know we can fetch from f->stream
// this requires a full ogg parse, but we know we can fetch from f->stream
...
@@ -3513,8 +3515,6 @@ static int is_whole_packet_present(stb_vorbis *f, int end_page)
...
@@ -3513,8 +3515,6 @@ static int is_whole_packet_present(stb_vorbis *f, int end_page)
break
;
break
;
}
}
// either this continues, or it ends it...
// either this continues, or it ends it...
if
(
end_page
)
if
(
s
<
f
->
segment_count
-
1
)
return
error
(
f
,
VORBIS_invalid_stream
);
if
(
s
==
f
->
segment_count
)
if
(
s
==
f
->
segment_count
)
s
=
-
1
;
// set 'crosses page' flag
s
=
-
1
;
// set 'crosses page' flag
if
(
p
>
f
->
stream_end
)
return
error
(
f
,
VORBIS_need_more_data
);
if
(
p
>
f
->
stream_end
)
return
error
(
f
,
VORBIS_need_more_data
);
...
@@ -3547,8 +3547,6 @@ static int is_whole_packet_present(stb_vorbis *f, int end_page)
...
@@ -3547,8 +3547,6 @@ static int is_whole_packet_present(stb_vorbis *f, int end_page)
if
(
q
[
s
]
<
255
)
if
(
q
[
s
]
<
255
)
break
;
break
;
}
}
if
(
end_page
)
if
(
s
<
n
-
1
)
return
error
(
f
,
VORBIS_invalid_stream
);
if
(
s
==
n
)
if
(
s
==
n
)
s
=
-
1
;
// set 'crosses page' flag
s
=
-
1
;
// set 'crosses page' flag
if
(
p
>
f
->
stream_end
)
return
error
(
f
,
VORBIS_need_more_data
);
if
(
p
>
f
->
stream_end
)
return
error
(
f
,
VORBIS_need_more_data
);
...
@@ -3565,6 +3563,7 @@ static int start_decoder(vorb *f)
...
@@ -3565,6 +3563,7 @@ static int start_decoder(vorb *f)
int
longest_floorlist
=
0
;
int
longest_floorlist
=
0
;
// first page, first packet
// first page, first packet
f
->
first_decode
=
TRUE
;
if
(
!
start_page
(
f
))
return
FALSE
;
if
(
!
start_page
(
f
))
return
FALSE
;
// validate page flag
// validate page flag
...
@@ -3573,7 +3572,22 @@ static int start_decoder(vorb *f)
...
@@ -3573,7 +3572,22 @@ static int start_decoder(vorb *f)
if
(
f
->
page_flag
&
PAGEFLAG_continued_packet
)
return
error
(
f
,
VORBIS_invalid_first_page
);
if
(
f
->
page_flag
&
PAGEFLAG_continued_packet
)
return
error
(
f
,
VORBIS_invalid_first_page
);
// check for expected packet length
// check for expected packet length
if
(
f
->
segment_count
!=
1
)
return
error
(
f
,
VORBIS_invalid_first_page
);
if
(
f
->
segment_count
!=
1
)
return
error
(
f
,
VORBIS_invalid_first_page
);
if
(
f
->
segments
[
0
]
!=
30
)
return
error
(
f
,
VORBIS_invalid_first_page
);
if
(
f
->
segments
[
0
]
!=
30
)
{
// check for the Ogg skeleton fishead identifying header to refine our error
if
(
f
->
segments
[
0
]
==
64
&&
getn
(
f
,
header
,
6
)
&&
header
[
0
]
==
'f'
&&
header
[
1
]
==
'i'
&&
header
[
2
]
==
's'
&&
header
[
3
]
==
'h'
&&
header
[
4
]
==
'e'
&&
header
[
5
]
==
'a'
&&
get8
(
f
)
==
'd'
&&
get8
(
f
)
==
'\0'
)
return
error
(
f
,
VORBIS_ogg_skeleton_not_supported
);
else
return
error
(
f
,
VORBIS_invalid_first_page
);
}
// read packet
// read packet
// check packet header
// check packet header
if
(
get8
(
f
)
!=
VORBIS_packet_id
)
return
error
(
f
,
VORBIS_invalid_first_page
);
if
(
get8
(
f
)
!=
VORBIS_packet_id
)
return
error
(
f
,
VORBIS_invalid_first_page
);
...
@@ -3607,6 +3621,41 @@ static int start_decoder(vorb *f)
...
@@ -3607,6 +3621,41 @@ static int start_decoder(vorb *f)
if
(
!
start_page
(
f
))
return
FALSE
;
if
(
!
start_page
(
f
))
return
FALSE
;
if
(
!
start_packet
(
f
))
return
FALSE
;
if
(
!
start_packet
(
f
))
return
FALSE
;
if
(
!
next_segment
(
f
))
return
FALSE
;
if
(
get8_packet
(
f
)
!=
VORBIS_packet_comment
)
return
error
(
f
,
VORBIS_invalid_setup
);
for
(
i
=
0
;
i
<
6
;
++
i
)
header
[
i
]
=
get8_packet
(
f
);
if
(
!
vorbis_validate
(
header
))
return
error
(
f
,
VORBIS_invalid_setup
);
//file vendor
len
=
get32_packet
(
f
);
f
->
vendor
=
(
char
*
)
setup_malloc
(
f
,
sizeof
(
char
)
*
(
len
+
1
));
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
));
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
));
for
(
j
=
0
;
j
<
len
;
++
j
)
{
f
->
comment_list
[
i
][
j
]
=
get8_packet
(
f
);
}
f
->
comment_list
[
i
][
len
]
=
(
char
)
'\0'
;
}
// framing_flag
x
=
get8_packet
(
f
);
if
(
!
(
x
&
1
))
return
error
(
f
,
VORBIS_invalid_setup
);
skip
(
f
,
f
->
bytes_in_seg
);
f
->
bytes_in_seg
=
0
;
do
{
do
{
len
=
next_segment
(
f
);
len
=
next_segment
(
f
);
skip
(
f
,
len
);
skip
(
f
,
len
);
...
@@ -3618,7 +3667,7 @@ static int start_decoder(vorb *f)
...
@@ -3618,7 +3667,7 @@ static int start_decoder(vorb *f)
#ifndef STB_VORBIS_NO_PUSHDATA_API
#ifndef STB_VORBIS_NO_PUSHDATA_API
if
(
IS_PUSH_MODE
(
f
))
{
if
(
IS_PUSH_MODE
(
f
))
{
if
(
!
is_whole_packet_present
(
f
,
TRUE
))
{
if
(
!
is_whole_packet_present
(
f
))
{
// convert error in ogg header to write type
// convert error in ogg header to write type
if
(
f
->
error
==
VORBIS_invalid_stream
)
if
(
f
->
error
==
VORBIS_invalid_stream
)
f
->
error
=
VORBIS_invalid_setup
;
f
->
error
=
VORBIS_invalid_setup
;
...
@@ -3672,6 +3721,7 @@ static int start_decoder(vorb *f)
...
@@ -3672,6 +3721,7 @@ static int start_decoder(vorb *f)
while
(
current_entry
<
c
->
entries
)
{
while
(
current_entry
<
c
->
entries
)
{
int
limit
=
c
->
entries
-
current_entry
;
int
limit
=
c
->
entries
-
current_entry
;
int
n
=
get_bits
(
f
,
ilog
(
limit
));
int
n
=
get_bits
(
f
,
ilog
(
limit
));
if
(
current_length
>=
32
)
return
error
(
f
,
VORBIS_invalid_setup
);
if
(
current_entry
+
n
>
(
int
)
c
->
entries
)
{
return
error
(
f
,
VORBIS_invalid_setup
);
}
if
(
current_entry
+
n
>
(
int
)
c
->
entries
)
{
return
error
(
f
,
VORBIS_invalid_setup
);
}
memset
(
lengths
+
current_entry
,
current_length
,
n
);
memset
(
lengths
+
current_entry
,
current_length
,
n
);
current_entry
+=
n
;
current_entry
+=
n
;
...
@@ -3775,7 +3825,9 @@ static int start_decoder(vorb *f)
...
@@ -3775,7 +3825,9 @@ static int start_decoder(vorb *f)
c
->
value_bits
=
get_bits
(
f
,
4
)
+
1
;
c
->
value_bits
=
get_bits
(
f
,
4
)
+
1
;
c
->
sequence_p
=
get_bits
(
f
,
1
);
c
->
sequence_p
=
get_bits
(
f
,
1
);
if
(
c
->
lookup_type
==
1
)
{
if
(
c
->
lookup_type
==
1
)
{
c
->
lookup_values
=
lookup1_values
(
c
->
entries
,
c
->
dimensions
);
int
values
=
lookup1_values
(
c
->
entries
,
c
->
dimensions
);
if
(
values
<
0
)
return
error
(
f
,
VORBIS_invalid_setup
);
c
->
lookup_values
=
(
uint32
)
values
;
}
else
{
}
else
{
c
->
lookup_values
=
c
->
entries
*
c
->
dimensions
;
c
->
lookup_values
=
c
->
entries
*
c
->
dimensions
;
}
}
...
@@ -3911,11 +3963,14 @@ static int start_decoder(vorb *f)
...
@@ -3911,11 +3963,14 @@ static int start_decoder(vorb *f)
p
[
j
].
id
=
j
;
p
[
j
].
id
=
j
;
}
}
qsort
(
p
,
g
->
values
,
sizeof
(
p
[
0
]),
point_compare
);
qsort
(
p
,
g
->
values
,
sizeof
(
p
[
0
]),
point_compare
);
for
(
j
=
0
;
j
<
g
->
values
-
1
;
++
j
)
if
(
p
[
j
].
x
==
p
[
j
+
1
].
x
)
return
error
(
f
,
VORBIS_invalid_setup
);
for
(
j
=
0
;
j
<
g
->
values
;
++
j
)
for
(
j
=
0
;
j
<
g
->
values
;
++
j
)
g
->
sorted_order
[
j
]
=
(
uint8
)
p
[
j
].
id
;
g
->
sorted_order
[
j
]
=
(
uint8
)
p
[
j
].
id
;
// precompute the neighbors
// precompute the neighbors
for
(
j
=
2
;
j
<
g
->
values
;
++
j
)
{
for
(
j
=
2
;
j
<
g
->
values
;
++
j
)
{
int
low
,
hi
;
int
low
=
0
,
hi
=
0
;
neighbors
(
g
->
Xlist
,
j
,
&
low
,
&
hi
);
neighbors
(
g
->
Xlist
,
j
,
&
low
,
&
hi
);
g
->
neighbors
[
j
][
0
]
=
low
;
g
->
neighbors
[
j
][
0
]
=
low
;
g
->
neighbors
[
j
][
1
]
=
hi
;
g
->
neighbors
[
j
][
1
]
=
hi
;
...
@@ -3997,6 +4052,7 @@ static int start_decoder(vorb *f)
...
@@ -3997,6 +4052,7 @@ static int start_decoder(vorb *f)
max_submaps
=
m
->
submaps
;
max_submaps
=
m
->
submaps
;
if
(
get_bits
(
f
,
1
))
{
if
(
get_bits
(
f
,
1
))
{
m
->
coupling_steps
=
get_bits
(
f
,
8
)
+
1
;
m
->
coupling_steps
=
get_bits
(
f
,
8
)
+
1
;
if
(
m
->
coupling_steps
>
f
->
channels
)
return
error
(
f
,
VORBIS_invalid_setup
);
for
(
k
=
0
;
k
<
m
->
coupling_steps
;
++
k
)
{
for
(
k
=
0
;
k
<
m
->
coupling_steps
;
++
k
)
{
m
->
chan
[
k
].
magnitude
=
get_bits
(
f
,
ilog
(
f
->
channels
-
1
));
m
->
chan
[
k
].
magnitude
=
get_bits
(
f
,
ilog
(
f
->
channels
-
1
));
m
->
chan
[
k
].
angle
=
get_bits
(
f
,
ilog
(
f
->
channels
-
1
));
m
->
chan
[
k
].
angle
=
get_bits
(
f
,
ilog
(
f
->
channels
-
1
));
...
@@ -4050,6 +4106,7 @@ static int start_decoder(vorb *f)
...
@@ -4050,6 +4106,7 @@ static int start_decoder(vorb *f)
f
->
previous_window
[
i
]
=
(
float
*
)
setup_malloc
(
f
,
sizeof
(
float
)
*
f
->
blocksize_1
/
2
);
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
);
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
);
if
(
f
->
channel_buffers
[
i
]
==
NULL
||
f
->
previous_window
[
i
]
==
NULL
||
f
->
finalY
[
i
]
==
NULL
)
return
error
(
f
,
VORBIS_outofmem
);
memset
(
f
->
channel_buffers
[
i
],
0
,
sizeof
(
float
)
*
f
->
blocksize_1
);
#ifdef STB_VORBIS_NO_DEFER_FLOOR
#ifdef STB_VORBIS_NO_DEFER_FLOOR
f
->
floor_buffers
[
i
]
=
(
float
*
)
setup_malloc
(
f
,
sizeof
(
float
)
*
f
->
blocksize_1
/
2
);
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
);
if
(
f
->
floor_buffers
[
i
]
==
NULL
)
return
error
(
f
,
VORBIS_outofmem
);
...
@@ -4077,7 +4134,10 @@ static int start_decoder(vorb *f)
...
@@ -4077,7 +4134,10 @@ static int start_decoder(vorb *f)
int
i
,
max_part_read
=
0
;
int
i
,
max_part_read
=
0
;
for
(
i
=
0
;
i
<
f
->
residue_count
;
++
i
)
{
for
(
i
=
0
;
i
<
f
->
residue_count
;
++
i
)
{
Residue
*
r
=
f
->
residue_config
+
i
;
Residue
*
r
=
f
->
residue_config
+
i
;
int
n_read
=
r
->
end
-
r
->
begin
;
unsigned
int
actual_size
=
f
->
blocksize_1
/
2
;
unsigned
int
limit_r_begin
=
r
->
begin
<
actual_size
?
r
->
begin
:
actual_size
;
unsigned
int
limit_r_end
=
r
->
end
<
actual_size
?
r
->
end
:
actual_size
;
int
n_read
=
limit_r_end
-
limit_r_begin
;
int
part_read
=
n_read
/
r
->
part_size
;
int
part_read
=
n_read
/
r
->
part_size
;
if
(
part_read
>
max_part_read
)
if
(
part_read
>
max_part_read
)
max_part_read
=
part_read
;
max_part_read
=
part_read
;
...
@@ -4088,12 +4148,13 @@ static int start_decoder(vorb *f)
...
@@ -4088,12 +4148,13 @@ static int start_decoder(vorb *f)
classify_mem
=
f
->
channels
*
(
sizeof
(
void
*
)
+
max_part_read
*
sizeof
(
int
*
));
classify_mem
=
f
->
channels
*
(
sizeof
(
void
*
)
+
max_part_read
*
sizeof
(
int
*
));
#endif
#endif
// maximum reasonable partition size is f->blocksize_1
f
->
temp_memory_required
=
classify_mem
;
f
->
temp_memory_required
=
classify_mem
;
if
(
imdct_mem
>
f
->
temp_memory_required
)
if
(
imdct_mem
>
f
->
temp_memory_required
)
f
->
temp_memory_required
=
imdct_mem
;
f
->
temp_memory_required
=
imdct_mem
;
}
}
f
->
first_decode
=
TRUE
;
if
(
f
->
alloc
.
alloc_buffer
)
{
if
(
f
->
alloc
.
alloc_buffer
)
{
assert
(
f
->
temp_offset
==
f
->
alloc
.
alloc_buffer_length_in_bytes
);
assert
(
f
->
temp_offset
==
f
->
alloc
.
alloc_buffer_length_in_bytes
);
...
@@ -4102,7 +4163,17 @@ static int start_decoder(vorb *f)
...
@@ -4102,7 +4163,17 @@ static int start_decoder(vorb *f)
return
error
(
f
,
VORBIS_outofmem
);
return
error
(
f
,
VORBIS_outofmem
);
}
}
// @TODO: stb_vorbis_seek_start expects first_audio_page_offset to point to a page
// without PAGEFLAG_continued_packet, so this either points to the first page, or
// the page after the end of the headers. It might be cleaner to point to a page
// in the middle of the headers, when that's the page where the first audio packet
// starts, but we'd have to also correctly skip the end of any continued packet in
// stb_vorbis_seek_start.
if
(
f
->
next_seg
==
-
1
)
{
f
->
first_audio_page_offset
=
stb_vorbis_get_file_offset
(
f
);
f
->
first_audio_page_offset
=
stb_vorbis_get_file_offset
(
f
);
}
else
{
f
->
first_audio_page_offset
=
0
;
}
return
TRUE
;
return
TRUE
;
}
}
...
@@ -4110,6 +4181,13 @@ static int start_decoder(vorb *f)
...
@@ -4110,6 +4181,13 @@ static int start_decoder(vorb *f)
static
void
vorbis_deinit
(
stb_vorbis
*
p
)
static
void
vorbis_deinit
(
stb_vorbis
*
p
)
{
{
int
i
,
j
;
int
i
,
j
;
setup_free
(
p
,
p
->
vendor
);
for
(
i
=
0
;
i
<
p
->
comment_list_length
;
++
i
)
{
setup_free
(
p
,
p
->
comment_list
[
i
]);
}
setup_free
(
p
,
p
->
comment_list
);
if
(
p
->
residue_config
)
{
if
(
p
->
residue_config
)
{
for
(
i
=
0
;
i
<
p
->
residue_count
;
++
i
)
{
for
(
i
=
0
;
i
<
p
->
residue_count
;
++
i
)
{
Residue
*
r
=
p
->
residue_config
+
i
;
Residue
*
r
=
p
->
residue_config
+
i
;
...
@@ -4209,6 +4287,15 @@ stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f)
...
@@ -4209,6 +4287,15 @@ stb_vorbis_info stb_vorbis_get_info(stb_vorbis *f)
return
d
;
return
d
;
}
}
stb_vorbis_comment
stb_vorbis_get_comment
(
stb_vorbis
*
f
)
{
stb_vorbis_comment
d
;
d
.
vendor
=
f
->
vendor
;
d
.
comment_list_length
=
f
->
comment_list_length
;
d
.
comment_list
=
f
->
comment_list
;
return
d
;
}
int
stb_vorbis_get_error
(
stb_vorbis
*
f
)
int
stb_vorbis_get_error
(
stb_vorbis
*
f
)
{
{
int
e
=
f
->
error
;
int
e
=
f
->
error
;
...
@@ -4350,7 +4437,7 @@ int stb_vorbis_decode_frame_pushdata(
...
@@ -4350,7 +4437,7 @@ int stb_vorbis_decode_frame_pushdata(
f
->
error
=
VORBIS__no_error
;
f
->
error
=
VORBIS__no_error
;
// check that we have the entire packet in memory
// check that we have the entire packet in memory
if
(
!
is_whole_packet_present
(
f
,
FALSE
))
{
if
(
!
is_whole_packet_present
(
f
))
{
*
samples
=
0
;
*
samples
=
0
;
return
0
;
return
0
;
}
}
...
@@ -4555,7 +4642,7 @@ static int get_seek_page_info(stb_vorbis *f, ProbedPage *z)
...
@@ -4555,7 +4642,7 @@ static int get_seek_page_info(stb_vorbis *f, ProbedPage *z)
return
1
;
return
1
;
}
}
// rarely used function to seek back to the prece
e
ding page while finding the
// rarely used function to seek back to the preceding page while finding the
// start of a packet
// start of a packet
static
int
go_to_page_before
(
stb_vorbis
*
f
,
unsigned
int
limit_offset
)
static
int
go_to_page_before
(
stb_vorbis
*
f
,
unsigned
int
limit_offset
)
{
{
...
@@ -4586,8 +4673,8 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
...
@@ -4586,8 +4673,8 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
{
{
ProbedPage
left
,
right
,
mid
;
ProbedPage
left
,
right
,
mid
;
int
i
,
start_seg_with_known_loc
,
end_pos
,
page_start
;
int
i
,
start_seg_with_known_loc
,
end_pos
,
page_start
;
uint32
delta
,
stream_length
,
padding
;
uint32
delta
,
stream_length
,
padding
,
last_sample_limit
;
double
offset
,
bytes_per_sample
;
double
offset
=
0
.
0
,
bytes_per_sample
=
0
.
0
;
int
probe
=
0
;
int
probe
=
0
;
// find the last page and validate the target sample
// find the last page and validate the target sample
...
@@ -4600,9 +4687,9 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
...
@@ -4600,9 +4687,9 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
// indicates should be the granule position (give or take one)).
// indicates should be the granule position (give or take one)).
padding
=
((
f
->
blocksize_1
-
f
->
blocksize_0
)
>>
2
);
padding
=
((
f
->
blocksize_1
-
f
->
blocksize_0
)
>>
2
);
if
(
sample_number
<
padding
)
if
(
sample_number
<
padding
)
sample_number
=
0
;
last_sample_limit
=
0
;
else
else
sample_number
-=
padding
;
last_sample_limit
=
sample_number
-
padding
;
left
=
f
->
p_first
;
left
=
f
->
p_first
;
while
(
left
.
last_decoded_sample
==
~
0U
)
{
while
(
left
.
last_decoded_sample
==
~
0U
)
{
...
@@ -4615,9 +4702,12 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
...
@@ -4615,9 +4702,12 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
assert
(
right
.
last_decoded_sample
!=
~
0U
);
assert
(
right
.
last_decoded_sample
!=
~
0U
);
// starting from the start is handled differently
// starting from the start is handled differently
if
(
sample_number
<=
left
.
last_decoded_sample
)
{
if
(
last_sample_limit
<=
left
.
last_decoded_sample
)
{
if
(
stb_vorbis_seek_start
(
f
))
if
(
stb_vorbis_seek_start
(
f
))
{
if
(
f
->
current_loc
>
sample_number
)
return
error
(
f
,
VORBIS_seek_failed
);
return
1
;
return
1
;
}
return
0
;
return
0
;
}
}
...
@@ -4634,10 +4724,10 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
...
@@ -4634,10 +4724,10 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
// first probe (interpolate)
// first probe (interpolate)
double
data_bytes
=
right
.
page_end
-
left
.
page_start
;
double
data_bytes
=
right
.
page_end
-
left
.
page_start
;
bytes_per_sample
=
data_bytes
/
right
.
last_decoded_sample
;
bytes_per_sample
=
data_bytes
/
right
.
last_decoded_sample
;
offset
=
left
.
page_start
+
bytes_per_sample
*
(
sample_number
-
left
.
last_decoded_sample
);
offset
=
left
.
page_start
+
bytes_per_sample
*
(
last_sample_limit
-
left
.
last_decoded_sample
);
}
else
{
}
else
{
// second probe (try to bound the other side)
// second probe (try to bound the other side)
double
error
=
((
double
)
sample_number
-
mid
.
last_decoded_sample
)
*
bytes_per_sample
;
double
error
=
((
double
)
last_sample_limit
-
mid
.
last_decoded_sample
)
*
bytes_per_sample
;
if
(
error
>=
0
&&
error
<
8000
)
error
=
8000
;
if
(
error
>=
0
&&
error
<
8000
)
error
=
8000
;
if
(
error
<
0
&&
error
>
-
8000
)
error
=
-
8000
;
if
(
error
<
0
&&
error
>
-
8000
)
error
=
-
8000
;
offset
+=
error
*
2
;
offset
+=
error
*
2
;
...
@@ -4668,14 +4758,16 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
...
@@ -4668,14 +4758,16 @@ static int seek_to_sample_coarse(stb_vorbis *f, uint32 sample_number)
}
}
// if we've just found the last page again then we're in a tricky file,
// if we've just found the last page again then we're in a tricky file,
// and we're close enough.
// and we're close enough (if it wasn't an interpolation probe).
if
(
mid
.
page_start
==
right
.
page_start
)
if
(
mid
.
page_start
==
right
.
page_start
)
{
if
(
probe
>=
2
||
delta
<=
65536
)
break
;
break
;
}
else
{
if
(
sample_number
<
mid
.
last_decoded_sample
)
if
(
last_sample_limit
<
mid
.
last_decoded_sample
)
right
=
mid
;
right
=
mid
;
else
else
left
=
mid
;
left
=
mid
;
}
++
probe
;
++
probe
;
}
}
...
@@ -4791,8 +4883,8 @@ int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number)
...
@@ -4791,8 +4883,8 @@ int stb_vorbis_seek_frame(stb_vorbis *f, unsigned int sample_number)
flush_packet
(
f
);
flush_packet
(
f
);
}
}
}
}
// the next frame
will
start with the sample
// the next frame
should
start with the sample
assert
(
f
->
current_loc
==
sample_number
);
if
(
f
->
current_loc
!=
sample_number
)
return
error
(
f
,
VORBIS_seek_failed
);
return
1
;
return
1
;
}
}
...
@@ -4962,7 +5054,13 @@ stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, con
...
@@ -4962,7 +5054,13 @@ stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, con
stb_vorbis
*
stb_vorbis_open_filename
(
const
char
*
filename
,
int
*
error
,
const
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"
);
FILE
*
f
;
#if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__)
if
(
0
!=
fopen_s
(
&
f
,
filename
,
"rb"
))
f
=
NULL
;
#else
f
=
fopen
(
filename
,
"rb"
);
#endif
if
(
f
)
if
(
f
)
return
stb_vorbis_open_file
(
f
,
TRUE
,
error
,
alloc
);
return
stb_vorbis_open_file
(
f
,
TRUE
,
error
,
alloc
);
if
(
error
)
*
error
=
VORBIS_file_open_failure
;
if
(
error
)
*
error
=
VORBIS_file_open_failure
;
...
@@ -5128,7 +5226,7 @@ static void convert_samples_short(int buf_c, short **buffer, int b_offset, int d
...
@@ -5128,7 +5226,7 @@ static void convert_samples_short(int buf_c, short **buffer, int b_offset, int d
int
stb_vorbis_get_frame_short
(
stb_vorbis
*
f
,
int
num_c
,
short
**
buffer
,
int
num_samples
)
int
stb_vorbis_get_frame_short
(
stb_vorbis
*
f
,
int
num_c
,
short
**
buffer
,
int
num_samples
)
{
{
float
**
output
;
float
**
output
=
NULL
;
int
len
=
stb_vorbis_get_frame_float
(
f
,
NULL
,
&
output
);
int
len
=
stb_vorbis_get_frame_float
(
f
,
NULL
,
&
output
);
if
(
len
>
num_samples
)
len
=
num_samples
;
if
(
len
>
num_samples
)
len
=
num_samples
;
if
(
len
)
if
(
len
)
...
@@ -5351,20 +5449,28 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in
...
@@ -5351,20 +5449,28 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in
#endif // STB_VORBIS_NO_PULLDATA_API
#endif // STB_VORBIS_NO_PULLDATA_API
/* Version history
/* Version history
1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory
1.17 - 2019-07-08 - fix CVE-2019-13217, -13218, -13219, -13220, -13221, -13222, -13223
1.09 - 2016/04/04 - back out 'avoid discarding last frame' fix from previous version
found with Mayhem by ForAllSecure
1.08 - 2016/04/02 - fixed multiple warnings; fix setup memory leaks;
1.16 - 2019-03-04 - fix warnings
1.15 - 2019-02-07 - explicit failure if Ogg Skeleton data is found
1.14 - 2018-02-11 - delete bogus dealloca usage
1.13 - 2018-01-29 - fix truncation of last frame (hopefully)
1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files
1.11 - 2017-07-23 - fix MinGW compilation
1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory
1.09 - 2016-04-04 - back out 'avoid discarding last frame' fix from previous version
1.08 - 2016-04-02 - fixed multiple warnings; fix setup memory leaks;
avoid discarding last frame of audio data
avoid discarding last frame of audio data
1.07 - 2015
/01/
16 - fixed some warnings, fix mingw, const-correct API
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
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)
1.06 - 2015
-08-
31 - full, correct support for seeking API (Dougall Johnson)
some crash fixes when out of memory or with corrupt files
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.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.04 - 2014
-08-
27 - fix missing const-correct case in API
1.03 - 2014
/08/
07 - Warning fixes
1.03 - 2014
-08-
07 - Warning fixes
1.02 - 2014
/07/
09 - Declare qsort compare function _cdecl on windows
1.02 - 2014
-07-
09 - Declare qsort compare function _cdecl on windows
1.01 - 2014
/06/
18 - fix stb_vorbis_get_samples_float
1.01 - 2014
-06-
18 - fix stb_vorbis_get_samples_float
1.0 - 2014
/05/
26 - fix memory leaks; fix warnings; fix bugs in multichannel
1.0 - 2014
-05-
26 - fix memory leaks; fix warnings; fix bugs in multichannel
(API change) report sample rate for decode-full-file funcs
(API change) report sample rate for decode-full-file funcs
0.99996 - bracket #include <malloc.h> for macintosh compilation by Laurent Gomila
0.99996 - bracket #include <malloc.h> for macintosh compilation by Laurent Gomila
0.99995 - use union instead of pointer-cast for fast-float-to-int to avoid alias-optimization problem
0.99995 - use union instead of pointer-cast for fast-float-to-int to avoid alias-optimization problem
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment