From 9d0ef311c03445bd42db55fc7826e9821ce0d5da Mon Sep 17 00:00:00 2001 From: Paul Walker Date: Mon, 5 Aug 2024 14:52:57 -0400 Subject: [PATCH] A few small performance tweaks Turns out the active voice calculation was kidna expensive as were VUs on busses we weren't using, so do a couple of little optimizations for each of those. The bug ones (don't evaluate busses with no activity at all) still isn't done. Addresses #1068 --- libs/sst/sst-basic-blocks | 2 +- src/engine/bus.cpp | 10 +++++++++- src/engine/engine.cpp | 13 +++++++++---- src/engine/engine.h | 3 ++- src/voice/voice.cpp | 1 + src/voice/voice.h | 1 + 6 files changed, 23 insertions(+), 7 deletions(-) diff --git a/libs/sst/sst-basic-blocks b/libs/sst/sst-basic-blocks index a91558d6..0fa6e1dd 160000 --- a/libs/sst/sst-basic-blocks +++ b/libs/sst/sst-basic-blocks @@ -1 +1 @@ -Subproject commit a91558d6d92039a10e30d46ebffcdf13fb620b90 +Subproject commit 0fa6e1dd7577f2799d06ad91a9cba7d066aad3b3 diff --git a/src/engine/bus.cpp b/src/engine/bus.cpp index f540af6e..b27625fd 100644 --- a/src/engine/bus.cpp +++ b/src/engine/bus.cpp @@ -289,7 +289,15 @@ void Bus::process() for (int c = 0; c < 2; ++c) { vuLevel[c] = std::min(2.f, a * vuLevel[c]); - vuLevel[c] = std::max((float)vuLevel[c], mech::blockAbsMax(output[c])); + /* we use this as a proxy for a silent block without having to scan the entire + * block. If the block isn't silent, we will get the next vlock if we just get + * unlucky with sample 0 except in a super pathological case of an exactly + * 16 sample sin wave or something. + */ + if (std::fabs(output[c][0]) > 1e-15) + { + vuLevel[c] = std::max((float)vuLevel[c], mech::blockAbsMax(output[c])); + } } } diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 3c82b711..6d948a32 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -179,6 +179,7 @@ voice::Voice *Engine::initiateVoice(const pathToZone_t &path) voices[idx]->noteId = path.noteid; voices[idx]->setSampleRate(sampleRate, sampleRateInv); voices[idx]->endpoints = std::move(mp); + activeVoices++; return voices[idx]; } } @@ -248,7 +249,7 @@ bool Engine::processAudio() #endif messageController->engineProcessRuns++; messageController->isAudioRunning = true; - auto av = activeVoiceCount(); + auto av = (uint32_t)activeVoices; bool tryToDrain{true}; while (tryToDrain && !messageController->serializationToAudioQueue.empty()) @@ -316,7 +317,11 @@ bool Engine::processAudio() bl[idx++][c] = a.vuLevel[c]; } - auto pav = activeVoiceCount(); + auto pav = (uint32_t)activeVoices; +#if BUILD_IS_DEBUG + if (pav != av) + assertActiveVoiceCount(); +#endif bool doUpdate = messageController->isClientConnected && ( @@ -372,7 +377,7 @@ bool Engine::processAudio() return true; } -uint32_t Engine::activeVoiceCount() +void Engine::assertActiveVoiceCount() { uint32_t res{0}; for (const auto v : voices) @@ -380,7 +385,7 @@ uint32_t Engine::activeVoiceCount() if (v) res += (v->isVoiceAssigned && v->isVoicePlaying); } - return res; + assert(res == activeVoices); } const std::optional diff --git a/src/engine/engine.h b/src/engine/engine.h index 5d616129..fa0167a9 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -229,7 +229,8 @@ struct Engine : MoveableOnly, SampleRateSupport void stopAllSounds(); // TODO: All this gets ripped out when voice management is fixed - uint32_t activeVoiceCount(); + void assertActiveVoiceCount(); + std::atomic activeVoices{0}; const std::unique_ptr &getMessageController() const { diff --git a/src/voice/voice.cpp b/src/voice/voice.cpp index d92b2df8..3fd57073 100644 --- a/src/voice/voice.cpp +++ b/src/voice/voice.cpp @@ -68,6 +68,7 @@ void Voice::cleanupVoice() zone = nullptr; isVoiceAssigned = false; engine->voiceManagerResponder.doVoiceEndCallback(this); + engine->activeVoices--; // We cleanup processors here since they may have, say, // memory pool resources checked out that others could diff --git a/src/voice/voice.h b/src/voice/voice.h index 2e1dcd2f..014c2576 100644 --- a/src/voice/voice.h +++ b/src/voice/voice.h @@ -178,6 +178,7 @@ struct alignas(16) Voice : MoveableOnly, isVoicePlaying = true; isVoiceAssigned = true; + voiceStarted(); } void release() { isGated = false; }