Allow allocating new audio waves

...probably. I have no means to test this code atm.
This commit is contained in:
PJB3005
2026-08-06 01:55:16 +02:00
parent 756f8d5fb9
commit 2fca463139
7 changed files with 151 additions and 21 deletions
+2
View File
@@ -1498,6 +1498,8 @@ set(DUSK_FILES
src/dusk/mods/svc/gfx.cpp
src/dusk/mods/svc/hook.cpp
src/dusk/mods/svc/host.cpp
src/dusk/mods/svc/id_allocator.cpp
src/dusk/mods/svc/id_allocator.hpp
src/dusk/mods/svc/log.cpp
src/dusk/mods/svc/overlay.cpp
src/dusk/mods/svc/registry.cpp
+8
View File
@@ -52,6 +52,14 @@ typedef struct AudioResService {
AudioWaveInfo const* wave_info,
AudioWaveHandle* out_handle);
ModResult (*add_wave)(
ModContext* ctx,
AudioWaveBank bank,
char const* file_name,
AudioWaveInfo const* wave_info,
AudioWaveHandle* out_handle,
uint16_t* out_wave_id);
ModResult (*remove_wave)(ModContext* ctx, AudioWaveHandle handle);
} AudioResService;
@@ -16,6 +16,7 @@ using namespace dusk::helpers::cast;
constexpr AudioResService s_audioResService{
.header = SERVICE_HEADER(AudioResService, AUDIO_RES_SERVICE_MAJOR, AUDIO_RES_SERVICE_MINOR),
.replace_wave = &wsys::insert_replace_wave,
.add_wave = &wsys::insert_add_wave,
.remove_wave = &wsys::remove_wave,
};
+79 -21
View File
@@ -1,10 +1,9 @@
#include "wsys.hpp"
#include "../registry.hpp"
#include "../slot_map.hpp"
#include "../id_allocator.hpp"
#include "aurora/lib/logging.hpp"
#include "dusk/audio/DuskAudioSystem.h"
#include "dusk/mods/loader/loader.hpp"
#include "helpers/alignment.hpp"
#include "helpers/cast.hpp"
namespace dusk::mods::svc::audio_res::wsys {
@@ -26,6 +25,12 @@ constexpr ContainerLoadFunction s_containerLoadFunctions[] = {
#endif
};
PlainIdAllocator<u16> sound_effect_id_allocator(5'000);
PlainIdAllocator<u16> music_sample_id_allocator(1'000);
PlainIdAllocator<u16>& id_allocator_for_bank(AudioWaveBank const bank) {
return bank == SoundEffects ? sound_effect_id_allocator : music_sample_id_allocator;
}
bool validate_raw_size(LoadedMod const& mod, std::string const& path, uintptr_t actual_size, AudioRawWave const& raw, u32& sample_count) {
u32 samples_per_block;
@@ -122,32 +127,25 @@ JASWaveInfo wave_info_from_slot(RuntimeWaveReplacementSlot const& slot) {
}
bool wave_remove(LoadedMod const& mod, AudioWaveHandle const handle) {
auto const result = s_waveReplacements.erase_owned(handle, mod);
wave_replacements_dirty |= result;
return result;
}
}
absl::flat_hash_map<AudioWaveKey, AudioWaveReplacementValue> s_replacements;
std::mutex s_replacements_mutex;
ModResult remove_wave(ModContext* ctx, AudioWaveHandle handle) {
auto* mod = mod_from_context(ctx);
if (mod == nullptr || handle == 0) {
return MOD_INVALID_ARGUMENT;
auto const found = s_waveReplacements.find_owned(handle, mod);
if (found == nullptr) {
return false;
}
if (!wave_remove(*mod, handle)) {
Log.error("[{}] remove wave failed: unknown handle {}", mod->metadata.id, handle);
return MOD_INVALID_ARGUMENT;
if (found->value.mod_defined) {
auto& allocator = id_allocator_for_bank(found->value.bank);
allocator.free(found->value.wave_id);
}
return MOD_OK;
s_waveReplacements.erase_owned(handle, mod);
return true;
}
ModResult insert_replace_wave(
ModResult insert_replace_wave_core(
ModContext* ctx,
AudioWaveBank bank,
u16 wave_id,
bool mod_defined,
char const* file_name,
AudioWaveInfo const* wave_info,
AudioWaveHandle* out_handle) {
@@ -164,6 +162,7 @@ ModResult insert_replace_wave(
slot.bundle_path = file_name;
slot.bank = bank;
slot.wave_id = wave_id;
slot.mod_defined = mod_defined;
ModResult result;
if (wave_info && wave_info->raw_wave) {
@@ -197,6 +196,65 @@ ModResult insert_replace_wave(
return MOD_OK;
}
}
absl::flat_hash_map<AudioWaveKey, AudioWaveReplacementValue> s_replacements;
std::mutex s_replacements_mutex;
ModResult remove_wave(ModContext* ctx, AudioWaveHandle handle) {
auto* mod = mod_from_context(ctx);
if (mod == nullptr || handle == 0) {
return MOD_INVALID_ARGUMENT;
}
if (!wave_remove(*mod, handle)) {
Log.error("[{}] remove wave failed: unknown handle {}", mod->metadata.id, handle);
return MOD_INVALID_ARGUMENT;
}
return MOD_OK;
}
ModResult insert_replace_wave(
ModContext* ctx,
AudioWaveBank bank,
u16 wave_id,
char const* file_name,
AudioWaveInfo const* wave_info,
AudioWaveHandle* out_handle) {
return insert_replace_wave_core(ctx, bank, wave_id, false, file_name, wave_info, out_handle);
}
ModResult insert_add_wave(
ModContext* ctx,
AudioWaveBank bank,
char const* file_name,
AudioWaveInfo const* wave_info,
AudioWaveHandle* out_handle,
u16* out_wave_id) {
if (out_wave_id == nullptr) {
return MOD_INVALID_ARGUMENT;
}
*out_wave_id = 0;
if (bank != SoundEffects && bank != MusicSamples) {
return MOD_INVALID_ARGUMENT;
}
auto& allocator = id_allocator_for_bank(bank);
auto const new_wave_id = allocator.alloc();
auto const result = insert_replace_wave_core(ctx, bank, new_wave_id, true, file_name, wave_info, out_handle);
if (result != MOD_OK) {
allocator.free(new_wave_id);
}
*out_wave_id = new_wave_id;
return result;
}
void remove_mod(LoadedMod& mod) {
s_waveReplacements.erase_all(mod);
+9
View File
@@ -82,6 +82,7 @@ extern std::mutex s_replacements_mutex;
struct RuntimeWaveReplacementSlot {
std::string bundle_path;
AudioWaveBank bank;
bool mod_defined;
u16 wave_id;
u8 base_key;
@@ -115,6 +116,14 @@ ModResult insert_replace_wave(
AudioWaveInfo const* wave_info,
AudioWaveHandle* out_handle);
ModResult insert_add_wave(
ModContext* ctx,
AudioWaveBank bank,
char const* file_name,
AudioWaveInfo const* wave_info,
AudioWaveHandle* out_handle,
u16* out_wave_id);
ModResult remove_wave(ModContext* ctx, AudioWaveHandle handle);
}
+9
View File
@@ -0,0 +1,9 @@
#include "id_allocator.hpp"
namespace dusk::mods::svc {
void id_allocator_exhausted() {
CRASH("ID allocator exhausted!");
}
} // namespace dusk::mods::svc
+43
View File
@@ -0,0 +1,43 @@
#pragma once
#include <vector>
#include <limits>
namespace dusk::mods::svc {
[[noreturn]] void id_allocator_exhausted();
template<typename T> requires std::is_integral_v<T>
class PlainIdAllocator {
std::vector<T> reusable;
T alloc_next;
T alloc_max;
public:
explicit PlainIdAllocator(T first, T max=std::numeric_limits<T>::max())
: alloc_next(first), alloc_max(max) {
}
T alloc() {
if (reusable.empty()) {
if (alloc_next == alloc_max) {
id_allocator_exhausted();
}
return alloc_next++;
}
auto val = reusable.back();
reusable.pop_back();
return val;
}
void free(T value) {
assert(value < alloc_max && value < alloc_next);
reusable.push_back(value);
}
};
}