mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 09:39:33 +01:00
Audio: Size the granular queue from the classic resampler's target
The queue cap was four output callbacks plus a frame of audio. Bluetooth and other outputs without a fast path call back with large chunks, so that came to about 100 ms there. Now it's the classic target (which also honors Extra audio buffering), raised for slow games' per-frame bursts and to keep half the queue above one callback's read, plus a granule for the overlap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
997cc92072
commit
5f349fd603
3 files changed
+28
-17
No files matched your search
@@ -14,6 +14,7 @@
|
||||
#include "Common/Swap.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/HW/Display.h"
|
||||
#include "Core/HW/StereoResampler.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/Util/AudioFormat.h" // for clamp_u16
|
||||
@@ -102,13 +103,17 @@ void GranularMixer::Mix(s16 *samples, u32 num_samples, int outSampleRate, float
|
||||
const float fade_in_mul = -std::expm1(-1.0 / (out_sample_rate * FADE_IN_RC));
|
||||
const float fade_out_mul = -std::expm1(-1.0 / (out_sample_rate * FADE_OUT_RC));
|
||||
|
||||
// Calculate the ideal length of the granule queue.
|
||||
// NOTE: We must have enough room here for 20fps games, generating all their audio
|
||||
// in a burst each frame (since we can't force real clock sync). That means 16*3 = 48 or rather 50ms.
|
||||
// However, in case of faster framerates, we should apply some pressure to reduce this. And if real clock sync
|
||||
// is on, we should also be able to get away with a shorter buffer here.
|
||||
// const u32 buffer_size_ms = frameTimeEstimate_ * 44100.0f;
|
||||
const u32 buffer_size_samples = smoothedReadSize_ * 4 + std::llround(frameTimeEstimate_ * inSampleRate);
|
||||
// Calculate the length of the granule queue. Dequeue() cuts the queue back to half when it
|
||||
// goes over, so this is a cap rather than a fill level.
|
||||
// We aim for the same latency as StereoResampler, but must also have room for slow (like 20fps)
|
||||
// games, which generate all their audio in a burst each frame (since we can't force real
|
||||
// clock sync), and keep half the queue above what one output callback reads, or each callback
|
||||
// runs dry. Bluetooth and other non-fast outputs read in large chunks.
|
||||
// One more granule on top, for the two half-overlapping granules being played.
|
||||
const int targetSamples = StereoResampler::TargetBufferSize();
|
||||
const int frameSamples = (int)std::llround(frameTimeEstimate_ * inSampleRate);
|
||||
const int readSamples = (int)(smoothedReadSize_ * inSampleRate / out_sample_rate);
|
||||
const u32 buffer_size_samples = std::max({ targetSamples, frameSamples + targetSamples / 2, readSamples * 2 }) + GRANULE_SIZE;
|
||||
queuedSamplesTarget_ = buffer_size_samples;
|
||||
|
||||
// Limit the possible queue sizes to any number between 4 and 64.
|
||||
|
||||
+13
-10
@@ -74,20 +74,23 @@ StereoResampler::~StereoResampler() {
|
||||
buffer_ = nullptr;
|
||||
}
|
||||
|
||||
void StereoResampler::UpdateBufferSize() {
|
||||
int StereoResampler::TargetBufferSize() {
|
||||
if (g_Config.bExtraAudioBuffering) {
|
||||
return TARGET_BUFSIZE_EXTRA;
|
||||
}
|
||||
int systemBufsize = System_GetPropertyInt(SYSPROP_AUDIO_FRAMES_PER_BUFFER);
|
||||
if (systemBufsize > 0 && TARGET_BUFSIZE_DEFAULT < systemBufsize + TARGET_BUFSIZE_MARGIN) {
|
||||
return std::min(4096, systemBufsize + TARGET_BUFSIZE_MARGIN);
|
||||
}
|
||||
return TARGET_BUFSIZE_DEFAULT;
|
||||
}
|
||||
|
||||
void StereoResampler::UpdateBufferSize() {
|
||||
targetBufsize_ = TargetBufferSize();
|
||||
if (g_Config.bExtraAudioBuffering || targetBufsize_ * 2 > MAX_BUFSIZE_DEFAULT) {
|
||||
maxBufsize_ = MAX_BUFSIZE_EXTRA;
|
||||
targetBufsize_ = TARGET_BUFSIZE_EXTRA;
|
||||
} else {
|
||||
maxBufsize_ = MAX_BUFSIZE_DEFAULT;
|
||||
targetBufsize_ = TARGET_BUFSIZE_DEFAULT;
|
||||
|
||||
int systemBufsize = System_GetPropertyInt(SYSPROP_AUDIO_FRAMES_PER_BUFFER);
|
||||
if (systemBufsize > 0 && targetBufsize_ < systemBufsize + TARGET_BUFSIZE_MARGIN) {
|
||||
targetBufsize_ = std::min(4096, systemBufsize + TARGET_BUFSIZE_MARGIN);
|
||||
if (targetBufsize_ * 2 > MAX_BUFSIZE_DEFAULT)
|
||||
maxBufsize_ = MAX_BUFSIZE_EXTRA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,9 @@ public:
|
||||
void GetAudioDebugStats(char *buf, size_t bufSize);
|
||||
void ResetStatCounters();
|
||||
|
||||
// The buffer fill to aim for, in 44.1 kHz stereo frames. GranularMixer sizes its queue from this too.
|
||||
static int TargetBufferSize();
|
||||
|
||||
private:
|
||||
void UpdateBufferSize();
|
||||
|
||||
|
||||
Reference in new issue
Block a user