2021-09-11 23:18:12 -04:00
|
|
|
#include <unordered_map>
|
|
|
|
#include <string>
|
|
|
|
#include <functional>
|
|
|
|
|
|
|
|
#include <AL/al.h>
|
|
|
|
|
2022-09-25 15:47:36 -04:00
|
|
|
#include <LIEF/ELF.hpp>
|
|
|
|
|
2021-09-11 23:18:12 -04:00
|
|
|
#include <libreborn/libreborn.h>
|
|
|
|
|
|
|
|
#include "file.h"
|
|
|
|
#include "engine.h"
|
|
|
|
|
|
|
|
// Load Symbol From ELF File
|
2023-05-28 00:45:58 -04:00
|
|
|
static void load_symbol(const char *source, const char *name, std::function<void(const unsigned char *, uint32_t)> callback) {
|
2024-01-30 19:44:07 -05:00
|
|
|
static std::unordered_map<std::string, std::unique_ptr<LIEF::ELF::Binary>> sources = {};
|
|
|
|
auto pos = sources.find(std::string(source));
|
|
|
|
if (pos == sources.end()) {
|
|
|
|
sources[std::string(source)] = LIEF::ELF::Parser::parse(source);
|
2021-09-11 23:18:12 -04:00
|
|
|
}
|
2024-01-30 19:44:07 -05:00
|
|
|
std::unique_ptr<LIEF::ELF::Binary> &binary = sources[std::string(source)];
|
2022-09-25 15:47:36 -04:00
|
|
|
const LIEF::ELF::Symbol *symbol = binary->get_dynamic_symbol(name);
|
|
|
|
if (symbol != NULL) {
|
2023-05-28 00:45:58 -04:00
|
|
|
LIEF::span<const uint8_t> data = binary->get_content_from_virtual_address(symbol->value(), symbol->size(), LIEF::Binary::VA_TYPES::VA);
|
2022-09-25 15:47:36 -04:00
|
|
|
callback(data.data(), data.size());
|
|
|
|
} else {
|
|
|
|
WARN("Unable To Find Symbol: %s", name);
|
2021-09-11 23:18:12 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
2023-05-28 00:45:58 -04:00
|
|
|
load_symbol(source, name, [name, &buffer](const unsigned char *symbol, uint32_t size) {
|
2021-09-11 23:18:12 -04:00
|
|
|
// 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;
|
|
|
|
}
|
2023-05-28 00:45:58 -04:00
|
|
|
const unsigned char *data = symbol + sizeof (audio_metadata);
|
2021-09-11 23:18:12 -04:00
|
|
|
|
|
|
|
// 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
|
2022-05-29 18:44:27 -04:00
|
|
|
static std::unordered_map<std::string, ALuint> buffers;
|
2021-09-11 23:18:12 -04:00
|
|
|
|
|
|
|
// Get Buffer For Sound
|
|
|
|
ALuint _media_audio_get_buffer(const char *source, const char *name) {
|
|
|
|
// Check
|
|
|
|
if (_media_audio_is_loaded()) {
|
2022-05-29 18:44:27 -04:00
|
|
|
if (buffers.count(name) > 0) {
|
2021-09-11 23:18:12 -04:00
|
|
|
// Return
|
2022-05-29 18:44:27 -04:00
|
|
|
return buffers[name];
|
2021-09-11 23:18:12 -04:00
|
|
|
} else {
|
|
|
|
// Load And Return
|
2022-05-29 18:44:27 -04:00
|
|
|
buffers[name] = load_sound(source, name);
|
2021-09-11 23:18:12 -04:00
|
|
|
return _media_audio_get_buffer(source, name);
|
|
|
|
}
|
|
|
|
} else {
|
2022-04-14 21:12:42 -04:00
|
|
|
ERR("Audio Engine Isn't Loaded");
|
2021-09-11 23:18:12 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete Buffers
|
|
|
|
void _media_audio_delete_buffers() {
|
|
|
|
if (_media_audio_is_loaded()) {
|
2022-07-13 23:35:05 -04:00
|
|
|
for (auto &it : buffers) {
|
2021-09-11 23:18:12 -04:00
|
|
|
if (it.second && alIsBuffer(it.second)) {
|
|
|
|
alDeleteBuffers(1, &it.second);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-05-29 18:44:27 -04:00
|
|
|
buffers.clear();
|
2021-09-11 23:18:12 -04:00
|
|
|
}
|