From fe17265cfb4341e768e7cd39a0537e7c06b0ce5c Mon Sep 17 00:00:00 2001 From: kichikuou Date: Thu, 27 Nov 2025 08:11:18 +0900 Subject: [PATCH] Fix ymfm timing issues by queuing register writes Rapid register writes could cause audio glitches [1]. This introduces a queue to process one write per audio generation cycle. This approach is the same as the one used in ymfm's vgmrender.cpp. [1] https://github.com/aaronsgiles/ymfm/issues/1 --- src/fm/mako_ymfm.cpp | 11 ++++++++--- src/fm/mako_ymfm.h | 8 ++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/fm/mako_ymfm.cpp b/src/fm/mako_ymfm.cpp index 15ef412..249bead 100644 --- a/src/fm/mako_ymfm.cpp +++ b/src/fm/mako_ymfm.cpp @@ -48,9 +48,8 @@ void MakoYmfm::Process(int16_t* stream, int len) { } void MakoYmfm::SetReg(RegType type, uint8_t addr, uint8_t val) { - uint32_t offset = type == OPNA_SLAVE ? 2 : 0; - opna.write(offset, addr); - opna.write(offset + 1, val); + uint8_t port = type == OPNA_SLAVE ? 2 : 0; + queue.push({port, addr, val}); } void MakoYmfm::Generate(int16_t* buf, int samples) { @@ -62,6 +61,12 @@ void MakoYmfm::Generate(int16_t* buf, int samples) { // generate at the appropriate sample rate assert(opna_pos <= output_pos); while (opna_pos <= output_pos) { + if (!queue.empty()) { + auto w = queue.front(); + opna.write(w.port, w.addr); + opna.write(w.port + 1, w.val); + queue.pop(); + } opna.generate(&opna_output); opna_pos += opna_step; } diff --git a/src/fm/mako_ymfm.h b/src/fm/mako_ymfm.h index fb4ace0..f908d5b 100644 --- a/src/fm/mako_ymfm.h +++ b/src/fm/mako_ymfm.h @@ -1,6 +1,7 @@ #ifndef MAKOYMFM_H_ #define MAKOYMFM_H_ +#include #include #include "ymfm_opn.h" #include "makofm.h" @@ -15,6 +16,12 @@ private: // we use an int64_t as emulated time, as a 32.32 fixed point value using emulated_time = int64_t; + struct RegWrite { + uint8_t port; + uint8_t addr; + uint8_t val; + }; + void SetReg(RegType type, uint8_t addr, uint8_t val) override; void Generate(int16_t* buf, int samples); @@ -24,6 +31,7 @@ private: emulated_time output_pos = 0; int last_sync = 0; int samples_left = 0; + std::queue queue; }; #endif // MAKOYMFM_H_