Audio res documentation, API cleanup, bug fixes

This commit is contained in:
PJB3005
2026-08-30 20:50:59 +02:00
parent bd7e5cb77d
commit cd1d12eec6
14 changed files with 410 additions and 37 deletions
@@ -16,11 +16,14 @@ using namespace dusk::helpers::cast;
constexpr AudioResService s_audioResService{
.header = SERVICE_HEADER(AudioResService, AUDIO_RES_SERVICE_MAJOR, AUDIO_RES_SERVICE_MINOR),
.default_wave_info = &wsys::default_wave_info,
.replace_wave = &wsys::insert_replace_wave,
.add_wave = &wsys::insert_add_wave,
.remove_wave = &wsys::remove_wave,
.default_effect_info = &bst::default_effect_info,
.replace_sound_table_effect = &bst::replace_sound_table_effect,
.add_sound_table_effect = &bst::add_sound_table_effect,
.default_stream_info = &bst::default_stream_info,
.replace_sound_table_stream = &bst::replace_sound_table_stream,
.add_sound_table_stream = &bst::add_sound_table_stream,
.remove_sound_table = &bst::remove_sound_table,
+30 -8
View File
@@ -35,6 +35,7 @@ bool validate_category(SoundEffectCategory const category) {
}
uint8_t volume_to_item(float volume) {
volume = std::clamp(volume, 0.0f, 2.0f);
return static_cast<uint8_t>(volume * 127);
}
@@ -90,8 +91,8 @@ u8 SoundEffectReplacementSlot::get_type_id() const {
}
StreamReplacementSlot::StreamReplacementSlot(
bool mod_defined, u16 id, const AudioSoundTableStreamInfo& info)
: SoundTableReplacementSlot(mod_defined, id), file_path(info.file_path) {
bool mod_defined, u16 id, char const* file_path, const AudioSoundTableStreamInfo& info)
: SoundTableReplacementSlot(mod_defined, id), file_path(file_path) {
stop_on_scene_change = info.stop_on_scene_change;
item.mPriority = info.priority;
item.mVolume = volume_to_item(info.volume);
@@ -216,10 +217,14 @@ static ModResult insert_sound_table_effect_core(ModContext* ctx, SoundEffectCate
}
auto mod = mod_from_context(ctx);
if (mod == nullptr || info == nullptr || !validate_category(category_id)) {
if (mod == nullptr || !validate_category(category_id)) {
return MOD_INVALID_ARGUMENT;
}
if (info == nullptr) {
info = &default_effect_info;
}
auto slot = std::make_shared<SoundEffectReplacementSlot>(mod_defined, effect_id, category_id, *info);
sound_replacements_dirty = true;
@@ -236,6 +241,8 @@ ModResult replace_sound_table_effect(ModContext* ctx, SoundEffectCategory catego
return insert_sound_table_effect_core(ctx, category_id, effect_id, false, info, out_handle);
}
AudioSoundTableEffectInfo const default_effect_info(128, 1, 1);
ModResult add_sound_table_effect(ModContext* ctx, SoundEffectCategory category_id,
AudioSoundTableEffectInfo const* info, AudioSoundTableHandle* out_handle,
uint16_t* out_effect_id) {
@@ -263,6 +270,7 @@ static ModResult insert_sound_table_stream_core(
ModContext* ctx,
uint16_t stream_id,
bool mod_defined,
char const* file_path,
AudioSoundTableStreamInfo const* info,
AudioSoundTableHandle* out_handle) {
if (out_handle != nullptr) {
@@ -270,11 +278,15 @@ static ModResult insert_sound_table_stream_core(
}
auto mod = mod_from_context(ctx);
if (mod == nullptr || info == nullptr) {
if (mod == nullptr || file_path == nullptr) {
return MOD_INVALID_ARGUMENT;
}
auto slot = std::make_shared<StreamReplacementSlot>(mod_defined, stream_id, *info);
if (info == nullptr) {
info = &default_stream_info;
}
auto slot = std::make_shared<StreamReplacementSlot>(mod_defined, stream_id, file_path, *info);
sound_replacements_dirty = true;
auto const handle = sound_replacements.emplace(*mod, std::move(slot));
@@ -285,12 +297,22 @@ static ModResult insert_sound_table_stream_core(
return MOD_OK;
}
AudioSoundTableStreamInfo const default_stream_info(
128,
1,
{
STREAM_PAN_LEFT,
STREAM_PAN_RIGHT
});
ModResult replace_sound_table_stream(ModContext* ctx, uint16_t stream_id,
char const* file_path,
AudioSoundTableStreamInfo const* info, AudioSoundTableHandle* out_handle) {
return insert_sound_table_stream_core(ctx, stream_id, false, info, out_handle);
return insert_sound_table_stream_core(ctx, stream_id, false, file_path, info, out_handle);
}
ModResult add_sound_table_stream(ModContext* ctx, AudioSoundTableStreamInfo const* info,
ModResult add_sound_table_stream(ModContext* ctx,
char const* file_path, AudioSoundTableStreamInfo const* info,
AudioSoundTableHandle* out_handle, uint16_t* out_stream_id) {
if (out_stream_id == nullptr) {
return MOD_INVALID_ARGUMENT;
@@ -298,7 +320,7 @@ ModResult add_sound_table_stream(ModContext* ctx, AudioSoundTableStreamInfo cons
auto const stream_id = stream_id_allocator.alloc();
auto const result = insert_sound_table_stream_core(ctx, stream_id, true, info, out_handle);
auto const result = insert_sound_table_stream_core(ctx, stream_id, true, file_path, info, out_handle);
if (result != MOD_OK) {
stream_id_allocator.free(stream_id);
}
+7 -1
View File
@@ -39,7 +39,7 @@ struct StreamReplacementSlot final : SoundTableReplacementSlot {
std::string file_path;
bool stop_on_scene_change;
StreamReplacementSlot(bool mod_defined, u16 id, const AudioSoundTableStreamInfo& info);
StreamReplacementSlot(bool mod_defined, u16 id, char const* file_path, const AudioSoundTableStreamInfo& info);
~StreamReplacementSlot() override = default;
@@ -68,6 +68,8 @@ void frame_end();
void remove_mod(LoadedMod const& mod);
void sync_audio_replacements();
extern AudioSoundTableEffectInfo const default_effect_info;
ModResult replace_sound_table_effect(
ModContext* ctx,
SoundEffectCategory category_id,
@@ -82,14 +84,18 @@ ModResult add_sound_table_effect(
AudioSoundTableHandle* out_handle,
uint16_t* out_effect_id);
extern AudioSoundTableStreamInfo const default_stream_info;
ModResult replace_sound_table_stream(
ModContext* ctx,
uint16_t stream_id,
char const* file_path,
AudioSoundTableStreamInfo const* info,
AudioSoundTableHandle* out_handle);
ModResult add_sound_table_stream(
ModContext* ctx,
char const* file_path,
AudioSoundTableStreamInfo const* info,
AudioSoundTableHandle* out_handle,
uint16_t* out_stream_id);
+1 -1
View File
@@ -84,7 +84,7 @@ ModResult load_opus(LoadedMod const& mod, RuntimeWaveReplacementSlot& slot, std:
slot.data = std::make_shared<SampleDataPcm16>(std::move(pcm_buffer));
slot.sample_rate = 48000; // Opus always decodes at 48 kHz.
slot.sample_count = length;
slot.format = Pcm16;
slot.format = AUDIO_WAVE_FORMAT_PCM16;
return MOD_OK;
}
+1 -1
View File
@@ -135,7 +135,7 @@ ModResult load_wav(LoadedMod const& mod, RuntimeWaveReplacementSlot& slot, std::
pcmData.be_swap();
slot.format = Pcm16;
slot.format = AUDIO_WAVE_FORMAT_PCM16;
slot.sample_count = pcmData.size() / sizeof(u16);
slot.data = std::make_unique<SampleDataPcm16>(std::move(pcmData));
+16 -5
View File
@@ -29,18 +29,18 @@ 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;
return bank == AUDIO_WAVE_BANK_SOUND_EFFECTS ? 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;
u32 bytes_per_block;
switch (raw.format) {
case Adpcm4:
case AUDIO_WAVE_FORMAT_ADPCM4:
samples_per_block = 16;
bytes_per_block = 9;
break;
case Pcm16:
case AUDIO_WAVE_FORMAT_PCM16:
samples_per_block = 1;
bytes_per_block = 2;
break;
@@ -71,7 +71,7 @@ ModResult load_raw(
return MOD_INVALID_ARGUMENT;
}
if (slot.format == Pcm16) {
if (slot.format == AUDIO_WAVE_FORMAT_PCM16) {
SampleDataPcm16 pcm16;
pcm16.data.resize(sample_count);
memcpy(pcm16.data.data(), file_contents.data(), file_contents.size());
@@ -179,6 +179,15 @@ ModResult insert_replace_wave_core(
slot.loop = wave_info->loop;
slot.loop_start_sample = wave_info->loop_start_sample;
slot.loop_end_sample = wave_info->loop_end_sample;
if (slot.loop_end_sample > slot.sample_count) {
slot.loop_end_sample = slot.sample_count;
}
if (slot.loop_start_sample >= slot.loop_end_sample) {
Log.error("[{}] wave has start >= end", mod->metadata.id);
return MOD_INVALID_ARGUMENT;
}
} else {
slot.base_key = AUDIO_RES_DEFAULT_KEY;
slot.loop = false;
@@ -202,6 +211,8 @@ ModResult insert_replace_wave_core(
absl::flat_hash_map<AudioWaveKey, AudioWaveReplacementValue> s_replacements;
std::mutex s_replacements_mutex;
AudioWaveInfo const default_wave_info(AUDIO_RES_DEFAULT_KEY, false, 0, std::numeric_limits<u32>::max(), nullptr);
ModResult remove_wave(ModContext* ctx, AudioWaveHandle handle) {
auto* mod = mod_from_context(ctx);
if (mod == nullptr || handle == 0) {
@@ -239,7 +250,7 @@ ModResult insert_add_wave(
*out_wave_id = 0;
if (bank != SoundEffects && bank != MusicSamples) {
if (bank != AUDIO_WAVE_BANK_SOUND_EFFECTS && bank != AUDIO_WAVE_BANK_MUSIC_SAMPLES) {
return MOD_INVALID_ARGUMENT;
}
+2
View File
@@ -108,6 +108,8 @@ void frame_end();
void remove_mod(LoadedMod& mod);
void sync_audio_replacements();
extern AudioWaveInfo const default_wave_info;
ModResult insert_replace_wave(
ModContext* ctx,
AudioWaveBank bank,