reverb proof of concept

This commit is contained in:
madeline
2026-04-04 01:38:28 -07:00
parent c869320471
commit f5ce58ca7f
15 changed files with 668 additions and 19 deletions
+40 -14
View File
@@ -19,6 +19,7 @@ ChannelAuxData dusk::audio::ChannelAux[DSP_CHANNELS] = {};
f32 dusk::audio::MasterVolume = 1.0f;
f32 dusk::audio::PrevMasterVolume = 1.0f;
bool dusk::audio::EnableReverb = true;
/**
* Validate that a DSP channel's format is actually something we know how to play.
@@ -112,32 +113,47 @@ void dusk::audio::DspRender(OutputSubframe& subframe) {
auto& channel = channels[i];
auto& channelAux = ChannelAux[i];
if (!channel.mIsActive) {
continue;
}
bool skipRender = false;
if (channel.mPauseFlag) {
if (!channel.mIsActive) {
skipRender = true;
}
else if (channel.mPauseFlag) {
// Not really sure what the practical difference between pause and
// deactivation is. Either avoids clearing state or allows the DSP to avoid popping?
continue;
skipRender = true;
}
if (channel.mForcedStop) {
else if (channel.mForcedStop) {
channel.mIsFinished = true;
continue;
skipRender = true;
}
if (channel.mWaveAramAddress == 0) {
else if (channel.mWaveAramAddress == 0) {
// I think these are oscillator channels? Not backed by audio.
// No idea how to implement these yet, so skip them.
channel.mIsFinished = true;
continue;
skipRender = true;
}
ValidateChannel(channel);
OutputSubframe channelSubframe = {};
RenderChannel(channel, channelAux, channelSubframe);
if (!skipRender) {
ValidateChannel(channel);
RenderChannel(channel, channelAux, channelSubframe);
// todo figure out an actual way to convert this accurately to dry/wet
channelAux.reverb.setwet(((channel.mAutoMixerFxMix >> 8) / 255.0f));
channelAux.reverb.setdry(1.0f - channelAux.reverb.getwet());
}
if (EnableReverb) {
channelAux.reverb.processreplace(
channelSubframe.channels[0].data(),
channelSubframe.channels[1].data(),
channelSubframe.channels[0].data(),
channelSubframe.channels[1].data(),
DSP_SUBFRAME_SIZE,
1
);
}
for (int o = 0; o < subframe.channels.size(); o++) {
MixSubframe(subframe.channels[o], channelSubframe.channels[o]);
@@ -463,6 +479,16 @@ static void RenderChannel(
}
void dusk::audio::DspInit() {
for (int i = 0; i < DSP_CHANNELS; i++) {
auto& channelAux = ChannelAux[i];
channelAux.reverb.setwet(0.0f);
channelAux.reverb.setdry(1.0f);
channelAux.reverb.setroomsize(0.2f);
channelAux.reverb.setdamp(0.3f);
channelAux.reverb.setwidth(1.0f);
channelAux.reverb.setmode(0.0f);
channelAux.reverb.mute();
}
}
void dusk::audio::ApplyVolume(
+4
View File
@@ -8,6 +8,8 @@
#include "SDL3/SDL_audio.h"
#include <span>
#include "revmodel.hpp"
// ReSharper disable once CppUnusedIncludeDirective
#include "global.h"
@@ -29,6 +31,7 @@ namespace dusk::audio {
// Used for debugging tools.
u32 resetCount;
revmodel reverb;
/**
* Previous volume values, per output channel.
@@ -118,4 +121,5 @@ namespace dusk::audio {
extern f32 MasterVolume;
extern f32 PrevMasterVolume;
extern bool EnableReverb;
}
+3 -1
View File
@@ -6,6 +6,7 @@
#include <imgui_internal.h>
#include "JSystem/JUtility/JUTGamePad.h"
#include "dusk/audio/DuskDsp.hpp"
#include "dusk/audio/DuskAudioSystem.h"
#include "dusk/hotkeys.h"
#include "dusk/settings.h"
@@ -34,7 +35,7 @@ namespace dusk {
if (ImGui::BeginMenu("Audio")) {
ImGui::Text("Master Volume");
ImGui::SliderFloat("##masterVolume", &getSettings().audio.masterVolume, 0.0f, 1.0f, "");
ImGui::Checkbox("Enable Reverb", &getSettings().audio.enableReverb);
/*
// TODO: implement additional settings
ImGui::Text("Main Music Volume");
@@ -55,6 +56,7 @@ namespace dusk {
*/
audio::SetMasterVolume(getSettings().audio.masterVolume);
audio::EnableReverb = getSettings().audio.enableReverb;
ImGui::EndMenu();
}
+1
View File
@@ -17,6 +17,7 @@ UserSettings g_userSettings = {
.subMusicVolume = 1.0f,
.soundEffectsVolume = 1.0f,
.fanfareVolume = 1.0f,
.enableReverb = true
},
// Game settings