mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-07-12 07:39:41 -04:00
Fix audio regression playing audio too slowly (#6894)
Dither to 32000Khz
This commit is contained in:
+19
-12
@@ -1020,13 +1020,24 @@ std::unordered_map<std::string, ExtensionEntry> ExtensionCache;
|
||||
|
||||
void OTRAudio_Thread() {
|
||||
#define SAMPLES_HIGH 560
|
||||
#define SAMPLES_MID 544
|
||||
#define SAMPLES_LOW 528
|
||||
#define AUDIO_FRAMES_PER_UPDATE (R_UPDATE_RATE > 0 ? R_UPDATE_RATE : 1)
|
||||
#define NUM_AUDIO_CHANNELS 2
|
||||
|
||||
// Single producer routine used by both the wake-driven and pre-buffer
|
||||
// loops. Captures the per-iteration sample count from the caller.
|
||||
auto produce_and_play = [&](u32 num_audio_samples) {
|
||||
// The sequencer advances a fixed slice of musical time per engine update
|
||||
// (tempoInternalToExternal in audio_heap.c assumes 60 updates/sec), so with
|
||||
// production paced by backend buffer fill the sample count must average
|
||||
// exactly 32000/60 = 533.33 per update or tempo drifts.
|
||||
// Two thirds 528 one third 544 gives 533.33.
|
||||
int32_t sample_debt_thirds = 0;
|
||||
|
||||
// Single producer routine used by both wake-driven and pre-buffer loops.
|
||||
// Picks per-iteration sample count itself, then produces and plays it.
|
||||
auto produce_next_batch = [&]() {
|
||||
u32 num_audio_samples = sample_debt_thirds > 0 ? SAMPLES_MID : SAMPLES_LOW;
|
||||
sample_debt_thirds += (1600 - 3 * (int32_t)num_audio_samples) * AUDIO_FRAMES_PER_UPDATE;
|
||||
|
||||
const u32 total_frames = num_audio_samples * AUDIO_FRAMES_PER_UPDATE;
|
||||
const u32 total_samples = total_frames * NUM_AUDIO_CHANNELS;
|
||||
|
||||
@@ -1077,18 +1088,16 @@ void OTRAudio_Thread() {
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> Lock(audio.mutex);
|
||||
int samples_left = AudioPlayer_Buffered();
|
||||
u32 num_audio_samples = samples_left < AudioPlayer_GetDesiredBuffered() ? SAMPLES_HIGH : SAMPLES_LOW;
|
||||
|
||||
// Producer guard (banteg/Shipwright#6594): skip advancing the audio
|
||||
// engine if the backend ring cannot accept the smallest next burst.
|
||||
// engine if the backend ring cannot accept the largest next burst.
|
||||
// Generating PCM that DoPlay() would refuse creates a discontinuity
|
||||
// audible as a click. The pre-buffer loop below will catch up once
|
||||
// the backend drains enough.
|
||||
if (AudioPlayer_Buffered() + SAMPLES_LOW * AUDIO_FRAMES_PER_UPDATE > AudioPlayer_GetDesiredBuffered()) {
|
||||
if (AudioPlayer_Buffered() + SAMPLES_MID * AUDIO_FRAMES_PER_UPDATE > AudioPlayer_GetDesiredBuffered()) {
|
||||
audio.processing = false;
|
||||
} else {
|
||||
produce_and_play(num_audio_samples);
|
||||
produce_next_batch();
|
||||
audio.processing = false;
|
||||
}
|
||||
}
|
||||
@@ -1099,12 +1108,10 @@ void OTRAudio_Thread() {
|
||||
// The producer guard (same as above) prevents advancing the audio engine
|
||||
// when the backend ring is already at capacity.
|
||||
while (audio.running && AudioPlayer_Buffered() < AudioPlayer_GetDesiredBuffered()) {
|
||||
if (AudioPlayer_Buffered() + SAMPLES_LOW * AUDIO_FRAMES_PER_UPDATE > AudioPlayer_GetDesiredBuffered()) {
|
||||
if (AudioPlayer_Buffered() + SAMPLES_MID * AUDIO_FRAMES_PER_UPDATE > AudioPlayer_GetDesiredBuffered()) {
|
||||
break;
|
||||
}
|
||||
int samples_left = AudioPlayer_Buffered();
|
||||
u32 num_audio_samples = samples_left < AudioPlayer_GetDesiredBuffered() ? SAMPLES_HIGH : SAMPLES_LOW;
|
||||
produce_and_play(num_audio_samples);
|
||||
produce_next_batch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user