mirror of
https://github.com/raysan5/raylib.git
synced 2026-04-26 16:47:25 -04:00
Compare commits
12 Commits
d3cc78d9d7
...
8743e11285
| Author | SHA1 | Date | |
|---|---|---|---|
| 8743e11285 | |||
| 04f81538b7 | |||
| 8d70f1007b | |||
| 6c0134bb5c | |||
| e9231bc4f1 | |||
| 4c79c6837b | |||
| e5f0c9f8b1 | |||
| d5326fe880 | |||
| adc4c9b875 | |||
| b09da8fce8 | |||
| 0b87a35e5a | |||
| a1bf8d9c75 |
26
CHANGELOG
26
CHANGELOG
@ -759,6 +759,7 @@ Detailed changes:
|
||||
[rexm] REVIEWED: `Makefile.Web` before trying to rebuild new example for web by @raysan5
|
||||
[rexm] REVIEWED: Using `Makefile.Web` for specific web versions generation by @raysan5
|
||||
|
||||
[external] ADDED: `cgltf_write` 1.15, to support glTF models export in the future, by @raysan5
|
||||
[external] RENAMED: `rl_gputex.h` to `rltexgpu.h`, compressed textures loading
|
||||
[external] REVIEWED: `rltexgpu.h`, make it usable standalone by @raysan5
|
||||
[external] REVIEWED: `rltexgpu.h, fix the swizzling in `rl_load_dds_from_memory()` (#5422) by @msmith-codes
|
||||
@ -767,16 +768,23 @@ Detailed changes:
|
||||
[external] REVIEWED: `sdefl` and `sinfl` issues (#5367) by @raysan5
|
||||
[external] REVIEWED: `sinfl_bsr()`, improvements by @RicoP
|
||||
[external] REVIEWED: `stb_truetype`, fix composite glyph scaling logic (#4811) by @ashishbhattarai
|
||||
[external] UPDATED: `raygui` to 5.0-dev for examples by @raysan5
|
||||
[external] UPDATED: dr_libs (#5020) by @Emil2010
|
||||
[external] UPDATED: miniaudio to v0.11.22 (#4983) by @M374LX
|
||||
[external] UPDATED: miniaudio to v0.11.23 (#5234) by @pyrokn8
|
||||
[external] UPDATED: miniaudio to v0.11.24 (#5506) by @vdemcak
|
||||
[external] UPDATED: raygui to 5.0-dev for examples by @raysan5
|
||||
[external] UPDATED: RGFW to 1.5 (#4688) by @ColleagueRiley
|
||||
[external] UPDATED: RGFW to 1.6 (#4795) by @colleagueRiley
|
||||
[external] UPDATED: RGFW to 1.7 (#4965) by @M374LX
|
||||
[external] UPDATED: RGFW to 1.7.5-dev (#4976) by @M374LX
|
||||
[external] UPDATED: RGFW to 2.0.0 (#5582) by @CrackedPixel
|
||||
[external] UPDATED: `miniaudio` to v0.11.22 (#4983) by @M374LX
|
||||
[external] UPDATED: `miniaudio` to v0.11.23 (#5234) by @pyrokn8
|
||||
[external] UPDATED: `miniaudio` to v0.11.24 (#5506) by @vdemcak
|
||||
[external] UPDATED: `RGFW` to 1.5 (#4688) by @ColleagueRiley
|
||||
[external] UPDATED: `RGFW` to 1.6 (#4795) by @colleagueRiley
|
||||
[external] UPDATED: `RGFW` to 1.7 (#4965) by @M374LX
|
||||
[external] UPDATED: `RGFW` to 1.7.5-dev (#4976) by @M374LX
|
||||
[external] UPDATED: `RGFW` to 2.0.0 (#5582) by @CrackedPixel
|
||||
[external] UPDATED: `cgltf` 1.14 to 1.15 by @raysan5
|
||||
[external] UPDATED: `dr_flac` v0.13.0 to v0.13.3 by @raysan5
|
||||
[external] UPDATED: `dr_mp3` v0.7.0 to v0.7.4 by @raysan5
|
||||
[external] UPDATED: `m3d` to latest master by @raysan5
|
||||
[external] UPDATED: `qoi` to latest master by @raysan5
|
||||
[external] UPDATED: `qoa` to latest master by @raysan5
|
||||
[external] UPDATED: `stb_image_resize2` v2.12 to v2.18 by @raysan5
|
||||
|
||||
[misc] ADDED: SECURITY.md for security reporting policies by @raysan5
|
||||
[misc] ADDED: `examples/examples_list`, to be used by `rexm` or other tools by @raysan5
|
||||
|
||||
211
src/external/cgltf.h
vendored
211
src/external/cgltf.h
vendored
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* cgltf - a single-file glTF 2.0 parser written in C99.
|
||||
*
|
||||
* Version: 1.14
|
||||
* Version: 1.15
|
||||
*
|
||||
* Website: https://github.com/jkuhlmann/cgltf
|
||||
*
|
||||
@ -141,7 +141,7 @@ typedef struct cgltf_memory_options
|
||||
typedef struct cgltf_file_options
|
||||
{
|
||||
cgltf_result(*read)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, const char* path, cgltf_size* size, void** data);
|
||||
void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data);
|
||||
void (*release)(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data, cgltf_size size);
|
||||
void* user_data;
|
||||
} cgltf_file_options;
|
||||
|
||||
@ -296,6 +296,7 @@ typedef enum cgltf_meshopt_compression_filter {
|
||||
cgltf_meshopt_compression_filter_octahedral,
|
||||
cgltf_meshopt_compression_filter_quaternion,
|
||||
cgltf_meshopt_compression_filter_exponential,
|
||||
cgltf_meshopt_compression_filter_color,
|
||||
cgltf_meshopt_compression_filter_max_enum
|
||||
} cgltf_meshopt_compression_filter;
|
||||
|
||||
@ -308,6 +309,7 @@ typedef struct cgltf_meshopt_compression
|
||||
cgltf_size count;
|
||||
cgltf_meshopt_compression_mode mode;
|
||||
cgltf_meshopt_compression_filter filter;
|
||||
cgltf_bool is_khr;
|
||||
} cgltf_meshopt_compression;
|
||||
|
||||
typedef struct cgltf_buffer_view
|
||||
@ -376,13 +378,29 @@ typedef struct cgltf_image
|
||||
cgltf_extension* extensions;
|
||||
} cgltf_image;
|
||||
|
||||
typedef enum cgltf_filter_type {
|
||||
cgltf_filter_type_undefined = 0,
|
||||
cgltf_filter_type_nearest = 9728,
|
||||
cgltf_filter_type_linear = 9729,
|
||||
cgltf_filter_type_nearest_mipmap_nearest = 9984,
|
||||
cgltf_filter_type_linear_mipmap_nearest = 9985,
|
||||
cgltf_filter_type_nearest_mipmap_linear = 9986,
|
||||
cgltf_filter_type_linear_mipmap_linear = 9987
|
||||
} cgltf_filter_type;
|
||||
|
||||
typedef enum cgltf_wrap_mode {
|
||||
cgltf_wrap_mode_clamp_to_edge = 33071,
|
||||
cgltf_wrap_mode_mirrored_repeat = 33648,
|
||||
cgltf_wrap_mode_repeat = 10497
|
||||
} cgltf_wrap_mode;
|
||||
|
||||
typedef struct cgltf_sampler
|
||||
{
|
||||
char* name;
|
||||
cgltf_int mag_filter;
|
||||
cgltf_int min_filter;
|
||||
cgltf_int wrap_s;
|
||||
cgltf_int wrap_t;
|
||||
cgltf_filter_type mag_filter;
|
||||
cgltf_filter_type min_filter;
|
||||
cgltf_wrap_mode wrap_s;
|
||||
cgltf_wrap_mode wrap_t;
|
||||
cgltf_extras extras;
|
||||
cgltf_size extensions_count;
|
||||
cgltf_extension* extensions;
|
||||
@ -500,6 +518,14 @@ typedef struct cgltf_iridescence
|
||||
cgltf_texture_view iridescence_thickness_texture;
|
||||
} cgltf_iridescence;
|
||||
|
||||
typedef struct cgltf_diffuse_transmission
|
||||
{
|
||||
cgltf_texture_view diffuse_transmission_texture;
|
||||
cgltf_float diffuse_transmission_factor;
|
||||
cgltf_float diffuse_transmission_color_factor[3];
|
||||
cgltf_texture_view diffuse_transmission_color_texture;
|
||||
} cgltf_diffuse_transmission;
|
||||
|
||||
typedef struct cgltf_anisotropy
|
||||
{
|
||||
cgltf_float anisotropy_strength;
|
||||
@ -525,6 +551,7 @@ typedef struct cgltf_material
|
||||
cgltf_bool has_sheen;
|
||||
cgltf_bool has_emissive_strength;
|
||||
cgltf_bool has_iridescence;
|
||||
cgltf_bool has_diffuse_transmission;
|
||||
cgltf_bool has_anisotropy;
|
||||
cgltf_bool has_dispersion;
|
||||
cgltf_pbr_metallic_roughness pbr_metallic_roughness;
|
||||
@ -537,6 +564,7 @@ typedef struct cgltf_material
|
||||
cgltf_volume volume;
|
||||
cgltf_emissive_strength emissive_strength;
|
||||
cgltf_iridescence iridescence;
|
||||
cgltf_diffuse_transmission diffuse_transmission;
|
||||
cgltf_anisotropy anisotropy;
|
||||
cgltf_dispersion dispersion;
|
||||
cgltf_texture_view normal_texture;
|
||||
@ -743,6 +771,7 @@ typedef struct cgltf_data
|
||||
{
|
||||
cgltf_file_type file_type;
|
||||
void* file_data;
|
||||
cgltf_size file_size;
|
||||
|
||||
cgltf_asset asset;
|
||||
|
||||
@ -844,6 +873,8 @@ void cgltf_node_transform_world(const cgltf_node* node, cgltf_float* out_matrix)
|
||||
|
||||
const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view);
|
||||
|
||||
const cgltf_accessor* cgltf_find_accessor(const cgltf_primitive* prim, cgltf_attribute_type type, cgltf_int index);
|
||||
|
||||
cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size);
|
||||
cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size index, cgltf_uint* out, cgltf_size element_size);
|
||||
cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size index);
|
||||
@ -1071,9 +1102,10 @@ static cgltf_result cgltf_default_file_read(const struct cgltf_memory_options* m
|
||||
return cgltf_result_success;
|
||||
}
|
||||
|
||||
static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data)
|
||||
static void cgltf_default_file_release(const struct cgltf_memory_options* memory_options, const struct cgltf_file_options* file_options, void* data, cgltf_size size)
|
||||
{
|
||||
(void)file_options;
|
||||
(void)size;
|
||||
void (*memfree)(void*, void*) = memory_options->free_func ? memory_options->free_func : &cgltf_default_free;
|
||||
memfree(memory_options->user_data, data);
|
||||
}
|
||||
@ -1220,7 +1252,7 @@ cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cg
|
||||
}
|
||||
|
||||
cgltf_result (*file_read)(const struct cgltf_memory_options*, const struct cgltf_file_options*, const char*, cgltf_size*, void**) = options->file.read ? options->file.read : &cgltf_default_file_read;
|
||||
void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = options->file.release ? options->file.release : cgltf_default_file_release;
|
||||
void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data, cgltf_size size) = options->file.release ? options->file.release : cgltf_default_file_release;
|
||||
|
||||
void* file_data = NULL;
|
||||
cgltf_size file_size = 0;
|
||||
@ -1234,11 +1266,12 @@ cgltf_result cgltf_parse_file(const cgltf_options* options, const char* path, cg
|
||||
|
||||
if (result != cgltf_result_success)
|
||||
{
|
||||
file_release(&options->memory, &options->file, file_data);
|
||||
file_release(&options->memory, &options->file, file_data, file_size);
|
||||
return result;
|
||||
}
|
||||
|
||||
(*out_data)->file_data = file_data;
|
||||
(*out_data)->file_size = file_size;
|
||||
|
||||
return cgltf_result_success;
|
||||
}
|
||||
@ -1630,8 +1663,8 @@ cgltf_result cgltf_validate(cgltf_data* data)
|
||||
CGLTF_ASSERT_IF((mc->mode == cgltf_meshopt_compression_mode_triangles || mc->mode == cgltf_meshopt_compression_mode_indices) && mc->filter != cgltf_meshopt_compression_filter_none, cgltf_result_invalid_gltf);
|
||||
|
||||
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_octahedral && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf);
|
||||
|
||||
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_quaternion && mc->stride != 8, cgltf_result_invalid_gltf);
|
||||
CGLTF_ASSERT_IF(mc->filter == cgltf_meshopt_compression_filter_color && mc->stride != 4 && mc->stride != 8, cgltf_result_invalid_gltf);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1822,7 +1855,7 @@ void cgltf_free(cgltf_data* data)
|
||||
return;
|
||||
}
|
||||
|
||||
void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data) = data->file.release ? data->file.release : cgltf_default_file_release;
|
||||
void (*file_release)(const struct cgltf_memory_options*, const struct cgltf_file_options*, void* data, cgltf_size size) = data->file.release ? data->file.release : cgltf_default_file_release;
|
||||
|
||||
data->memory.free_func(data->memory.user_data, data->asset.copyright);
|
||||
data->memory.free_func(data->memory.user_data, data->asset.generator);
|
||||
@ -1857,7 +1890,7 @@ void cgltf_free(cgltf_data* data)
|
||||
|
||||
if (data->buffers[i].data_free_method == cgltf_data_free_method_file_release)
|
||||
{
|
||||
file_release(&data->memory, &data->file, data->buffers[i].data);
|
||||
file_release(&data->memory, &data->file, data->buffers[i].data, data->buffers[i].size);
|
||||
}
|
||||
else if (data->buffers[i].data_free_method == cgltf_data_free_method_memory_free)
|
||||
{
|
||||
@ -2096,7 +2129,7 @@ void cgltf_free(cgltf_data* data)
|
||||
|
||||
data->memory.free_func(data->memory.user_data, data->extensions_required);
|
||||
|
||||
file_release(&data->memory, &data->file, data->file_data);
|
||||
file_release(&data->memory, &data->file, data->file_data, data->file_size);
|
||||
|
||||
data->memory.free_func(data->memory.user_data, data);
|
||||
}
|
||||
@ -2312,11 +2345,58 @@ const uint8_t* cgltf_buffer_view_data(const cgltf_buffer_view* view)
|
||||
return result;
|
||||
}
|
||||
|
||||
const cgltf_accessor* cgltf_find_accessor(const cgltf_primitive* prim, cgltf_attribute_type type, cgltf_int index)
|
||||
{
|
||||
for (cgltf_size i = 0; i < prim->attributes_count; ++i)
|
||||
{
|
||||
const cgltf_attribute* attr = &prim->attributes[i];
|
||||
if (attr->type == type && attr->index == index)
|
||||
return attr->data;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const uint8_t* cgltf_find_sparse_index(const cgltf_accessor* accessor, cgltf_size needle)
|
||||
{
|
||||
const cgltf_accessor_sparse* sparse = &accessor->sparse;
|
||||
const uint8_t* index_data = cgltf_buffer_view_data(sparse->indices_buffer_view);
|
||||
const uint8_t* value_data = cgltf_buffer_view_data(sparse->values_buffer_view);
|
||||
|
||||
if (index_data == NULL || value_data == NULL)
|
||||
return NULL;
|
||||
|
||||
index_data += sparse->indices_byte_offset;
|
||||
value_data += sparse->values_byte_offset;
|
||||
|
||||
cgltf_size index_stride = cgltf_component_size(sparse->indices_component_type);
|
||||
|
||||
cgltf_size offset = 0;
|
||||
cgltf_size length = sparse->count;
|
||||
|
||||
while (length)
|
||||
{
|
||||
cgltf_size rem = length % 2;
|
||||
length /= 2;
|
||||
|
||||
cgltf_size index = cgltf_component_read_index(index_data + (offset + length) * index_stride, sparse->indices_component_type);
|
||||
offset += index < needle ? length + rem : 0;
|
||||
}
|
||||
|
||||
if (offset == sparse->count)
|
||||
return NULL;
|
||||
|
||||
cgltf_size index = cgltf_component_read_index(index_data + offset * index_stride, sparse->indices_component_type);
|
||||
return index == needle ? value_data + offset * accessor->stride : NULL;
|
||||
}
|
||||
|
||||
cgltf_bool cgltf_accessor_read_float(const cgltf_accessor* accessor, cgltf_size index, cgltf_float* out, cgltf_size element_size)
|
||||
{
|
||||
if (accessor->is_sparse)
|
||||
{
|
||||
return 0;
|
||||
const uint8_t* element = cgltf_find_sparse_index(accessor, index);
|
||||
if (element)
|
||||
return cgltf_element_read_float(element, accessor->type, accessor->component_type, accessor->normalized, out, element_size);
|
||||
}
|
||||
if (accessor->buffer_view == NULL)
|
||||
{
|
||||
@ -2460,11 +2540,13 @@ cgltf_bool cgltf_accessor_read_uint(const cgltf_accessor* accessor, cgltf_size i
|
||||
{
|
||||
if (accessor->is_sparse)
|
||||
{
|
||||
return 0;
|
||||
const uint8_t* element = cgltf_find_sparse_index(accessor, index);
|
||||
if (element)
|
||||
return cgltf_element_read_uint(element, accessor->type, accessor->component_type, out, element_size);
|
||||
}
|
||||
if (accessor->buffer_view == NULL)
|
||||
{
|
||||
memset(out, 0, element_size * sizeof( cgltf_uint ));
|
||||
memset(out, 0, element_size * sizeof(cgltf_uint));
|
||||
return 1;
|
||||
}
|
||||
const uint8_t* element = cgltf_buffer_view_data(accessor->buffer_view);
|
||||
@ -2480,7 +2562,9 @@ cgltf_size cgltf_accessor_read_index(const cgltf_accessor* accessor, cgltf_size
|
||||
{
|
||||
if (accessor->is_sparse)
|
||||
{
|
||||
return 0; // This is an error case, but we can't communicate the error with existing interface.
|
||||
const uint8_t* element = cgltf_find_sparse_index(accessor, index);
|
||||
if (element)
|
||||
return cgltf_component_read_index(element, accessor->component_type);
|
||||
}
|
||||
if (accessor->buffer_view == NULL)
|
||||
{
|
||||
@ -2598,7 +2682,10 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o
|
||||
return accessor->count;
|
||||
}
|
||||
|
||||
index_count = accessor->count < index_count ? accessor->count : index_count;
|
||||
cgltf_size numbers_per_element = cgltf_num_components(accessor->type);
|
||||
cgltf_size available_numbers = accessor->count * numbers_per_element;
|
||||
|
||||
index_count = available_numbers < index_count ? available_numbers : index_count;
|
||||
cgltf_size index_component_size = cgltf_component_size(accessor->component_type);
|
||||
|
||||
if (accessor->is_sparse)
|
||||
@ -2620,15 +2707,23 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o
|
||||
}
|
||||
element += accessor->offset;
|
||||
|
||||
if (index_component_size == out_component_size && accessor->stride == out_component_size)
|
||||
if (index_component_size == out_component_size && accessor->stride == out_component_size * numbers_per_element)
|
||||
{
|
||||
memcpy(out, element, index_count * index_component_size);
|
||||
return index_count;
|
||||
}
|
||||
|
||||
// Data couldn't be copied with memcpy due to stride being larger than the component size.
|
||||
// OR
|
||||
// The component size of the output array is larger than the component size of the index data, so index data will be padded.
|
||||
switch (out_component_size)
|
||||
{
|
||||
case 1:
|
||||
for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
|
||||
{
|
||||
((uint8_t*)out)[index] = (uint8_t)cgltf_component_read_index(element, accessor->component_type);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for (cgltf_size index = 0; index < index_count; index++, element += accessor->stride)
|
||||
{
|
||||
@ -2642,7 +2737,7 @@ cgltf_size cgltf_accessor_unpack_indices(const cgltf_accessor* accessor, void* o
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return index_count;
|
||||
@ -4278,6 +4373,52 @@ static int cgltf_parse_json_iridescence(cgltf_options* options, jsmntok_t const*
|
||||
return i;
|
||||
}
|
||||
|
||||
static int cgltf_parse_json_diffuse_transmission(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_diffuse_transmission* out_diff_transmission)
|
||||
{
|
||||
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
int size = tokens[i].size;
|
||||
++i;
|
||||
|
||||
// Defaults
|
||||
cgltf_fill_float_array(out_diff_transmission->diffuse_transmission_color_factor, 3, 1.0f);
|
||||
out_diff_transmission->diffuse_transmission_factor = 0.f;
|
||||
|
||||
for (int j = 0; j < size; ++j)
|
||||
{
|
||||
CGLTF_CHECK_KEY(tokens[i]);
|
||||
|
||||
if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionFactor") == 0)
|
||||
{
|
||||
++i;
|
||||
out_diff_transmission->diffuse_transmission_factor = cgltf_json_to_float(tokens + i, json_chunk);
|
||||
++i;
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionTexture") == 0)
|
||||
{
|
||||
i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_diff_transmission->diffuse_transmission_texture);
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionColorFactor") == 0)
|
||||
{
|
||||
i = cgltf_parse_json_float_array(tokens, i + 1, json_chunk, out_diff_transmission->diffuse_transmission_color_factor, 3);
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "diffuseTransmissionColorTexture") == 0)
|
||||
{
|
||||
i = cgltf_parse_json_texture_view(options, tokens, i + 1, json_chunk, &out_diff_transmission->diffuse_transmission_color_texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = cgltf_skip_json(tokens, i + 1);
|
||||
}
|
||||
|
||||
if (i < 0)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int cgltf_parse_json_anisotropy(cgltf_options* options, jsmntok_t const* tokens, int i, const uint8_t* json_chunk, cgltf_anisotropy* out_anisotropy)
|
||||
{
|
||||
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
@ -4406,8 +4547,8 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok
|
||||
(void)options;
|
||||
CGLTF_CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
|
||||
|
||||
out_sampler->wrap_s = 10497;
|
||||
out_sampler->wrap_t = 10497;
|
||||
out_sampler->wrap_s = cgltf_wrap_mode_repeat;
|
||||
out_sampler->wrap_t = cgltf_wrap_mode_repeat;
|
||||
|
||||
int size = tokens[i].size;
|
||||
++i;
|
||||
@ -4424,28 +4565,28 @@ static int cgltf_parse_json_sampler(cgltf_options* options, jsmntok_t const* tok
|
||||
{
|
||||
++i;
|
||||
out_sampler->mag_filter
|
||||
= cgltf_json_to_int(tokens + i, json_chunk);
|
||||
= (cgltf_filter_type)cgltf_json_to_int(tokens + i, json_chunk);
|
||||
++i;
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "minFilter") == 0)
|
||||
{
|
||||
++i;
|
||||
out_sampler->min_filter
|
||||
= cgltf_json_to_int(tokens + i, json_chunk);
|
||||
= (cgltf_filter_type)cgltf_json_to_int(tokens + i, json_chunk);
|
||||
++i;
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapS") == 0)
|
||||
{
|
||||
++i;
|
||||
out_sampler->wrap_s
|
||||
= cgltf_json_to_int(tokens + i, json_chunk);
|
||||
= (cgltf_wrap_mode)cgltf_json_to_int(tokens + i, json_chunk);
|
||||
++i;
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "wrapT") == 0)
|
||||
{
|
||||
++i;
|
||||
out_sampler->wrap_t
|
||||
= cgltf_json_to_int(tokens + i, json_chunk);
|
||||
= (cgltf_wrap_mode)cgltf_json_to_int(tokens + i, json_chunk);
|
||||
++i;
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "extras") == 0)
|
||||
@ -4766,6 +4907,11 @@ static int cgltf_parse_json_material(cgltf_options* options, jsmntok_t const* to
|
||||
out_material->has_iridescence = 1;
|
||||
i = cgltf_parse_json_iridescence(options, tokens, i + 1, json_chunk, &out_material->iridescence);
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_diffuse_transmission") == 0)
|
||||
{
|
||||
out_material->has_diffuse_transmission = 1;
|
||||
i = cgltf_parse_json_diffuse_transmission(options, tokens, i + 1, json_chunk, &out_material->diffuse_transmission);
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens + i, json_chunk, "KHR_materials_anisotropy") == 0)
|
||||
{
|
||||
out_material->has_anisotropy = 1;
|
||||
@ -4974,6 +5120,10 @@ static int cgltf_parse_json_meshopt_compression(cgltf_options* options, jsmntok_
|
||||
{
|
||||
out_meshopt_compression->filter = cgltf_meshopt_compression_filter_exponential;
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens+i, json_chunk, "COLOR") == 0)
|
||||
{
|
||||
out_meshopt_compression->filter = cgltf_meshopt_compression_filter_color;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
else
|
||||
@ -5084,6 +5234,12 @@ static int cgltf_parse_json_buffer_view(cgltf_options* options, jsmntok_t const*
|
||||
out_buffer_view->has_meshopt_compression = 1;
|
||||
i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression);
|
||||
}
|
||||
else if (cgltf_json_strcmp(tokens+i, json_chunk, "KHR_meshopt_compression") == 0)
|
||||
{
|
||||
out_buffer_view->has_meshopt_compression = 1;
|
||||
out_buffer_view->meshopt_compression.is_khr = 1;
|
||||
i = cgltf_parse_json_meshopt_compression(options, tokens, i + 1, json_chunk, &out_buffer_view->meshopt_compression);
|
||||
}
|
||||
else
|
||||
{
|
||||
i = cgltf_parse_json_unprocessed_extension(options, tokens, i, json_chunk, &(out_buffer_view->extensions[out_buffer_view->extensions_count++]));
|
||||
@ -6629,6 +6785,9 @@ static int cgltf_fixup_pointers(cgltf_data* data)
|
||||
CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_texture.texture, data->textures, data->textures_count);
|
||||
CGLTF_PTRFIXUP(data->materials[i].iridescence.iridescence_thickness_texture.texture, data->textures, data->textures_count);
|
||||
|
||||
CGLTF_PTRFIXUP(data->materials[i].diffuse_transmission.diffuse_transmission_texture.texture, data->textures, data->textures_count);
|
||||
CGLTF_PTRFIXUP(data->materials[i].diffuse_transmission.diffuse_transmission_color_texture.texture, data->textures, data->textures_count);
|
||||
|
||||
CGLTF_PTRFIXUP(data->materials[i].anisotropy.anisotropy_texture.texture, data->textures, data->textures_count);
|
||||
}
|
||||
|
||||
|
||||
1565
src/external/cgltf_write.h
vendored
Normal file
1565
src/external/cgltf_write.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
306
src/external/dr_flac.h
vendored
306
src/external/dr_flac.h
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
FLAC audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||
dr_flac - v0.13.0 - TBD
|
||||
dr_flac - v0.13.3 - 2026-01-17
|
||||
|
||||
David Reid - mackron@gmail.com
|
||||
|
||||
@ -126,7 +126,7 @@ extern "C" {
|
||||
|
||||
#define DRFLAC_VERSION_MAJOR 0
|
||||
#define DRFLAC_VERSION_MINOR 13
|
||||
#define DRFLAC_VERSION_REVISION 0
|
||||
#define DRFLAC_VERSION_REVISION 3
|
||||
#define DRFLAC_VERSION_STRING DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MAJOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_MINOR) "." DRFLAC_XSTRINGIFY(DRFLAC_VERSION_REVISION)
|
||||
|
||||
#include <stddef.h> /* For size_t. */
|
||||
@ -331,6 +331,12 @@ typedef struct
|
||||
*/
|
||||
drflac_uint32 type;
|
||||
|
||||
/* The size in bytes of the block and the buffer pointed to by pRawData if it's non-NULL. */
|
||||
drflac_uint32 rawDataSize;
|
||||
|
||||
/* The offset in the stream of the raw data. */
|
||||
drflac_uint64 rawDataOffset;
|
||||
|
||||
/*
|
||||
A pointer to the raw data. This points to a temporary buffer so don't hold on to it. It's best to
|
||||
not modify the contents of this buffer. Use the structures below for more meaningful and structured
|
||||
@ -338,9 +344,6 @@ typedef struct
|
||||
*/
|
||||
const void* pRawData;
|
||||
|
||||
/* The size in bytes of the block and the buffer pointed to by pRawData if it's non-NULL. */
|
||||
drflac_uint32 rawDataSize;
|
||||
|
||||
union
|
||||
{
|
||||
drflac_streaminfo streaminfo;
|
||||
@ -392,6 +395,7 @@ typedef struct
|
||||
drflac_uint32 colorDepth;
|
||||
drflac_uint32 indexColorCount;
|
||||
drflac_uint32 pictureDataSize;
|
||||
drflac_uint64 pictureDataOffset; /* Offset from the start of the stream. */
|
||||
const drflac_uint8* pPictureData;
|
||||
} picture;
|
||||
} data;
|
||||
@ -2712,9 +2716,17 @@ static DRFLAC_INLINE drflac_uint32 drflac__clz_lzcnt(drflac_cache_t x)
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#if defined(DRFLAC_X64)
|
||||
{
|
||||
/*
|
||||
A note on lzcnt.
|
||||
|
||||
We check for the presence of the lzcnt instruction at runtime before calling this function, but we still generate this code. I have had
|
||||
a report where the assembler does not recognize the lzcnt instruction. To work around this we are going to use `rep; bsr` instead which
|
||||
has an identical byte encoding as lzcnt, and should hopefully improve compatibility with older assemblers.
|
||||
*/
|
||||
drflac_uint64 r;
|
||||
__asm__ __volatile__ (
|
||||
"lzcnt{ %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
|
||||
"rep; bsr{q %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
|
||||
/*"lzcnt{ %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"*/
|
||||
);
|
||||
|
||||
return (drflac_uint32)r;
|
||||
@ -2723,12 +2735,13 @@ static DRFLAC_INLINE drflac_uint32 drflac__clz_lzcnt(drflac_cache_t x)
|
||||
{
|
||||
drflac_uint32 r;
|
||||
__asm__ __volatile__ (
|
||||
"lzcnt{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
|
||||
"rep; bsr{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"
|
||||
/*"lzcnt{l %1, %0| %0, %1}" : "=r"(r) : "r"(x) : "cc"*/
|
||||
);
|
||||
|
||||
return r;
|
||||
}
|
||||
#elif defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5) && !defined(__ARM_ARCH_6M__) && !defined(DRFLAC_64BIT) /* <-- I haven't tested 64-bit inline assembly, so only enabling this for the 32-bit build for now. */
|
||||
#elif defined(DRFLAC_ARM) && (defined(__ARM_ARCH) && __ARM_ARCH >= 5) && !defined(__ARM_ARCH_6M__) && !(defined(__thumb__) && !defined(__thumb2__)) && !defined(DRFLAC_64BIT) /* <-- I haven't tested 64-bit inline assembly, so only enabling this for the 32-bit build for now. */
|
||||
{
|
||||
unsigned int r;
|
||||
__asm__ __volatile__ (
|
||||
@ -6434,8 +6447,9 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
||||
runningFilePos += 4;
|
||||
|
||||
metadata.type = blockType;
|
||||
metadata.pRawData = NULL;
|
||||
metadata.rawDataSize = 0;
|
||||
metadata.rawDataOffset = runningFilePos;
|
||||
metadata.pRawData = NULL;
|
||||
|
||||
switch (blockType)
|
||||
{
|
||||
@ -6712,59 +6726,151 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
||||
}
|
||||
|
||||
if (onMeta) {
|
||||
void* pRawData;
|
||||
const char* pRunningData;
|
||||
const char* pRunningDataEnd;
|
||||
drflac_bool32 result = DRFLAC_TRUE;
|
||||
drflac_uint32 blockSizeRemaining = blockSize;
|
||||
char* pMime = NULL;
|
||||
char* pDescription = NULL;
|
||||
void* pPictureData = NULL;
|
||||
|
||||
pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
|
||||
if (pRawData == NULL) {
|
||||
return DRFLAC_FALSE;
|
||||
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.type, 4) != 4) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
blockSizeRemaining -= 4;
|
||||
metadata.data.picture.type = drflac__be2host_32(metadata.data.picture.type);
|
||||
|
||||
|
||||
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.mimeLength, 4) != 4) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
blockSizeRemaining -= 4;
|
||||
metadata.data.picture.mimeLength = drflac__be2host_32(metadata.data.picture.mimeLength);
|
||||
|
||||
pMime = (char*)drflac__malloc_from_callbacks(metadata.data.picture.mimeLength + 1, pAllocationCallbacks); /* +1 for null terminator. */
|
||||
if (pMime == NULL) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
|
||||
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
|
||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
||||
return DRFLAC_FALSE;
|
||||
if (blockSizeRemaining < metadata.data.picture.mimeLength || onRead(pUserData, pMime, metadata.data.picture.mimeLength) != metadata.data.picture.mimeLength) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
blockSizeRemaining -= metadata.data.picture.mimeLength;
|
||||
pMime[metadata.data.picture.mimeLength] = '\0'; /* Null terminate for safety. */
|
||||
metadata.data.picture.mime = (const char*)pMime;
|
||||
|
||||
|
||||
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.descriptionLength, 4) != 4) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
blockSizeRemaining -= 4;
|
||||
metadata.data.picture.descriptionLength = drflac__be2host_32(metadata.data.picture.descriptionLength);
|
||||
|
||||
pDescription = (char*)drflac__malloc_from_callbacks(metadata.data.picture.descriptionLength + 1, pAllocationCallbacks); /* +1 for null terminator. */
|
||||
if (pDescription == NULL) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
|
||||
metadata.pRawData = pRawData;
|
||||
metadata.rawDataSize = blockSize;
|
||||
|
||||
pRunningData = (const char*)pRawData;
|
||||
pRunningDataEnd = (const char*)pRawData + blockSize;
|
||||
|
||||
metadata.data.picture.type = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
||||
metadata.data.picture.mimeLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
||||
|
||||
/* Need space for the rest of the block */
|
||||
if ((pRunningDataEnd - pRunningData) - 24 < (drflac_int64)metadata.data.picture.mimeLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
|
||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
||||
return DRFLAC_FALSE;
|
||||
if (blockSizeRemaining < metadata.data.picture.descriptionLength || onRead(pUserData, pDescription, metadata.data.picture.descriptionLength) != metadata.data.picture.descriptionLength) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
metadata.data.picture.mime = pRunningData; pRunningData += metadata.data.picture.mimeLength;
|
||||
metadata.data.picture.descriptionLength = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
||||
blockSizeRemaining -= metadata.data.picture.descriptionLength;
|
||||
pDescription[metadata.data.picture.descriptionLength] = '\0'; /* Null terminate for safety. */
|
||||
metadata.data.picture.description = (const char*)pDescription;
|
||||
|
||||
/* Need space for the rest of the block */
|
||||
if ((pRunningDataEnd - pRunningData) - 20 < (drflac_int64)metadata.data.picture.descriptionLength) { /* <-- Note the order of operations to avoid overflow to a valid value */
|
||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
||||
return DRFLAC_FALSE;
|
||||
|
||||
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.width, 4) != 4) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
metadata.data.picture.description = pRunningData; pRunningData += metadata.data.picture.descriptionLength;
|
||||
metadata.data.picture.width = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
||||
metadata.data.picture.height = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
||||
metadata.data.picture.colorDepth = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
||||
metadata.data.picture.indexColorCount = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
||||
metadata.data.picture.pictureDataSize = drflac__be2host_32_ptr_unaligned(pRunningData); pRunningData += 4;
|
||||
metadata.data.picture.pPictureData = (const drflac_uint8*)pRunningData;
|
||||
blockSizeRemaining -= 4;
|
||||
metadata.data.picture.width = drflac__be2host_32(metadata.data.picture.width);
|
||||
|
||||
/* Need space for the picture after the block */
|
||||
if (pRunningDataEnd - pRunningData < (drflac_int64)metadata.data.picture.pictureDataSize) { /* <-- Note the order of operations to avoid overflow to a valid value */
|
||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
||||
return DRFLAC_FALSE;
|
||||
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.height, 4) != 4) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
blockSizeRemaining -= 4;
|
||||
metadata.data.picture.height = drflac__be2host_32(metadata.data.picture.height);
|
||||
|
||||
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.colorDepth, 4) != 4) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
blockSizeRemaining -= 4;
|
||||
metadata.data.picture.colorDepth = drflac__be2host_32(metadata.data.picture.colorDepth);
|
||||
|
||||
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.indexColorCount, 4) != 4) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
blockSizeRemaining -= 4;
|
||||
metadata.data.picture.indexColorCount = drflac__be2host_32(metadata.data.picture.indexColorCount);
|
||||
|
||||
|
||||
/* Picture data. */
|
||||
if (blockSizeRemaining < 4 || onRead(pUserData, &metadata.data.picture.pictureDataSize, 4) != 4) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
blockSizeRemaining -= 4;
|
||||
metadata.data.picture.pictureDataSize = drflac__be2host_32(metadata.data.picture.pictureDataSize);
|
||||
|
||||
if (blockSizeRemaining < metadata.data.picture.pictureDataSize) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
|
||||
onMeta(pUserDataMD, &metadata);
|
||||
/* For the actual image data we want to store the offset to the start of the stream. */
|
||||
metadata.data.picture.pictureDataOffset = runningFilePos + (blockSize - blockSizeRemaining);
|
||||
|
||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
||||
/*
|
||||
For the allocation of image data, we can allow memory allocation to fail, in which case we just leave
|
||||
the pointer as null. If it fails, we need to fall back to seeking past the image data.
|
||||
*/
|
||||
#ifndef DR_FLAC_NO_PICTURE_METADATA_MALLOC
|
||||
pPictureData = drflac__malloc_from_callbacks(metadata.data.picture.pictureDataSize, pAllocationCallbacks);
|
||||
if (pPictureData != NULL) {
|
||||
if (onRead(pUserData, pPictureData, metadata.data.picture.pictureDataSize) != metadata.data.picture.pictureDataSize) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* Allocation failed. We need to seek past the picture data. */
|
||||
if (!onSeek(pUserData, metadata.data.picture.pictureDataSize, DRFLAC_SEEK_CUR)) {
|
||||
result = DRFLAC_FALSE;
|
||||
goto done_flac;
|
||||
}
|
||||
}
|
||||
|
||||
blockSizeRemaining -= metadata.data.picture.pictureDataSize;
|
||||
(void)blockSizeRemaining;
|
||||
|
||||
metadata.data.picture.pPictureData = (const drflac_uint8*)pPictureData;
|
||||
|
||||
|
||||
/* Only fire the callback if we actually have a way to read the image data. We must have either a valid offset, or a valid data pointer. */
|
||||
if (metadata.data.picture.pictureDataOffset != 0 || metadata.data.picture.pPictureData != NULL) {
|
||||
onMeta(pUserDataMD, &metadata);
|
||||
} else {
|
||||
/* Don't have a valid offset or data pointer, so just pretend we don't have a picture metadata. */
|
||||
}
|
||||
|
||||
done_flac:
|
||||
drflac__free_from_callbacks(pMime, pAllocationCallbacks);
|
||||
drflac__free_from_callbacks(pDescription, pAllocationCallbacks);
|
||||
drflac__free_from_callbacks(pPictureData, pAllocationCallbacks);
|
||||
|
||||
if (result != DRFLAC_TRUE) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
@ -6800,13 +6906,16 @@ static drflac_bool32 drflac__read_and_decode_metadata(drflac_read_proc onRead, d
|
||||
*/
|
||||
if (onMeta) {
|
||||
void* pRawData = drflac__malloc_from_callbacks(blockSize, pAllocationCallbacks);
|
||||
if (pRawData == NULL) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
|
||||
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
|
||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
||||
return DRFLAC_FALSE;
|
||||
if (pRawData != NULL) {
|
||||
if (onRead(pUserData, pRawData, blockSize) != blockSize) {
|
||||
drflac__free_from_callbacks(pRawData, pAllocationCallbacks);
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
} else {
|
||||
/* Allocation failed. We need to seek past the block. */
|
||||
if (!onSeek(pUserData, blockSize, DRFLAC_SEEK_CUR)) {
|
||||
return DRFLAC_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
metadata.pRawData = pRawData;
|
||||
@ -8699,7 +8808,7 @@ static drflac_bool32 drflac__on_tell_stdio(void* pUserData, drflac_int64* pCurso
|
||||
DRFLAC_ASSERT(pFileStdio != NULL);
|
||||
DRFLAC_ASSERT(pCursor != NULL);
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32) && !defined(NXDK)
|
||||
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||
result = _ftelli64(pFileStdio);
|
||||
#else
|
||||
@ -8821,8 +8930,6 @@ static drflac_bool32 drflac__on_seek_memory(void* pUserData, int offset, drflac_
|
||||
|
||||
DRFLAC_ASSERT(memoryStream != NULL);
|
||||
|
||||
newCursor = memoryStream->currentReadPos;
|
||||
|
||||
if (origin == DRFLAC_SEEK_SET) {
|
||||
newCursor = 0;
|
||||
} else if (origin == DRFLAC_SEEK_CUR) {
|
||||
@ -11702,58 +11809,43 @@ static type* drflac__full_read_and_close_ ## extension (drflac* pFlac, unsigned
|
||||
{ \
|
||||
type* pSampleData = NULL; \
|
||||
drflac_uint64 totalPCMFrameCount; \
|
||||
type buffer[4096]; \
|
||||
drflac_uint64 pcmFramesRead; \
|
||||
size_t sampleDataBufferSize = sizeof(buffer); \
|
||||
\
|
||||
DRFLAC_ASSERT(pFlac != NULL); \
|
||||
\
|
||||
totalPCMFrameCount = pFlac->totalPCMFrameCount; \
|
||||
totalPCMFrameCount = 0; \
|
||||
\
|
||||
if (totalPCMFrameCount == 0) { \
|
||||
type buffer[4096]; \
|
||||
drflac_uint64 pcmFramesRead; \
|
||||
size_t sampleDataBufferSize = sizeof(buffer); \
|
||||
pSampleData = (type*)drflac__malloc_from_callbacks(sampleDataBufferSize, &pFlac->allocationCallbacks); \
|
||||
if (pSampleData == NULL) { \
|
||||
goto on_error; \
|
||||
} \
|
||||
\
|
||||
pSampleData = (type*)drflac__malloc_from_callbacks(sampleDataBufferSize, &pFlac->allocationCallbacks); \
|
||||
if (pSampleData == NULL) { \
|
||||
goto on_error; \
|
||||
} \
|
||||
while ((pcmFramesRead = (drflac_uint64)drflac_read_pcm_frames_##extension(pFlac, sizeof(buffer)/sizeof(buffer[0])/pFlac->channels, buffer)) > 0) { \
|
||||
if (((totalPCMFrameCount + pcmFramesRead) * pFlac->channels * sizeof(type)) > sampleDataBufferSize) { \
|
||||
type* pNewSampleData; \
|
||||
size_t newSampleDataBufferSize; \
|
||||
\
|
||||
while ((pcmFramesRead = (drflac_uint64)drflac_read_pcm_frames_##extension(pFlac, sizeof(buffer)/sizeof(buffer[0])/pFlac->channels, buffer)) > 0) { \
|
||||
if (((totalPCMFrameCount + pcmFramesRead) * pFlac->channels * sizeof(type)) > sampleDataBufferSize) { \
|
||||
type* pNewSampleData; \
|
||||
size_t newSampleDataBufferSize; \
|
||||
\
|
||||
newSampleDataBufferSize = sampleDataBufferSize * 2; \
|
||||
pNewSampleData = (type*)drflac__realloc_from_callbacks(pSampleData, newSampleDataBufferSize, sampleDataBufferSize, &pFlac->allocationCallbacks); \
|
||||
if (pNewSampleData == NULL) { \
|
||||
drflac__free_from_callbacks(pSampleData, &pFlac->allocationCallbacks); \
|
||||
goto on_error; \
|
||||
} \
|
||||
\
|
||||
sampleDataBufferSize = newSampleDataBufferSize; \
|
||||
pSampleData = pNewSampleData; \
|
||||
newSampleDataBufferSize = sampleDataBufferSize * 2; \
|
||||
pNewSampleData = (type*)drflac__realloc_from_callbacks(pSampleData, newSampleDataBufferSize, sampleDataBufferSize, &pFlac->allocationCallbacks); \
|
||||
if (pNewSampleData == NULL) { \
|
||||
drflac__free_from_callbacks(pSampleData, &pFlac->allocationCallbacks); \
|
||||
goto on_error; \
|
||||
} \
|
||||
\
|
||||
DRFLAC_COPY_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), buffer, (size_t)(pcmFramesRead*pFlac->channels*sizeof(type))); \
|
||||
totalPCMFrameCount += pcmFramesRead; \
|
||||
sampleDataBufferSize = newSampleDataBufferSize; \
|
||||
pSampleData = pNewSampleData; \
|
||||
} \
|
||||
\
|
||||
/* At this point everything should be decoded, but we just want to fill the unused part buffer with silence - need to \
|
||||
protect those ears from random noise! */ \
|
||||
DRFLAC_ZERO_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), (size_t)(sampleDataBufferSize - totalPCMFrameCount*pFlac->channels*sizeof(type))); \
|
||||
} else { \
|
||||
drflac_uint64 dataSize = totalPCMFrameCount*pFlac->channels*sizeof(type); \
|
||||
if (dataSize > (drflac_uint64)DRFLAC_SIZE_MAX) { \
|
||||
goto on_error; /* The decoded data is too big. */ \
|
||||
} \
|
||||
\
|
||||
pSampleData = (type*)drflac__malloc_from_callbacks((size_t)dataSize, &pFlac->allocationCallbacks); /* <-- Safe cast as per the check above. */ \
|
||||
if (pSampleData == NULL) { \
|
||||
goto on_error; \
|
||||
} \
|
||||
\
|
||||
totalPCMFrameCount = drflac_read_pcm_frames_##extension(pFlac, pFlac->totalPCMFrameCount, pSampleData); \
|
||||
DRFLAC_COPY_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), buffer, (size_t)(pcmFramesRead*pFlac->channels*sizeof(type))); \
|
||||
totalPCMFrameCount += pcmFramesRead; \
|
||||
} \
|
||||
\
|
||||
/* At this point everything should be decoded, but we just want to fill the unused part buffer with silence - need to \
|
||||
protect those ears from random noise! */ \
|
||||
DRFLAC_ZERO_MEMORY(pSampleData + (totalPCMFrameCount*pFlac->channels), (size_t)(sampleDataBufferSize - totalPCMFrameCount*pFlac->channels*sizeof(type))); \
|
||||
\
|
||||
if (sampleRateOut) *sampleRateOut = pFlac->sampleRate; \
|
||||
if (channelsOut) *channelsOut = pFlac->channels; \
|
||||
if (totalPCMFrameCountOut) *totalPCMFrameCountOut = totalPCMFrameCount; \
|
||||
@ -12077,7 +12169,19 @@ DRFLAC_API drflac_bool32 drflac_next_cuesheet_track(drflac_cuesheet_track_iterat
|
||||
/*
|
||||
REVISION HISTORY
|
||||
================
|
||||
v0.13.0 - TBD
|
||||
v0.13.3 - 2026-01-17
|
||||
- Fix a compiler compatibility issue with some inlined assembly.
|
||||
- Fix a compilation warning.
|
||||
|
||||
v0.13.2 - 2025-12-02
|
||||
- Improve robustness of the parsing of picture metadata to improve support for memory constrained embedded devices.
|
||||
- Fix a warning about an assigned by unused variable.
|
||||
- Improvements to drflac_open_and_read_pcm_frames_*() and family to avoid excessively large memory allocations from malformed files.
|
||||
|
||||
v0.13.1 - 2025-09-10
|
||||
- Fix an error with the NXDK build.
|
||||
|
||||
v0.13.0 - 2025-07-23
|
||||
- API CHANGE: Seek origin enums have been renamed to match the naming convention used by other dr_libs libraries:
|
||||
- drflac_seek_origin_start -> DRFLAC_SEEK_SET
|
||||
- drflac_seek_origin_current -> DRFLAC_SEEK_CUR
|
||||
|
||||
171
src/external/dr_mp3.h
vendored
171
src/external/dr_mp3.h
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
MP3 audio decoder. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||
dr_mp3 - v0.7.0 - TBD
|
||||
dr_mp3 - v0.7.4 - TBD
|
||||
|
||||
David Reid - mackron@gmail.com
|
||||
|
||||
@ -72,7 +72,7 @@ extern "C" {
|
||||
|
||||
#define DRMP3_VERSION_MAJOR 0
|
||||
#define DRMP3_VERSION_MINOR 7
|
||||
#define DRMP3_VERSION_REVISION 0
|
||||
#define DRMP3_VERSION_REVISION 4
|
||||
#define DRMP3_VERSION_STRING DRMP3_XSTRINGIFY(DRMP3_VERSION_MAJOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_MINOR) "." DRMP3_XSTRINGIFY(DRMP3_VERSION_REVISION)
|
||||
|
||||
#include <stddef.h> /* For size_t. */
|
||||
@ -257,16 +257,45 @@ typedef struct
|
||||
Low Level Push API
|
||||
==================
|
||||
*/
|
||||
#define DRMP3_MAX_BITRESERVOIR_BYTES 511
|
||||
#define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE 2304 /* more than ISO spec's */
|
||||
#define DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES DRMP3_MAX_FREE_FORMAT_FRAME_SIZE /* MUST be >= 320000/8/32000*1152 = 1440 */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int frame_bytes, channels, sample_rate, layer, bitrate_kbps;
|
||||
} drmp3dec_frame_info;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const drmp3_uint8 *buf;
|
||||
int pos, limit;
|
||||
} drmp3_bs;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const drmp3_uint8 *sfbtab;
|
||||
drmp3_uint16 part_23_length, big_values, scalefac_compress;
|
||||
drmp3_uint8 global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb;
|
||||
drmp3_uint8 table_select[3], region_count[3], subblock_gain[3];
|
||||
drmp3_uint8 preflag, scalefac_scale, count1_table, scfsi;
|
||||
} drmp3_L3_gr_info;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
drmp3_bs bs;
|
||||
drmp3_uint8 maindata[DRMP3_MAX_BITRESERVOIR_BYTES + DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES];
|
||||
drmp3_L3_gr_info gr_info[4];
|
||||
float grbuf[2][576], scf[40], syn[18 + 15][2*32];
|
||||
drmp3_uint8 ist_pos[2][39];
|
||||
} drmp3dec_scratch;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float mdct_overlap[2][9*32], qmf_state[15*2*32];
|
||||
int reserv, free_format_bytes;
|
||||
drmp3_uint8 header[4], reserv_buf[511];
|
||||
drmp3dec_scratch scratch;
|
||||
} drmp3dec;
|
||||
|
||||
/* Initializes a low level decoder. */
|
||||
@ -592,14 +621,10 @@ DRMP3_API const char* drmp3_version_string(void)
|
||||
|
||||
#define DRMP3_OFFSET_PTR(p, offset) ((void*)((drmp3_uint8*)(p) + (offset)))
|
||||
|
||||
#define DRMP3_MAX_FREE_FORMAT_FRAME_SIZE 2304 /* more than ISO spec's */
|
||||
#ifndef DRMP3_MAX_FRAME_SYNC_MATCHES
|
||||
#define DRMP3_MAX_FRAME_SYNC_MATCHES 10
|
||||
#endif
|
||||
|
||||
#define DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES DRMP3_MAX_FREE_FORMAT_FRAME_SIZE /* MUST be >= 320000/8/32000*1152 = 1440 */
|
||||
|
||||
#define DRMP3_MAX_BITRESERVOIR_BYTES 511
|
||||
#define DRMP3_SHORT_BLOCK_TYPE 2
|
||||
#define DRMP3_STOP_BLOCK_TYPE 3
|
||||
#define DRMP3_MODE_MONO 3
|
||||
@ -632,8 +657,10 @@ DRMP3_API const char* drmp3_version_string(void)
|
||||
|
||||
#if !defined(DR_MP3_NO_SIMD)
|
||||
|
||||
#if !defined(DR_MP3_ONLY_SIMD) && (defined(_M_X64) || defined(__x86_64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC))
|
||||
/* x64 always have SSE2, arm64 always have neon, no need for generic code */
|
||||
#if !defined(DR_MP3_ONLY_SIMD) && ((defined(_MSC_VER) && _MSC_VER >= 1400) && defined(_M_X64)) || ((defined(__i386) || defined(_M_IX86) || defined(__i386__) || defined(__x86_64__)) && ((defined(_M_IX86_FP) && _M_IX86_FP == 2) || defined(__SSE2__)))
|
||||
#define DR_MP3_ONLY_SIMD
|
||||
#endif
|
||||
#if !defined(DR_MP3_ONLY_SIMD) && (defined(__ARM_NEON) || defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC))
|
||||
#define DR_MP3_ONLY_SIMD
|
||||
#endif
|
||||
|
||||
@ -655,7 +682,7 @@ DRMP3_API const char* drmp3_version_string(void)
|
||||
#define DRMP3_VMUL_S(x, s) _mm_mul_ps(x, _mm_set1_ps(s))
|
||||
#define DRMP3_VREV(x) _mm_shuffle_ps(x, x, _MM_SHUFFLE(0, 1, 2, 3))
|
||||
typedef __m128 drmp3_f4;
|
||||
#if defined(_MSC_VER) || defined(DR_MP3_ONLY_SIMD)
|
||||
#if (defined(_MSC_VER) || defined(DR_MP3_ONLY_SIMD)) && !defined(__clang__)
|
||||
#define drmp3_cpuid __cpuid
|
||||
#else
|
||||
static __inline__ __attribute__((always_inline)) void drmp3_cpuid(int CPUInfo[], const int InfoType)
|
||||
@ -779,11 +806,7 @@ static __inline__ __attribute__((always_inline)) drmp3_int32 drmp3_clip_int16_ar
|
||||
#define DRMP3_FREE(p) free((p))
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const drmp3_uint8 *buf;
|
||||
int pos, limit;
|
||||
} drmp3_bs;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -796,24 +819,6 @@ typedef struct
|
||||
drmp3_uint8 tab_offset, code_tab_width, band_count;
|
||||
} drmp3_L12_subband_alloc;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const drmp3_uint8 *sfbtab;
|
||||
drmp3_uint16 part_23_length, big_values, scalefac_compress;
|
||||
drmp3_uint8 global_gain, block_type, mixed_block_flag, n_long_sfb, n_short_sfb;
|
||||
drmp3_uint8 table_select[3], region_count[3], subblock_gain[3];
|
||||
drmp3_uint8 preflag, scalefac_scale, count1_table, scfsi;
|
||||
} drmp3_L3_gr_info;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
drmp3_bs bs;
|
||||
drmp3_uint8 maindata[DRMP3_MAX_BITRESERVOIR_BYTES + DRMP3_MAX_L3_FRAME_PAYLOAD_BYTES];
|
||||
drmp3_L3_gr_info gr_info[4];
|
||||
float grbuf[2][576], scf[40], syn[18 + 15][2*32];
|
||||
drmp3_uint8 ist_pos[2][39];
|
||||
} drmp3dec_scratch;
|
||||
|
||||
static void drmp3_bs_init(drmp3_bs *bs, const drmp3_uint8 *data, int bytes)
|
||||
{
|
||||
bs->buf = data;
|
||||
@ -1227,6 +1232,14 @@ static float drmp3_L3_ldexp_q2(float y, int exp_q2)
|
||||
return y;
|
||||
}
|
||||
|
||||
/*
|
||||
I've had reports of GCC 14 throwing an incorrect -Wstringop-overflow warning here. This is an attempt
|
||||
to silence this warning.
|
||||
*/
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 13)) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstringop-overflow"
|
||||
#endif
|
||||
static void drmp3_L3_decode_scalefactors(const drmp3_uint8 *hdr, drmp3_uint8 *ist_pos, drmp3_bs *bs, const drmp3_L3_gr_info *gr, float *scf, int ch)
|
||||
{
|
||||
static const drmp3_uint8 g_scf_partitions[3][28] = {
|
||||
@ -1288,6 +1301,9 @@ static void drmp3_L3_decode_scalefactors(const drmp3_uint8 *hdr, drmp3_uint8 *is
|
||||
scf[i] = drmp3_L3_ldexp_q2(gain, iscf[i] << scf_shift);
|
||||
}
|
||||
}
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 13)) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
static const float g_drmp3_pow43[129 + 16] = {
|
||||
0,-1,-2.519842f,-4.326749f,-6.349604f,-8.549880f,-10.902724f,-13.390518f,-16.000000f,-18.720754f,-21.544347f,-24.463781f,-27.473142f,-30.567351f,-33.741992f,-36.993181f,
|
||||
@ -2299,7 +2315,6 @@ DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int m
|
||||
int i = 0, igr, frame_size = 0, success = 1;
|
||||
const drmp3_uint8 *hdr;
|
||||
drmp3_bs bs_frame[1];
|
||||
drmp3dec_scratch scratch;
|
||||
|
||||
if (mp3_bytes > 4 && dec->header[0] == 0xff && drmp3_hdr_compare(dec->header, mp3))
|
||||
{
|
||||
@ -2336,23 +2351,23 @@ DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int m
|
||||
|
||||
if (info->layer == 3)
|
||||
{
|
||||
int main_data_begin = drmp3_L3_read_side_info(bs_frame, scratch.gr_info, hdr);
|
||||
int main_data_begin = drmp3_L3_read_side_info(bs_frame, dec->scratch.gr_info, hdr);
|
||||
if (main_data_begin < 0 || bs_frame->pos > bs_frame->limit)
|
||||
{
|
||||
drmp3dec_init(dec);
|
||||
return 0;
|
||||
}
|
||||
success = drmp3_L3_restore_reservoir(dec, bs_frame, &scratch, main_data_begin);
|
||||
success = drmp3_L3_restore_reservoir(dec, bs_frame, &dec->scratch, main_data_begin);
|
||||
if (success && pcm != NULL)
|
||||
{
|
||||
for (igr = 0; igr < (DRMP3_HDR_TEST_MPEG1(hdr) ? 2 : 1); igr++, pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*576*info->channels))
|
||||
{
|
||||
DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float));
|
||||
drmp3_L3_decode(dec, &scratch, scratch.gr_info + igr*info->channels, info->channels);
|
||||
drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 18, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]);
|
||||
DRMP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float));
|
||||
drmp3_L3_decode(dec, &dec->scratch, dec->scratch.gr_info + igr*info->channels, info->channels);
|
||||
drmp3d_synth_granule(dec->qmf_state, dec->scratch.grbuf[0], 18, info->channels, (drmp3d_sample_t*)pcm, dec->scratch.syn[0]);
|
||||
}
|
||||
}
|
||||
drmp3_L3_save_reservoir(dec, &scratch);
|
||||
drmp3_L3_save_reservoir(dec, &dec->scratch);
|
||||
} else
|
||||
{
|
||||
#ifdef DR_MP3_ONLY_MP3
|
||||
@ -2366,15 +2381,15 @@ DRMP3_API int drmp3dec_decode_frame(drmp3dec *dec, const drmp3_uint8 *mp3, int m
|
||||
|
||||
drmp3_L12_read_scale_info(hdr, bs_frame, sci);
|
||||
|
||||
DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float));
|
||||
DRMP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float));
|
||||
for (i = 0, igr = 0; igr < 3; igr++)
|
||||
{
|
||||
if (12 == (i += drmp3_L12_dequantize_granule(scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1)))
|
||||
if (12 == (i += drmp3_L12_dequantize_granule(dec->scratch.grbuf[0] + i, bs_frame, sci, info->layer | 1)))
|
||||
{
|
||||
i = 0;
|
||||
drmp3_L12_apply_scf_384(sci, sci->scf + igr, scratch.grbuf[0]);
|
||||
drmp3d_synth_granule(dec->qmf_state, scratch.grbuf[0], 12, info->channels, (drmp3d_sample_t*)pcm, scratch.syn[0]);
|
||||
DRMP3_ZERO_MEMORY(scratch.grbuf[0], 576*2*sizeof(float));
|
||||
drmp3_L12_apply_scf_384(sci, sci->scf + igr, dec->scratch.grbuf[0]);
|
||||
drmp3d_synth_granule(dec->qmf_state, dec->scratch.grbuf[0], 12, info->channels, (drmp3d_sample_t*)pcm, dec->scratch.syn[0]);
|
||||
DRMP3_ZERO_MEMORY(dec->scratch.grbuf[0], 576*2*sizeof(float));
|
||||
pcm = DRMP3_OFFSET_PTR(pcm, sizeof(drmp3d_sample_t)*384*info->channels);
|
||||
}
|
||||
if (bs_frame->pos > bs_frame->limit)
|
||||
@ -3005,23 +3020,27 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
||||
((drmp3_uint32)ape[26] << 16) |
|
||||
((drmp3_uint32)ape[27] << 24);
|
||||
|
||||
streamEndOffset -= 32 + tagSize;
|
||||
streamLen -= 32 + tagSize;
|
||||
|
||||
/* Fire a metadata callback for the APE data. Must include both the main content and footer. */
|
||||
if (onMeta != NULL) {
|
||||
/* We first need to seek to the start of the APE tag. */
|
||||
if (onSeek(pUserData, streamEndOffset, DRMP3_SEEK_END)) {
|
||||
size_t apeTagSize = (size_t)tagSize + 32;
|
||||
drmp3_uint8* pTagData = (drmp3_uint8*)drmp3_malloc(apeTagSize, pAllocationCallbacks);
|
||||
if (pTagData != NULL) {
|
||||
if (onRead(pUserData, pTagData, apeTagSize) == apeTagSize) {
|
||||
drmp3__on_meta(pMP3, DRMP3_METADATA_TYPE_APE, pTagData, apeTagSize);
|
||||
}
|
||||
if (32 + tagSize < streamLen) {
|
||||
streamEndOffset -= 32 + tagSize;
|
||||
streamLen -= 32 + tagSize;
|
||||
|
||||
/* Fire a metadata callback for the APE data. Must include both the main content and footer. */
|
||||
if (onMeta != NULL) {
|
||||
/* We first need to seek to the start of the APE tag. */
|
||||
if (onSeek(pUserData, streamEndOffset, DRMP3_SEEK_END)) {
|
||||
size_t apeTagSize = (size_t)tagSize + 32;
|
||||
drmp3_uint8* pTagData = (drmp3_uint8*)drmp3_malloc(apeTagSize, pAllocationCallbacks);
|
||||
if (pTagData != NULL) {
|
||||
if (onRead(pUserData, pTagData, apeTagSize) == apeTagSize) {
|
||||
drmp3__on_meta(pMP3, DRMP3_METADATA_TYPE_APE, pTagData, apeTagSize);
|
||||
}
|
||||
|
||||
drmp3_free(pTagData, pAllocationCallbacks);
|
||||
drmp3_free(pTagData, pAllocationCallbacks);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* The tag size is larger than the stream. Invalid APE tag. */
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3153,7 +3172,6 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
||||
{
|
||||
drmp3_bs bs;
|
||||
drmp3_L3_gr_info grInfo[4];
|
||||
const drmp3_uint8* pTagData = pFirstFrameData;
|
||||
|
||||
drmp3_bs_init(&bs, pFirstFrameData + DRMP3_HDR_SIZE, firstFrameInfo.frame_bytes - DRMP3_HDR_SIZE);
|
||||
|
||||
@ -3164,6 +3182,7 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
||||
if (drmp3_L3_read_side_info(&bs, grInfo, pFirstFrameData) >= 0) {
|
||||
drmp3_bool32 isXing = DRMP3_FALSE;
|
||||
drmp3_bool32 isInfo = DRMP3_FALSE;
|
||||
const drmp3_uint8* pTagData;
|
||||
const drmp3_uint8* pTagDataBeg;
|
||||
|
||||
pTagDataBeg = pFirstFrameData + DRMP3_HDR_SIZE + (bs.pos/8);
|
||||
@ -3246,6 +3265,13 @@ static drmp3_bool32 drmp3_init_internal(drmp3* pMP3, drmp3_read_proc onRead, drm
|
||||
/* The start offset needs to be moved to the end of this frame so it's not included in any audio processing after seeking. */
|
||||
pMP3->streamStartOffset += (drmp3_uint32)(firstFrameInfo.frame_bytes);
|
||||
pMP3->streamCursor = pMP3->streamStartOffset;
|
||||
|
||||
/*
|
||||
The internal decoder needs to be reset to clear out any state. If we don't reset this state, it's possible for
|
||||
there to be inconsistencies in the number of samples read when reading to the end of the stream depending on
|
||||
whether or not the caller seeks to the start of the stream.
|
||||
*/
|
||||
drmp3dec_init(&pMP3->decoder);
|
||||
}
|
||||
} else {
|
||||
/* Failed to read the side info. */
|
||||
@ -3307,8 +3333,6 @@ static drmp3_bool32 drmp3__on_seek_memory(void* pUserData, int byteOffset, drmp3
|
||||
|
||||
DRMP3_ASSERT(pMP3 != NULL);
|
||||
|
||||
newCursor = pMP3->memory.currentReadPos;
|
||||
|
||||
if (origin == DRMP3_SEEK_SET) {
|
||||
newCursor = 0;
|
||||
} else if (origin == DRMP3_SEEK_CUR) {
|
||||
@ -3981,7 +4005,7 @@ static drmp3_bool32 drmp3__on_tell_stdio(void* pUserData, drmp3_int64* pCursor)
|
||||
DRMP3_ASSERT(pFileStdio != NULL);
|
||||
DRMP3_ASSERT(pCursor != NULL);
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32) && !defined(NXDK)
|
||||
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||
result = _ftelli64(pFileStdio);
|
||||
#else
|
||||
@ -4780,6 +4804,8 @@ static float* drmp3__full_read_and_close_f32(drmp3* pMP3, drmp3_config* pConfig,
|
||||
pNewFrames = (float*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
|
||||
if (pNewFrames == NULL) {
|
||||
drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks);
|
||||
pFrames = NULL;
|
||||
totalFramesRead = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4847,6 +4873,8 @@ static drmp3_int16* drmp3__full_read_and_close_s16(drmp3* pMP3, drmp3_config* pC
|
||||
pNewFrames = (drmp3_int16*)drmp3__realloc_from_callbacks(pFrames, (size_t)newFramesBufferSize, (size_t)oldFramesBufferSize, &pMP3->allocationCallbacks);
|
||||
if (pNewFrames == NULL) {
|
||||
drmp3__free_from_callbacks(pFrames, &pMP3->allocationCallbacks);
|
||||
pFrames = NULL;
|
||||
totalFramesRead = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4981,7 +5009,24 @@ DIFFERENCES BETWEEN minimp3 AND dr_mp3
|
||||
/*
|
||||
REVISION HISTORY
|
||||
================
|
||||
v0.7.0 - TBD
|
||||
v0.7.4 - TBD
|
||||
- Improvements to SIMD detection.
|
||||
|
||||
v0.7.3 - 2026-01-17
|
||||
- Fix an error in drmp3_open_and_read_pcm_frames_s16() and family when memory allocation fails.
|
||||
- Fix some compilation warnings.
|
||||
|
||||
v0.7.2 - 2025-12-02
|
||||
- Reduce stack space to improve robustness on embedded systems.
|
||||
- Fix a compilation error with MSVC Clang toolset relating to cpuid.
|
||||
- Fix an error with APE tag parsing.
|
||||
|
||||
v0.7.1 - 2025-09-10
|
||||
- Silence a warning with GCC.
|
||||
- Fix an error with the NXDK build.
|
||||
- Fix a decoding inconsistency when seeking. Prior to this change, reading to the end of the stream immediately after initializing will result in a different number of samples read than if the stream is seeked to the start and read to the end.
|
||||
|
||||
v0.7.0 - 2025-07-23
|
||||
- The old `DRMP3_IMPLEMENTATION` has been removed. Use `DR_MP3_IMPLEMENTATION` instead. The reason for this change is that in the future everything will eventually be using the underscored naming convention in the future, so `drmp3` will become `dr_mp3`.
|
||||
- API CHANGE: Seek origins have been renamed to match the naming convention used by dr_wav and my other libraries.
|
||||
- drmp3_seek_origin_start -> DRMP3_SEEK_SET
|
||||
|
||||
133
src/external/dr_wav.h
vendored
133
src/external/dr_wav.h
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
WAV audio loader and writer. Choice of public domain or MIT-0. See license statements at the end of this file.
|
||||
dr_wav - v0.14.0 - TBD
|
||||
dr_wav - v0.14.5 - 2026-03-03
|
||||
|
||||
David Reid - mackron@gmail.com
|
||||
|
||||
@ -147,7 +147,7 @@ extern "C" {
|
||||
|
||||
#define DRWAV_VERSION_MAJOR 0
|
||||
#define DRWAV_VERSION_MINOR 14
|
||||
#define DRWAV_VERSION_REVISION 0
|
||||
#define DRWAV_VERSION_REVISION 5
|
||||
#define DRWAV_VERSION_STRING DRWAV_XSTRINGIFY(DRWAV_VERSION_MAJOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_MINOR) "." DRWAV_XSTRINGIFY(DRWAV_VERSION_REVISION)
|
||||
|
||||
#include <stddef.h> /* For size_t. */
|
||||
@ -2189,6 +2189,22 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars
|
||||
|
||||
if (pMetadata != NULL && bytesJustRead == sizeof(smplHeaderData)) {
|
||||
drwav_uint32 iSampleLoop;
|
||||
drwav_uint32 loopCount;
|
||||
drwav_uint32 calculatedLoopCount;
|
||||
|
||||
/*
|
||||
When we calcualted the amount of memory required for the "smpl" chunk we excluded the chunk entirely
|
||||
if the loop count in the header did not match with the calculated count based on the size of the
|
||||
chunk. When this happens, the second stage will still hit this path but the `pMetadata` will be
|
||||
non-null, but will either be pointing at the very end of the allocation or at the start of another
|
||||
chunk. We need to check the loop counts for consistency *before* dereferencing the pMetadata object
|
||||
so it's consistent with how we do it in the first stage.
|
||||
*/
|
||||
loopCount = drwav_bytes_to_u32(smplHeaderData + 28);
|
||||
calculatedLoopCount = (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES;
|
||||
if (loopCount != calculatedLoopCount) {
|
||||
return totalBytesRead;
|
||||
}
|
||||
|
||||
pMetadata->type = drwav_metadata_type_smpl;
|
||||
pMetadata->data.smpl.manufacturerId = drwav_bytes_to_u32(smplHeaderData + 0);
|
||||
@ -2205,7 +2221,7 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars
|
||||
The loop count needs to be validated against the size of the chunk for safety so we don't
|
||||
attempt to read over the boundary of the chunk.
|
||||
*/
|
||||
if (pMetadata->data.smpl.sampleLoopCount == (pChunkHeader->sizeInBytes - DRWAV_SMPL_BYTES) / DRWAV_SMPL_LOOP_BYTES) {
|
||||
if (pMetadata->data.smpl.sampleLoopCount == calculatedLoopCount) {
|
||||
pMetadata->data.smpl.pLoops = (drwav_smpl_loop*)drwav__metadata_get_memory(pParser, sizeof(drwav_smpl_loop) * pMetadata->data.smpl.sampleLoopCount, DRWAV_METADATA_ALIGNMENT);
|
||||
|
||||
for (iSampleLoop = 0; iSampleLoop < pMetadata->data.smpl.sampleLoopCount; ++iSampleLoop) {
|
||||
@ -2230,6 +2246,15 @@ DRWAV_PRIVATE drwav_uint64 drwav__read_smpl_to_metadata_obj(drwav__metadata_pars
|
||||
|
||||
drwav__metadata_parser_read(pParser, pMetadata->data.smpl.pSamplerSpecificData, pMetadata->data.smpl.samplerSpecificDataSizeInBytes, &totalBytesRead);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
Getting here means the loop count in the header does not match up with the size of the
|
||||
chunk. Clear out the data to zero just to be safe.
|
||||
|
||||
This should never actually get hit because we check for it above, but keeping this here
|
||||
for added safety.
|
||||
*/
|
||||
DRWAV_ZERO_OBJECT(&pMetadata->data.smpl);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3605,7 +3630,7 @@ DRWAV_PRIVATE drwav_bool32 drwav_init__internal(drwav* pWav, drwav_chunk_proc on
|
||||
we'll need to abort because we can't be doing a backwards seek back to the SSND chunk in order to read the
|
||||
data. For this reason, this configuration of AIFF files are not supported with sequential mode.
|
||||
*/
|
||||
return DRWAV_FALSE;
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
} else {
|
||||
chunkSize += header.paddingSize; /* <-- Make sure we seek past the padding. */
|
||||
@ -5285,7 +5310,7 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_tell_stdio(void* pUserData, drwav_int64* pC
|
||||
DRWAV_ASSERT(pFileStdio != NULL);
|
||||
DRWAV_ASSERT(pCursor != NULL);
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(_WIN32) && !defined(NXDK)
|
||||
#if defined(_MSC_VER) && _MSC_VER > 1200
|
||||
result = _ftelli64(pFileStdio);
|
||||
#else
|
||||
@ -5492,8 +5517,6 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory(void* pUserData, int offset, dr
|
||||
|
||||
DRWAV_ASSERT(pWav != NULL);
|
||||
|
||||
newCursor = pWav->memoryStream.currentReadPos;
|
||||
|
||||
if (origin == DRWAV_SEEK_SET) {
|
||||
newCursor = 0;
|
||||
} else if (origin == DRWAV_SEEK_CUR) {
|
||||
@ -5566,8 +5589,6 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offs
|
||||
|
||||
DRWAV_ASSERT(pWav != NULL);
|
||||
|
||||
newCursor = pWav->memoryStreamWrite.currentWritePos;
|
||||
|
||||
if (origin == DRWAV_SEEK_SET) {
|
||||
newCursor = 0;
|
||||
} else if (origin == DRWAV_SEEK_CUR) {
|
||||
@ -5576,7 +5597,7 @@ DRWAV_PRIVATE drwav_bool32 drwav__on_seek_memory_write(void* pUserData, int offs
|
||||
newCursor = (drwav_int64)pWav->memoryStreamWrite.dataSize;
|
||||
} else {
|
||||
DRWAV_ASSERT(!"Invalid seek origin");
|
||||
return DRWAV_INVALID_ARGS;
|
||||
return DRWAV_FALSE;
|
||||
}
|
||||
|
||||
newCursor += offset;
|
||||
@ -6258,12 +6279,12 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
||||
{
|
||||
drwav_uint64 totalFramesRead = 0;
|
||||
|
||||
static drwav_int32 adaptationTable[] = {
|
||||
static const drwav_int32 adaptationTable[] = {
|
||||
230, 230, 230, 230, 307, 409, 512, 614,
|
||||
768, 614, 512, 409, 307, 230, 230, 230
|
||||
};
|
||||
static drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 };
|
||||
static drwav_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 };
|
||||
static const drwav_int32 coeff1Table[] = { 256, 512, 0, 192, 240, 460, 392 };
|
||||
static const drwav_int32 coeff2Table[] = { 0, -256, 0, 64, 0, -208, -232 };
|
||||
|
||||
DRWAV_ASSERT(pWav != NULL);
|
||||
DRWAV_ASSERT(framesToRead > 0);
|
||||
@ -6292,7 +6313,7 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
||||
pWav->msadpcm.cachedFrameCount = 2;
|
||||
|
||||
/* The predictor is used as an index into coeff1Table so we'll need to validate to ensure it never overflows. */
|
||||
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table)) {
|
||||
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table)) {
|
||||
return totalFramesRead; /* Invalid file. */
|
||||
}
|
||||
} else {
|
||||
@ -6319,7 +6340,8 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
||||
pWav->msadpcm.cachedFrameCount = 2;
|
||||
|
||||
/* The predictor is used as an index into coeff1Table so we'll need to validate to ensure it never overflows. */
|
||||
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= drwav_countof(coeff2Table)) {
|
||||
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table) ||
|
||||
pWav->msadpcm.predictor[1] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= drwav_countof(coeff2Table)) {
|
||||
return totalFramesRead; /* Invalid file. */
|
||||
}
|
||||
}
|
||||
@ -6373,15 +6395,17 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
||||
drwav_int32 newSample0;
|
||||
drwav_int32 newSample1;
|
||||
|
||||
/* The predictor is read from the file and then indexed into a table. Check that it's in bounds. */
|
||||
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table)) {
|
||||
return totalFramesRead;
|
||||
}
|
||||
|
||||
newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
|
||||
newSample0 += nibble0 * pWav->msadpcm.delta[0];
|
||||
newSample0 = drwav_clamp(newSample0, -32768, 32767);
|
||||
|
||||
pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
|
||||
if (pWav->msadpcm.delta[0] < 16) {
|
||||
pWav->msadpcm.delta[0] = 16;
|
||||
}
|
||||
|
||||
pWav->msadpcm.delta[0] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF);
|
||||
|
||||
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
||||
pWav->msadpcm.prevFrames[0][1] = newSample0;
|
||||
|
||||
@ -6390,15 +6414,11 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
||||
newSample1 += nibble1 * pWav->msadpcm.delta[0];
|
||||
newSample1 = drwav_clamp(newSample1, -32768, 32767);
|
||||
|
||||
pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8;
|
||||
if (pWav->msadpcm.delta[0] < 16) {
|
||||
pWav->msadpcm.delta[0] = 16;
|
||||
}
|
||||
pWav->msadpcm.delta[0] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF);
|
||||
|
||||
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
||||
pWav->msadpcm.prevFrames[0][1] = newSample1;
|
||||
|
||||
|
||||
pWav->msadpcm.cachedFrames[2] = newSample0;
|
||||
pWav->msadpcm.cachedFrames[3] = newSample1;
|
||||
pWav->msadpcm.cachedFrameCount = 2;
|
||||
@ -6408,28 +6428,30 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__msadpcm(drwav* pWav, drwav
|
||||
drwav_int32 newSample1;
|
||||
|
||||
/* Left. */
|
||||
if (pWav->msadpcm.predictor[0] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[0] >= drwav_countof(coeff2Table)) {
|
||||
return totalFramesRead; /* Out of bounds. Invalid file. */
|
||||
}
|
||||
|
||||
newSample0 = ((pWav->msadpcm.prevFrames[0][1] * coeff1Table[pWav->msadpcm.predictor[0]]) + (pWav->msadpcm.prevFrames[0][0] * coeff2Table[pWav->msadpcm.predictor[0]])) >> 8;
|
||||
newSample0 += nibble0 * pWav->msadpcm.delta[0];
|
||||
newSample0 = drwav_clamp(newSample0, -32768, 32767);
|
||||
|
||||
pWav->msadpcm.delta[0] = (adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8;
|
||||
if (pWav->msadpcm.delta[0] < 16) {
|
||||
pWav->msadpcm.delta[0] = 16;
|
||||
}
|
||||
pWav->msadpcm.delta[0] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0xF0) >> 4)] * pWav->msadpcm.delta[0]) >> 8, 16, 0x7FFFFFFF);
|
||||
|
||||
pWav->msadpcm.prevFrames[0][0] = pWav->msadpcm.prevFrames[0][1];
|
||||
pWav->msadpcm.prevFrames[0][1] = newSample0;
|
||||
|
||||
|
||||
/* Right. */
|
||||
if (pWav->msadpcm.predictor[1] >= drwav_countof(coeff1Table) || pWav->msadpcm.predictor[1] >= drwav_countof(coeff2Table)) {
|
||||
return totalFramesRead; /* Out of bounds. Invalid file. */
|
||||
}
|
||||
|
||||
newSample1 = ((pWav->msadpcm.prevFrames[1][1] * coeff1Table[pWav->msadpcm.predictor[1]]) + (pWav->msadpcm.prevFrames[1][0] * coeff2Table[pWav->msadpcm.predictor[1]])) >> 8;
|
||||
newSample1 += nibble1 * pWav->msadpcm.delta[1];
|
||||
newSample1 = drwav_clamp(newSample1, -32768, 32767);
|
||||
|
||||
pWav->msadpcm.delta[1] = (adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8;
|
||||
if (pWav->msadpcm.delta[1] < 16) {
|
||||
pWav->msadpcm.delta[1] = 16;
|
||||
}
|
||||
pWav->msadpcm.delta[1] = (drwav_int32)drwav_clamp(((drwav_int64)adaptationTable[((nibbles & 0x0F) >> 0)] * pWav->msadpcm.delta[1]) >> 8, 16, 0x7FFFFFFF);
|
||||
|
||||
pWav->msadpcm.prevFrames[1][0] = pWav->msadpcm.prevFrames[1][1];
|
||||
pWav->msadpcm.prevFrames[1][1] = newSample1;
|
||||
@ -6451,12 +6473,12 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uin
|
||||
drwav_uint64 totalFramesRead = 0;
|
||||
drwav_uint32 iChannel;
|
||||
|
||||
static drwav_int32 indexTable[16] = {
|
||||
static const drwav_int32 indexTable[16] = {
|
||||
-1, -1, -1, -1, 2, 4, 6, 8,
|
||||
-1, -1, -1, -1, 2, 4, 6, 8
|
||||
};
|
||||
|
||||
static drwav_int32 stepTable[89] = {
|
||||
static const drwav_int32 stepTable[89] = {
|
||||
7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
|
||||
19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
|
||||
50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
|
||||
@ -6606,7 +6628,7 @@ DRWAV_PRIVATE drwav_uint64 drwav_read_pcm_frames_s16__ima(drwav* pWav, drwav_uin
|
||||
|
||||
|
||||
#ifndef DR_WAV_NO_CONVERSION_API
|
||||
static unsigned short g_drwavAlawTable[256] = {
|
||||
static const unsigned short g_drwavAlawTable[256] = {
|
||||
0xEA80, 0xEB80, 0xE880, 0xE980, 0xEE80, 0xEF80, 0xEC80, 0xED80, 0xE280, 0xE380, 0xE080, 0xE180, 0xE680, 0xE780, 0xE480, 0xE580,
|
||||
0xF540, 0xF5C0, 0xF440, 0xF4C0, 0xF740, 0xF7C0, 0xF640, 0xF6C0, 0xF140, 0xF1C0, 0xF040, 0xF0C0, 0xF340, 0xF3C0, 0xF240, 0xF2C0,
|
||||
0xAA00, 0xAE00, 0xA200, 0xA600, 0xBA00, 0xBE00, 0xB200, 0xB600, 0x8A00, 0x8E00, 0x8200, 0x8600, 0x9A00, 0x9E00, 0x9200, 0x9600,
|
||||
@ -6625,7 +6647,7 @@ static unsigned short g_drwavAlawTable[256] = {
|
||||
0x02B0, 0x0290, 0x02F0, 0x02D0, 0x0230, 0x0210, 0x0270, 0x0250, 0x03B0, 0x0390, 0x03F0, 0x03D0, 0x0330, 0x0310, 0x0370, 0x0350
|
||||
};
|
||||
|
||||
static unsigned short g_drwavMulawTable[256] = {
|
||||
static const unsigned short g_drwavMulawTable[256] = {
|
||||
0x8284, 0x8684, 0x8A84, 0x8E84, 0x9284, 0x9684, 0x9A84, 0x9E84, 0xA284, 0xA684, 0xAA84, 0xAE84, 0xB284, 0xB684, 0xBA84, 0xBE84,
|
||||
0xC184, 0xC384, 0xC584, 0xC784, 0xC984, 0xCB84, 0xCD84, 0xCF84, 0xD184, 0xD384, 0xD584, 0xD784, 0xD984, 0xDB84, 0xDD84, 0xDF84,
|
||||
0xE104, 0xE204, 0xE304, 0xE404, 0xE504, 0xE604, 0xE704, 0xE804, 0xE904, 0xEA04, 0xEB04, 0xEC04, 0xED04, 0xEE04, 0xEF04, 0xF004,
|
||||
@ -8053,6 +8075,12 @@ DRWAV_PRIVATE drwav_int16* drwav__read_pcm_frames_and_close_s16(drwav* pWav, uns
|
||||
|
||||
DRWAV_ASSERT(pWav != NULL);
|
||||
|
||||
/* Check for overflow before multiplication. */
|
||||
if (pWav->channels == 0 || pWav->totalPCMFrameCount > DRWAV_SIZE_MAX / pWav->channels / sizeof(drwav_int16)) {
|
||||
drwav_uninit(pWav);
|
||||
return NULL; /* Overflow or invalid channels. */
|
||||
}
|
||||
|
||||
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int16);
|
||||
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
||||
drwav_uninit(pWav);
|
||||
@ -8095,6 +8123,12 @@ DRWAV_PRIVATE float* drwav__read_pcm_frames_and_close_f32(drwav* pWav, unsigned
|
||||
|
||||
DRWAV_ASSERT(pWav != NULL);
|
||||
|
||||
/* Check for overflow before multiplication. */
|
||||
if (pWav->channels == 0 || pWav->totalPCMFrameCount > DRWAV_SIZE_MAX / pWav->channels / sizeof(float)) {
|
||||
drwav_uninit(pWav);
|
||||
return NULL; /* Overflow or invalid channels. */
|
||||
}
|
||||
|
||||
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(float);
|
||||
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
||||
drwav_uninit(pWav);
|
||||
@ -8137,6 +8171,12 @@ DRWAV_PRIVATE drwav_int32* drwav__read_pcm_frames_and_close_s32(drwav* pWav, uns
|
||||
|
||||
DRWAV_ASSERT(pWav != NULL);
|
||||
|
||||
/* Check for overflow before multiplication. */
|
||||
if (pWav->channels == 0 || pWav->totalPCMFrameCount > DRWAV_SIZE_MAX / pWav->channels / sizeof(drwav_int32)) {
|
||||
drwav_uninit(pWav);
|
||||
return NULL; /* Overflow or invalid channels. */
|
||||
}
|
||||
|
||||
sampleDataSize = pWav->totalPCMFrameCount * pWav->channels * sizeof(drwav_int32);
|
||||
if (sampleDataSize > DRWAV_SIZE_MAX) {
|
||||
drwav_uninit(pWav);
|
||||
@ -8517,7 +8557,24 @@ DRWAV_API drwav_bool32 drwav_fourcc_equal(const drwav_uint8* a, const char* b)
|
||||
/*
|
||||
REVISION HISTORY
|
||||
================
|
||||
v0.14.0 - TBD
|
||||
v0.14.5 - 2026-03-03
|
||||
- Fix a crash when loading files with a malformed "smpl" chunk.
|
||||
- Fix a signed overflow bug with the MS-ADPCM decoder.
|
||||
|
||||
v0.14.4 - 2026-01-17
|
||||
- Fix some compilation warnings.
|
||||
|
||||
v0.14.3 - 2025-12-14
|
||||
- Fix a possible out-of-bounds read when reading from MS-ADPCM encoded files.
|
||||
- Fix a possible integer overflow error.
|
||||
|
||||
v0.14.2 - 2025-12-02
|
||||
- Fix a compilation warning.
|
||||
|
||||
v0.14.1 - 2025-09-10
|
||||
- Fix an error with the NXDK build.
|
||||
|
||||
v0.14.0 - 2025-07-23
|
||||
- API CHANGE: Seek origin enums have been renamed to the following:
|
||||
- drwav_seek_origin_start -> DRWAV_SEEK_SET
|
||||
- drwav_seek_origin_current -> DRWAV_SEEK_CUR
|
||||
|
||||
53
src/external/m3d.h
vendored
53
src/external/m3d.h
vendored
@ -236,7 +236,8 @@ typedef struct {
|
||||
#ifdef M3D_ASCII
|
||||
#define M3D_PROPERTYDEF(f,i,n) { (f), (i), (char*)(n) }
|
||||
char *key;
|
||||
#else
|
||||
#endif
|
||||
#ifndef M3D_ASCII
|
||||
#define M3D_PROPERTYDEF(f,i,n) { (f), (i) }
|
||||
#endif
|
||||
} m3dpd_t;
|
||||
@ -414,7 +415,8 @@ typedef struct {
|
||||
#ifdef M3D_ASCII
|
||||
#define M3D_CMDDEF(t,n,p,a,b,c,d,e,f,g,h) { (char*)(n), (p), { (a), (b), (c), (d), (e), (f), (g), (h) } }
|
||||
char *key;
|
||||
#else
|
||||
#endif
|
||||
#ifndef M3D_ASCII
|
||||
#define M3D_CMDDEF(t,n,p,a,b,c,d,e,f,g,h) { (p), { (a), (b), (c), (d), (e), (f), (g), (h) } }
|
||||
#endif
|
||||
uint8_t p;
|
||||
@ -674,6 +676,10 @@ static m3dcd_t m3d_commandtypes[] = {
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* we'll need this with M3D_NOTEXTURE */
|
||||
char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header);
|
||||
|
||||
#ifndef M3D_NOTEXTURE
|
||||
#if !defined(M3D_NOIMPORTER) && !defined(STBI_INCLUDE_STB_IMAGE_H)
|
||||
/* PNG decompressor from
|
||||
|
||||
@ -1868,6 +1874,11 @@ static void *_m3dstbi__png_load(_m3dstbi__context *s, int *x, int *y, int *comp,
|
||||
#if !defined(M3D_NOIMPORTER) && defined(STBI_INCLUDE_STB_IMAGE_H) && !defined(STB_IMAGE_IMPLEMENTATION)
|
||||
#error "stb_image.h included without STB_IMAGE_IMPLEMENTATION. Sorry, we need some stuff defined inside the ifguard for proper integration"
|
||||
#endif
|
||||
#else
|
||||
#if !defined(STBI_INCLUDE_STB_IMAGE_H) || defined(STBI_NO_ZLIB)
|
||||
#error "stb_image.h not included or STBI_NO_ZLIB defined. Sorry, we need its zlib implementation for proper integration"
|
||||
#endif
|
||||
#endif /* M3D_NOTEXTURE */
|
||||
|
||||
#if defined(M3D_EXPORTER) && !defined(INCLUDE_STB_IMAGE_WRITE_H)
|
||||
/* zlib_compressor from
|
||||
@ -2168,9 +2179,11 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char
|
||||
unsigned int i, len = 0;
|
||||
unsigned char *buff = NULL;
|
||||
char *fn2;
|
||||
#ifndef M3D_NOTEXTURE
|
||||
unsigned int w, h;
|
||||
stbi__context s;
|
||||
stbi__result_info ri;
|
||||
#endif
|
||||
|
||||
/* failsafe */
|
||||
if(!fn || !*fn) return M3D_UNDEF;
|
||||
@ -2209,13 +2222,17 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char
|
||||
if(!model->texture) {
|
||||
if(buff && freecb) (*freecb)(buff);
|
||||
model->errcode = M3D_ERR_ALLOC;
|
||||
model->numtexture = 0;
|
||||
return M3D_UNDEF;
|
||||
}
|
||||
memset(&model->texture[i], 0, sizeof(m3dtx_t));
|
||||
model->texture[i].name = fn;
|
||||
model->texture[i].w = model->texture[i].h = 0; model->texture[i].d = NULL;
|
||||
if(buff) {
|
||||
if(buff[0] == 0x89 && buff[1] == 'P' && buff[2] == 'N' && buff[3] == 'G') {
|
||||
s.read_from_callbacks = 0;
|
||||
#ifndef M3D_NOTEXTURE
|
||||
/* return pixel buffer of the decoded texture */
|
||||
memset(&s, 0, sizeof(s));
|
||||
memset(&ri, 0, sizeof(ri));
|
||||
s.img_buffer = s.img_buffer_original = (unsigned char *) buff;
|
||||
s.img_buffer_end = s.img_buffer_original_end = (unsigned char *) buff+len;
|
||||
/* don't use model->texture[i].w directly, it's a uint16_t */
|
||||
@ -2225,6 +2242,16 @@ M3D_INDEX _m3d_gettx(m3d_t *model, m3dread_t readfilecb, m3dfree_t freecb, char
|
||||
model->texture[i].w = w;
|
||||
model->texture[i].h = h;
|
||||
model->texture[i].f = (uint8_t)len;
|
||||
#else
|
||||
/* return only the raw undecoded texture */
|
||||
if((model->texture[i].d = (uint8_t*)M3D_MALLOC(len))) {
|
||||
memcpy(model->texture[i].d, buff, len);
|
||||
model->texture[i].w = len & 0xffff;
|
||||
model->texture[i].h = (len >> 16) & 0xffff;
|
||||
model->texture[i].f = 0;
|
||||
} else
|
||||
model->errcode = M3D_ERR_ALLOC;
|
||||
#endif
|
||||
} else {
|
||||
#ifdef M3D_TX_INTERP
|
||||
if((model->errcode = M3D_TX_INTERP(fn, buff, len, &model->texture[i])) != M3D_SUCCESS) {
|
||||
@ -4280,7 +4307,7 @@ m3db_t *m3d_pose(m3d_t *model, M3D_INDEX actionid, uint32_t msec)
|
||||
if(l != msec) {
|
||||
model->vertex = (m3dv_t*)M3D_REALLOC(model->vertex, (model->numvertex + 2 * model->numbone) * sizeof(m3dv_t));
|
||||
if(!model->vertex) {
|
||||
free(ret);
|
||||
M3D_FREE(ret);
|
||||
model->errcode = M3D_ERR_ALLOC;
|
||||
return NULL;
|
||||
}
|
||||
@ -4492,7 +4519,7 @@ void m3d_free(m3d_t *model)
|
||||
if(model->label) M3D_FREE(model->label);
|
||||
if(model->inlined) M3D_FREE(model->inlined);
|
||||
if(model->extra) M3D_FREE(model->extra);
|
||||
free(model);
|
||||
M3D_FREE(model);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -4568,15 +4595,15 @@ static uint32_t _m3d_stridx(m3dstr_t *str, uint32_t numstr, char *s)
|
||||
safe = _m3d_safestr(s, 0);
|
||||
if(!safe) return 0;
|
||||
if(!*safe) {
|
||||
free(safe);
|
||||
M3D_FREE(safe);
|
||||
return 0;
|
||||
}
|
||||
for(i = 0; i < numstr; i++)
|
||||
if(!strcmp(str[i].str, s)) {
|
||||
free(safe);
|
||||
M3D_FREE(safe);
|
||||
return str[i].offs;
|
||||
}
|
||||
free(safe);
|
||||
M3D_FREE(safe);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -4889,7 +4916,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
|
||||
if(cmd->type == m3dc_mesh) {
|
||||
if(numgrp + 2 < maxgrp) {
|
||||
maxgrp += 1024;
|
||||
grpidx = (uint32_t*)realloc(grpidx, maxgrp * sizeof(uint32_t));
|
||||
grpidx = (uint32_t*)M3D_REALLOC(grpidx, maxgrp * sizeof(uint32_t));
|
||||
if(!grpidx) goto memerr;
|
||||
if(!numgrp) {
|
||||
grpidx[0] = 0;
|
||||
@ -5194,7 +5221,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
|
||||
if(sa) M3D_FREE(sa);
|
||||
if(sd) M3D_FREE(sd);
|
||||
if(out) M3D_FREE(out);
|
||||
if(opa) free(opa);
|
||||
if(opa) M3D_FREE(opa);
|
||||
if(h) M3D_FREE(h);
|
||||
M3D_LOG("Out of memory");
|
||||
model->errcode = M3D_ERR_ALLOC;
|
||||
@ -6285,7 +6312,7 @@ memerr: if(vrtxidx) M3D_FREE(vrtxidx);
|
||||
if(skin) M3D_FREE(skin);
|
||||
if(str) M3D_FREE(str);
|
||||
if(vrtx) M3D_FREE(vrtx);
|
||||
if(opa) free(opa);
|
||||
if(opa) M3D_FREE(opa);
|
||||
if(h) M3D_FREE(h);
|
||||
return out;
|
||||
}
|
||||
@ -6310,7 +6337,7 @@ namespace M3D {
|
||||
|
||||
public:
|
||||
Model() {
|
||||
this->model = (m3d_t*)malloc(sizeof(m3d_t)); memset(this->model, 0, sizeof(m3d_t));
|
||||
this->model = (m3d_t*)M3D_MALLOC(sizeof(m3d_t)); memset(this->model, 0, sizeof(m3d_t));
|
||||
}
|
||||
Model(_unused const std::string &data, _unused m3dread_t ReadFileCB,
|
||||
_unused m3dfree_t FreeCB, _unused M3D::Model mtllib) {
|
||||
|
||||
60
src/external/qoa.h
vendored
60
src/external/qoa.h
vendored
@ -31,7 +31,7 @@ struct {
|
||||
struct {
|
||||
char magic[4]; // magic bytes "qoaf"
|
||||
uint32_t samples; // samples per channel in this file
|
||||
} file_header;
|
||||
} file_header;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
@ -39,12 +39,12 @@ struct {
|
||||
uint24_t samplerate; // samplerate in hz
|
||||
uint16_t fsamples; // samples per channel in this frame
|
||||
uint16_t fsize; // frame size (includes this header)
|
||||
} frame_header;
|
||||
} frame_header;
|
||||
|
||||
struct {
|
||||
int16_t history[4]; // most recent last
|
||||
int16_t weights[4]; // most recent last
|
||||
} lms_state[num_channels];
|
||||
} lms_state[num_channels];
|
||||
|
||||
qoa_slice_t slices[256][num_channels];
|
||||
|
||||
@ -66,7 +66,7 @@ frame may contain between 1 .. 256 (inclusive) slices per channel. The last
|
||||
slice (for each channel) in the last frame may contain less than 20 samples; the
|
||||
slice still must be 8 bytes wide, with the unused samples zeroed out.
|
||||
|
||||
Channels are interleaved per slice. E.g. for 2 channel stereo:
|
||||
Channels are interleaved per slice. E.g. for 2 channel stereo:
|
||||
slice[0] = L, slice[1] = R, slice[2] = L, slice[3] = R ...
|
||||
|
||||
A valid QOA file or stream must have at least one frame. Each frame must contain
|
||||
@ -74,7 +74,7 @@ at least one channel and one sample with a samplerate between 1 .. 16777215
|
||||
(inclusive).
|
||||
|
||||
If the total number of samples is not known by the encoder, the samples in the
|
||||
file header may be set to 0x00000000 to indicate that the encoder is
|
||||
file header may be set to 0x00000000 to indicate that the encoder is
|
||||
"streaming". In a streaming context, the samplerate and number of channels may
|
||||
differ from frame to frame. For static files (those with samples set to a
|
||||
non-zero value), each frame must have the same number of channels and same
|
||||
@ -88,15 +88,15 @@ counts 1 .. 8 is:
|
||||
|
||||
1. Mono
|
||||
2. L, R
|
||||
3. L, R, C
|
||||
4. FL, FR, B/SL, B/SR
|
||||
5. FL, FR, C, B/SL, B/SR
|
||||
3. L, R, C
|
||||
4. FL, FR, B/SL, B/SR
|
||||
5. FL, FR, C, B/SL, B/SR
|
||||
6. FL, FR, C, LFE, B/SL, B/SR
|
||||
7. FL, FR, C, LFE, B, SL, SR
|
||||
7. FL, FR, C, LFE, B, SL, SR
|
||||
8. FL, FR, C, LFE, BL, BR, SL, SR
|
||||
|
||||
QOA predicts each audio sample based on the previously decoded ones using a
|
||||
"Sign-Sign Least Mean Squares Filter" (LMS). This prediction plus the
|
||||
"Sign-Sign Least Mean Squares Filter" (LMS). This prediction plus the
|
||||
dequantized residual forms the final output sample.
|
||||
|
||||
*/
|
||||
@ -178,9 +178,9 @@ typedef unsigned long long qoa_uint64_t;
|
||||
|
||||
|
||||
/* The quant_tab provides an index into the dequant_tab for residuals in the
|
||||
range of -8 .. 8. It maps this range to just 3bits and becomes less accurate at
|
||||
the higher end. Note that the residual zero is identical to the lowest positive
|
||||
value. This is mostly fine, since the qoa_div() function always rounds away
|
||||
range of -8 .. 8. It maps this range to just 3bits and becomes less accurate at
|
||||
the higher end. Note that the residual zero is identical to the lowest positive
|
||||
value. This is mostly fine, since the qoa_div() function always rounds away
|
||||
from zero. */
|
||||
|
||||
static const int qoa_quant_tab[17] = {
|
||||
@ -193,8 +193,8 @@ static const int qoa_quant_tab[17] = {
|
||||
/* We have 16 different scalefactors. Like the quantized residuals these become
|
||||
less accurate at the higher end. In theory, the highest scalefactor that we
|
||||
would need to encode the highest 16bit residual is (2**16)/8 = 8192. However we
|
||||
rely on the LMS filter to predict samples accurately enough that a maximum
|
||||
residual of one quarter of the 16 bit range is sufficient. I.e. with the
|
||||
rely on the LMS filter to predict samples accurately enough that a maximum
|
||||
residual of one quarter of the 16 bit range is sufficient. I.e. with the
|
||||
scalefactor 2048 times the quant range of 8 we can encode residuals up to 2**14.
|
||||
|
||||
The scalefactor values are computed as:
|
||||
@ -205,9 +205,9 @@ static const int qoa_scalefactor_tab[16] = {
|
||||
};
|
||||
|
||||
|
||||
/* The reciprocal_tab maps each of the 16 scalefactors to their rounded
|
||||
reciprocals 1/scalefactor. This allows us to calculate the scaled residuals in
|
||||
the encoder with just one multiplication instead of an expensive division. We
|
||||
/* The reciprocal_tab maps each of the 16 scalefactors to their rounded
|
||||
reciprocals 1/scalefactor. This allows us to calculate the scaled residuals in
|
||||
the encoder with just one multiplication instead of an expensive division. We
|
||||
do this in .16 fixed point with integers, instead of floats.
|
||||
|
||||
The reciprocal_tab is computed as:
|
||||
@ -218,11 +218,11 @@ static const int qoa_reciprocal_tab[16] = {
|
||||
};
|
||||
|
||||
|
||||
/* The dequant_tab maps each of the scalefactors and quantized residuals to
|
||||
/* The dequant_tab maps each of the scalefactors and quantized residuals to
|
||||
their unscaled & dequantized version.
|
||||
|
||||
Since qoa_div rounds away from the zero, the smallest entries are mapped to 3/4
|
||||
instead of 1. The dequant_tab assumes the following dequantized values for each
|
||||
instead of 1. The dequant_tab assumes the following dequantized values for each
|
||||
of the quant_tab indices and is computed as:
|
||||
float dqt[8] = {0.75, -0.75, 2.5, -2.5, 4.5, -4.5, 7, -7};
|
||||
dequant_tab[s][q] <- round_ties_away_from_zero(scalefactor_tab[s] * dqt[q])
|
||||
@ -258,7 +258,7 @@ adjusting 4 weights based on the residual of the previous prediction.
|
||||
The next sample is predicted as the sum of (weight[i] * history[i]).
|
||||
|
||||
The adjustment of the weights is done with a "Sign-Sign-LMS" that adds or
|
||||
subtracts the residual to each weight, based on the corresponding sample from
|
||||
subtracts the residual to each weight, based on the corresponding sample from
|
||||
the history. This, surprisingly, is sufficient to get worthwhile predictions.
|
||||
|
||||
This is all done with fixed point integers. Hence the right-shifts when updating
|
||||
@ -285,8 +285,8 @@ static void qoa_lms_update(qoa_lms_t *lms, int sample, int residual) {
|
||||
}
|
||||
|
||||
|
||||
/* qoa_div() implements a rounding division, but avoids rounding to zero for
|
||||
small numbers. E.g. 0.1 will be rounded to 1. Note that 0 itself still
|
||||
/* qoa_div() implements a rounding division, but avoids rounding to zero for
|
||||
small numbers. E.g. 0.1 will be rounded to 1. Note that 0 itself still
|
||||
returns as 0, which is handled in the qoa_quant_tab[].
|
||||
qoa_div() takes an index into the .16 fixed point qoa_reciprocal_tab as an
|
||||
argument, so it can do the division with a cheaper integer multiplication. */
|
||||
@ -385,10 +385,10 @@ unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned
|
||||
for (unsigned int c = 0; c < channels; c++) {
|
||||
int slice_len = qoa_clamp(QOA_SLICE_LEN, 0, frame_len - sample_index);
|
||||
int slice_start = sample_index * channels + c;
|
||||
int slice_end = (sample_index + slice_len) * channels + c;
|
||||
int slice_end = (sample_index + slice_len) * channels + c;
|
||||
|
||||
/* Brute for search for the best scalefactor. Just go through all
|
||||
16 scalefactors, encode all samples for the current slice and
|
||||
/* Brute force search for the best scalefactor. Just go through all
|
||||
16 scalefactors, encode all samples for the current slice and
|
||||
meassure the total squared error. */
|
||||
qoa_uint64_t best_rank = -1;
|
||||
#ifdef QOA_RECORD_TOTAL_ERROR
|
||||
@ -402,7 +402,7 @@ unsigned int qoa_encode_frame(const short *sample_data, qoa_desc *qoa, unsigned
|
||||
/* There is a strong correlation between the scalefactors of
|
||||
neighboring slices. As an optimization, start testing
|
||||
the best scalefactor of the previous slice first. */
|
||||
int scalefactor = (sfi + prev_scalefactor[c]) % 16;
|
||||
int scalefactor = (sfi + prev_scalefactor[c]) & (16 - 1);
|
||||
|
||||
/* We have to reset the LMS state to the last known good one
|
||||
before trying each scalefactor, as each pass updates the LMS
|
||||
@ -500,7 +500,7 @@ void *qoa_encode(const short *sample_data, qoa_desc *qoa, unsigned int *out_len)
|
||||
num_frames * QOA_LMS_LEN * 4 * qoa->channels + /* 4 * 4 bytes lms state per channel */
|
||||
num_slices * 8 * qoa->channels; /* 8 byte slices */
|
||||
|
||||
unsigned char *bytes = (unsigned char *)QOA_MALLOC(encoded_size);
|
||||
unsigned char *bytes = QOA_MALLOC(encoded_size);
|
||||
|
||||
for (unsigned int c = 0; c < qoa->channels; c++) {
|
||||
/* Set the initial LMS weights to {0, 0, -1, 2}. This helps with the
|
||||
@ -657,7 +657,7 @@ short *qoa_decode(const unsigned char *bytes, int size, qoa_desc *qoa) {
|
||||
|
||||
/* Calculate the required size of the sample buffer and allocate */
|
||||
int total_samples = qoa->samples * qoa->channels;
|
||||
short *sample_data = (short *)QOA_MALLOC(total_samples * sizeof(short));
|
||||
short *sample_data = QOA_MALLOC(total_samples * sizeof(short));
|
||||
|
||||
unsigned int sample_index = 0;
|
||||
unsigned int frame_len;
|
||||
@ -733,7 +733,7 @@ void *qoa_read(const char *filename, qoa_desc *qoa) {
|
||||
bytes_read = fread(data, 1, size, f);
|
||||
fclose(f);
|
||||
|
||||
sample_data = qoa_decode((const unsigned char *)data, bytes_read, qoa);
|
||||
sample_data = qoa_decode(data, bytes_read, qoa);
|
||||
QOA_FREE(data);
|
||||
return sample_data;
|
||||
}
|
||||
|
||||
4
src/external/qoi.h
vendored
4
src/external/qoi.h
vendored
@ -427,7 +427,7 @@ void *qoi_encode(const void *data, const qoi_desc *desc, int *out_len) {
|
||||
run = 0;
|
||||
}
|
||||
|
||||
index_pos = QOI_COLOR_HASH(px) % 64;
|
||||
index_pos = QOI_COLOR_HASH(px) & (64 - 1);
|
||||
|
||||
if (index[index_pos].v == px.v) {
|
||||
bytes[p++] = QOI_OP_INDEX | index_pos;
|
||||
@ -574,7 +574,7 @@ void *qoi_decode(const void *data, int size, qoi_desc *desc, int channels) {
|
||||
run = (b1 & 0x3f);
|
||||
}
|
||||
|
||||
index[QOI_COLOR_HASH(px) % 64] = px;
|
||||
index[QOI_COLOR_HASH(px) & (64 - 1)] = px;
|
||||
}
|
||||
|
||||
pixels[px_pos + 0] = px.rgba.r;
|
||||
|
||||
662
src/external/stb_image_resize2.h
vendored
662
src/external/stb_image_resize2.h
vendored
File diff suppressed because it is too large
Load Diff
@ -10,6 +10,7 @@
|
||||
* #define SUPPORT_FILEFORMAT_MTL
|
||||
* #define SUPPORT_FILEFORMAT_IQM
|
||||
* #define SUPPORT_FILEFORMAT_GLTF
|
||||
* #define SUPPORT_FILEFORMAT_GLTF_WRITE
|
||||
* #define SUPPORT_FILEFORMAT_VOX
|
||||
* #define SUPPORT_FILEFORMAT_M3D
|
||||
* Selected desired fileformats to be supported for model data loading
|
||||
@ -71,6 +72,11 @@
|
||||
#define CGLTF_IMPLEMENTATION
|
||||
#include "external/cgltf.h" // glTF file format loading
|
||||
#endif
|
||||
#if SUPPORT_FILEFORMAT_GLTF_WRITE
|
||||
// NOTE: No need for custom allocators, memory buffer provided
|
||||
#define CGLTF_WRITE_IMPLEMENTATION
|
||||
#include "external/cgltf_write.h" // glTF file format writing
|
||||
#endif
|
||||
|
||||
#if SUPPORT_FILEFORMAT_VOX
|
||||
#define VOX_MALLOC RL_MALLOC
|
||||
@ -2017,6 +2023,19 @@ bool ExportMesh(Mesh mesh, const char *fileName)
|
||||
|
||||
RL_FREE(txtData);
|
||||
}
|
||||
else if (IsFileExtension(fileName, ".gltf")) // Or .glb
|
||||
{
|
||||
// TODO: Implement gltf/glb support
|
||||
/*
|
||||
cgltf_size expected = cgltf_write(options, NULL, 0, data);
|
||||
char *buffer = (char *)RL_CALLOC(expected, 0);
|
||||
cgltf_size actual = cgltf_write(options, buffer, expected, data);
|
||||
|
||||
// NOTE: cgltf_write() includes a NULL terminator that should be ommited in case of a .glb
|
||||
if (options->type == cgltf_file_type_glb) cgltf_write_glb(file, buffer, actual - 1, data->bin, data->bin_size);
|
||||
else SaveFileText(fileName, buffer); // Write a plain JSON file
|
||||
*/
|
||||
}
|
||||
else if (IsFileExtension(fileName, ".raw"))
|
||||
{
|
||||
// TODO: Support additional file formats to export mesh vertex data
|
||||
@ -5265,7 +5284,7 @@ static cgltf_result LoadFileGLTFCallback(const struct cgltf_memory_options *memo
|
||||
}
|
||||
|
||||
// Release file data callback for cgltf
|
||||
static void ReleaseFileGLTFCallback(const struct cgltf_memory_options *memoryOptions, const struct cgltf_file_options *fileOptions, void *data)
|
||||
static void ReleaseFileGLTFCallback(const struct cgltf_memory_options *memoryOptions, const struct cgltf_file_options *fileOptions, void *data, cgltf_size size)
|
||||
{
|
||||
UnloadFileData((unsigned char *)data);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user