#include #include #include #include #include #include #include "file.h" #include "engine.h" // Load Symbol From ELF File static void load_symbol(const char *source, const char *name, std::function callback) { static std::unique_ptr binary = NULL; if (binary == NULL) { binary = LIEF::ELF::Parser::parse(source); } const LIEF::ELF::Symbol *symbol = binary->get_dynamic_symbol(name); if (symbol != NULL) { std::vector data = binary->get_content_from_virtual_address(symbol->value(), symbol->size(), LIEF::Binary::VA_TYPES::VA); callback(data.data(), data.size()); } else { WARN("Unable To Find Symbol: %s", name); } } // Audio Metadata struct audio_metadata { int32_t channels; int32_t frame_size; int32_t sample_rate; int32_t frames; }; // Load Sound Symbol Into ALunit static ALuint load_sound(const char *source, const char *name) { // Check OpenAL if (!_media_audio_is_loaded()) { return 0; } // Store Result ALuint buffer = 0; // Load Symbol load_symbol(source, name, [name, &buffer](unsigned char *symbol, uint32_t size) { // Load Metadata if (size < sizeof (audio_metadata)) { WARN("Symbol Too Small To Contain Audio Metadata: %s", name); return; } audio_metadata *meta = (audio_metadata *) symbol; // Check Frame Size if (meta->frame_size != 1 && meta->frame_size != 2) { WARN("Unsupported Frame Size: %s: %i", name, meta->frame_size); return; } // Get Audio Format ALenum format = AL_NONE; if (meta->channels == 1) { format = meta->frame_size == 2 ? AL_FORMAT_MONO16 : AL_FORMAT_MONO8; } else if (meta->channels == 2) { format = meta->frame_size == 2 ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO8; } else { WARN("Unsupported Channel Count: %s: %i", name, meta->channels); return; } // Load Data int remaining_size = size - sizeof (audio_metadata); int data_size = meta->channels * meta->frames * meta->frame_size; if (remaining_size < data_size) { WARN("Symbol Too Small To Contain Specified Audio Data: %s", name); return; } unsigned char *data = symbol + sizeof (audio_metadata); // Create Buffer alGenBuffers(1, &buffer); alBufferData(buffer, format, data, data_size, meta->sample_rate); // Check OpenAL Error ALenum err = alGetError(); if (err != AL_NO_ERROR) { WARN("Unable To Store Audio Buffer: %s", alGetString(err)); if (buffer && alIsBuffer(buffer)) { alDeleteBuffers(1, &buffer); } buffer = 0; } }); // Return return buffer; } // Store Buffers static std::unordered_map buffers; // Get Buffer For Sound ALuint _media_audio_get_buffer(const char *source, const char *name) { // Check if (_media_audio_is_loaded()) { if (buffers.count(name) > 0) { // Return return buffers[name]; } else { // Load And Return buffers[name] = load_sound(source, name); return _media_audio_get_buffer(source, name); } } else { ERR("Audio Engine Isn't Loaded"); } } // Delete Buffers void _media_audio_delete_buffers() { if (_media_audio_is_loaded()) { for (auto &it : buffers) { if (it.second && alIsBuffer(it.second)) { alDeleteBuffers(1, &it.second); } } } buffers.clear(); }