fix AY envelope packing

This commit is contained in:
wbcbz7 2025-08-13 19:44:42 +07:00
parent ad6deb23d2
commit c41dca4325
2 changed files with 55 additions and 48 deletions

View file

@ -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;
}

View file

@ -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;