From c41dca43256a385fed1143fe3dbe0af6357bf1eb Mon Sep 17 00:00:00 2001 From: wbcbz7 Date: Wed, 13 Aug 2025 19:44:42 +0700 Subject: [PATCH] fix AY envelope packing --- vgm2opl_next/vgm2opl_next/vgm2opl_next.cpp | 99 ++++++++++++---------- vgmplay/lxmplay/main.cpp | 4 +- 2 files changed, 55 insertions(+), 48 deletions(-) diff --git a/vgm2opl_next/vgm2opl_next/vgm2opl_next.cpp b/vgm2opl_next/vgm2opl_next/vgm2opl_next.cpp index 5a10756..0bfb8ad 100644 --- a/vgm2opl_next/vgm2opl_next/vgm2opl_next.cpp +++ b/vgm2opl_next/vgm2opl_next/vgm2opl_next.cpp @@ -1046,7 +1046,7 @@ int opm_serialize_ssg_tone_stream(opm_channel_t* chctx) { s.rawdata.push_back(OPM_STREAM_END_FRAME); } else { - if (ef & OPM_REC_AYTONE_PERIOD_HIGH) { + if (ef & (OPM_REC_AYTONE_PERIOD_HIGH | OPM_REC_AYTONE_PERIOD_LOW)) { // high period available, write it auto ef_cur = ef; ef &= ~(OPM_REC_AYTONE_PERIOD_HIGH | OPM_REC_AYTONE_PERIOD_LOW); // write both hi and lo if available @@ -1093,6 +1093,7 @@ int opm_serialize_ssg_tone_stream(opm_channel_t* chctx) { int opm_serialize_ssg_env_stream(opm_channel_t* chctx) { int old_delay = -1; + bool delay_emitted = false; for (int f = 0; f < chctx->records.size(); f++) { auto& s = chctx->records[f]; s.rawdata.clear(); @@ -1105,61 +1106,67 @@ int opm_serialize_ssg_env_stream(opm_channel_t* chctx) { if (s.frame_dist != old_delay || (s.flags & OPM_CHAN_LOOP_POINT)) { old_delay = s.frame_dist; opm_set_delay(s.rawdata, s.frame_dist); + delay_emitted = true; } // process events - if (s.records.size() > 0) for (int i = 0; i < s.records.size(); i++) { - auto& e = s.records[i]; - uint64_t ef = e.flags; + if (s.records.size() > 0) { + for (int i = 0; i < s.records.size(); i++) { + auto& e = s.records[i]; + uint64_t ef = e.flags; - if ((ef == 0) && (i == s.records.size() - 1)) { - s.rawdata.push_back(OPM_STREAM_END_FRAME); - } - else { - if (ef & OPM_REC_AYENV_PERIOD_HIGH) { - // high period available, write it - auto ef_cur = ef; - ef &= ~(OPM_REC_AYENV_PERIOD_HIGH | OPM_REC_AYENV_PERIOD_LOW); // write both hi and lo if available - // write registers - s.rawdata.push_back( - OPM_AYENV_PERIOD_FULL | - ((ef == 0) && (i == s.records.size() - 1) ? OPM_AYENV_CMDF0_EOF : 0) | - (ef_cur & OPM_REC_AYENV_PERIOD_LOW ? OPM_AYENV_CMDF0_PERIOD_LOW : 0) | - (ef_cur & OPM_REC_AYENV_PERIOD_HIGH ? OPM_AYENV_CMDF0_PERIOD_HIGH : 0) - ); - if (ef_cur & OPM_REC_AYENV_PERIOD_LOW) s.rawdata.push_back(e.ayenv.period_low); - if (ef_cur & OPM_REC_AYENV_PERIOD_HIGH) s.rawdata.push_back(e.ayenv.period_hi); + if ((ef == 0) && (i == s.records.size() - 1)) { + s.rawdata.push_back(OPM_STREAM_END_FRAME); } + else { + if (ef & (OPM_REC_AYENV_PERIOD_HIGH | OPM_REC_AYENV_PERIOD_LOW)) { + // high period available, write it + auto ef_cur = ef; + ef &= ~(OPM_REC_AYENV_PERIOD_HIGH | OPM_REC_AYENV_PERIOD_LOW); // write both hi and lo if available + // write registers + s.rawdata.push_back( + OPM_AYENV_PERIOD_FULL | + ((ef == 0) && (i == s.records.size() - 1) ? OPM_AYENV_CMDF0_EOF : 0) | + (ef_cur & OPM_REC_AYENV_PERIOD_LOW ? OPM_AYENV_CMDF0_PERIOD_LOW : 0) | + (ef_cur & OPM_REC_AYENV_PERIOD_HIGH ? OPM_AYENV_CMDF0_PERIOD_HIGH : 0) + ); + if (ef_cur & OPM_REC_AYENV_PERIOD_LOW) s.rawdata.push_back(e.ayenv.period_low); + if (ef_cur & OPM_REC_AYENV_PERIOD_HIGH) s.rawdata.push_back(e.ayenv.period_hi); + } - if (ef & OPM_REC_AYENV_NOISE) { - // noise available, write it - auto ef_cur = ef; - ef &= ~(OPM_REC_AYENV_NOISE | OPM_REC_AYENV_PERIOD_LOW); // write both noise and period low if available - // write registers - s.rawdata.push_back( - OPM_AYENV_REGS | - ((ef == 0) && (i == s.records.size() - 1) ? OPM_AYENV_CMD00_EOF : 0) | - (ef_cur & OPM_REC_AYENV_PERIOD_LOW ? OPM_AYENV_CMD00_PERIOD_LOW : 0) | - (e.ayenv.noise & OPM_AYENV_CMD00_NOISE_MASK) - ); - if (ef_cur & OPM_REC_AYENV_PERIOD_LOW) s.rawdata.push_back(e.ayenv.period_low); - } + if (ef & (OPM_REC_AYENV_NOISE | OPM_REC_AYENV_PERIOD_LOW)) { + // noise available, write it + auto ef_cur = ef; + ef &= ~(OPM_REC_AYENV_NOISE | OPM_REC_AYENV_PERIOD_LOW); // write both noise and period low if available + // write registers + s.rawdata.push_back( + OPM_AYENV_REGS | + ((ef == 0) && (i == s.records.size() - 1) ? OPM_AYENV_CMD00_EOF : 0) | + (ef_cur & OPM_REC_AYENV_PERIOD_LOW ? OPM_AYENV_CMD00_PERIOD_LOW : 0) | + (e.ayenv.noise & OPM_AYENV_CMD00_NOISE_MASK) + ); + if (ef_cur & OPM_REC_AYENV_PERIOD_LOW) s.rawdata.push_back(e.ayenv.period_low); + } - if (ef & OPM_REC_AYENV_ENVTYPE) { - // envelope type available, write it - auto ef_cur = ef; - ef &= ~(OPM_REC_AYENV_ENVTYPE | OPM_REC_AYENV_PERIOD_LOW); // write both envtype and period low if available - // write registers - s.rawdata.push_back( - OPM_AYENV_ENVTYPE | - ((ef == 0) && (i == s.records.size() - 1) ? OPM_AYENV_CMD80_EOF : 0) | - (ef_cur & OPM_REC_AYENV_PERIOD_LOW ? OPM_AYENV_CMD80_PERIOD_LOW : 0) | - (e.ayenv.envtype & OPM_AYENV_CMD80_ENV_TYPE) - ); - if (ef_cur & OPM_REC_AYENV_PERIOD_LOW) s.rawdata.push_back(e.ayenv.period_low); + if (ef & (OPM_REC_AYENV_ENVTYPE | OPM_REC_AYENV_PERIOD_LOW)) { + // envelope type available, write it + auto ef_cur = ef; + ef &= ~(OPM_REC_AYENV_ENVTYPE | OPM_REC_AYENV_PERIOD_LOW); // write both envtype and period low if available + // write registers + s.rawdata.push_back( + OPM_AYENV_ENVTYPE | + ((ef == 0) && (i == s.records.size() - 1) ? OPM_AYENV_CMD80_EOF : 0) | + (ef_cur & OPM_REC_AYENV_PERIOD_LOW ? OPM_AYENV_CMD80_PERIOD_LOW : 0) | + (e.ayenv.envtype & OPM_AYENV_CMD80_ENV_TYPE) + ); + if (ef_cur & OPM_REC_AYENV_PERIOD_LOW) s.rawdata.push_back(e.ayenv.period_low); + } } } } + else { // if (s.records.size() > 0) + if (delay_emitted) s.rawdata.push_back(OPM_STREAM_END_FRAME); + } } return 0; } diff --git a/vgmplay/lxmplay/main.cpp b/vgmplay/lxmplay/main.cpp index 4a2763a..7dfd183 100644 --- a/vgmplay/lxmplay/main.cpp +++ b/vgmplay/lxmplay/main.cpp @@ -118,7 +118,7 @@ public: } }; -opna_interface_t opna_interface; +opna_interface_t opna_interface[2]; ymfm::ym2203 *opnachip[2]; opnx_register_queue_t opna_regqueue[2]; ymfm::ym2203::output_data opna_out[MAX_FRAMES_PER_BUFFER][2]; @@ -409,7 +409,7 @@ int main(int argc, char* argv[]) uint32_t sample_rate; for (int chip = 0; chip < 2; chip++) { - opnachip[chip] = new ymfm::ym2203(opna_interface); + opnachip[chip] = new ymfm::ym2203(opna_interface[chip]); if (opnachip[chip] == nullptr) { printf("error: unable to init ymfm!\n"); return 1;