Audio: Show granular mixer stats in the audio debug overlay

Queue fill and cap (in granules and ms), under/overruns, output rate, read
size and frame time, replacing the "no stats yet" placeholder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-11-10 10:29:23 +01:00
1 parent 5f349fd603
commit e040fa5223
3 files changed
+40 -1

No files matched your search

+34
View File
@@ -6,6 +6,7 @@
#include <chrono>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include "Common/CommonTypes.h"
@@ -80,6 +81,7 @@ void GranularMixer::Mix(s16 *samples, u32 num_samples, int outSampleRate, float
memset(samples, 0, num_samples * 2 * sizeof(s16));
// The estimate is 0 until a second has gone by.
frameTimeEstimate_ = 1.0f / std::max(fpsEstimate, 1.0f);
outSampleRate_ = outSampleRate;
smoothedReadSize_ = smoothedReadSize_ == 0 ? num_samples : (smoothedReadSize_ * 0.95f + num_samples * 0.05f);
@@ -309,3 +311,35 @@ void GranularMixer::GetStats(GranularStats *stats) {
queuedGranulesMin_ = 10000;
queuedGranulesMax_ = 0;
}
void GranularMixer::GetAudioDebugStats(char *buf, size_t bufSize) {
GranularStats stats;
GetStats(&stats);
// Each queued granule holds GRANULE_OVERLAP new samples.
const double msPerGranule = GRANULE_OVERLAP * 1000.0 / 44100.0;
snprintf(buf, bufSize,
"Granular mixer\n"
"Queued: %0.1f granules (%0.1fms)\n"
"Queued min/max: %d / %d\n"
"Cap: %d granules (%0.1fms, %d samples)\n"
"Underruns: %d\n"
"Overruns: %d\n"
"Output sample rate: %d\n"
"Read size: %0.1f\n"
"Frame time estimate: %0.1fms\n"
"Fade volume: %0.2f%s\n",
stats.smoothedQueuedGranules, stats.smoothedQueuedGranules * msPerGranule,
stats.queuedGranulesMin, stats.queuedGranulesMax,
stats.targetQueueSize, stats.targetQueueSize * msPerGranule, stats.queuedSamplesTarget,
stats.underruns,
stats.overruns,
outSampleRate_,
stats.smoothedReadSize,
stats.frameTimeEstimate * 1000.0f,
stats.fadeVolume, stats.looping ? " (looping)" : "");
}
void GranularMixer::ResetStatCounters() {
underruns_ = 0;
overruns_ = 0;
}
+4
View File
@@ -46,6 +46,9 @@ public:
void PushSamples(const s32 *samples, u32 num_samples, float volume);
void GetStats(GranularStats *stats);
// Text for the audio debug overlay.
void GetAudioDebugStats(char *buf, size_t bufSize);
void ResetStatCounters();
static constexpr u32 GRANULE_SIZE = 256;
@@ -107,6 +110,7 @@ private:
int queuedSamplesTarget_ = 0;
float smoothedReadSize_ = 0.0f;
float frameTimeEstimate_ = 0.0f;
int outSampleRate_ = 0;
void Enqueue();
void Dequeue(Granule* granule);
+2 -1
View File
@@ -47,12 +47,13 @@ void NativeMix(int16_t *outStereo, int numFrames, int sampleRateHz, void *userda
void System_AudioGetDebugStats(char *buf, size_t bufSize) {
if (buf) {
if (g_Config.iAudioPlaybackMode == (int)AudioSyncMode::GRANULAR) {
snprintf(buf, bufSize, "(No stats available for granular yet)");
g_granular.GetAudioDebugStats(buf, bufSize);
} else {
g_resampler.GetAudioDebugStats(buf, bufSize);
}
} else {
g_resampler.ResetStatCounters();
g_granular.ResetStatCounters();
}
}