mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-08-08 10:03:06 -04:00
Allow allocating new audio waves
...probably. I have no means to test this code atm.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "id_allocator.hpp"
|
||||
|
||||
namespace dusk::mods::svc {
|
||||
|
||||
void id_allocator_exhausted() {
|
||||
CRASH("ID allocator exhausted!");
|
||||
}
|
||||
|
||||
} // namespace dusk::mods::svc
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user