implement implicit end of frames
This commit is contained in:
parent
cafc4a011b
commit
4770e2cffd
|
@ -20,7 +20,7 @@
|
|||
const uint32_t SAMPLE_RATE = 44100;
|
||||
enum {
|
||||
CHANNELS = 2,
|
||||
FRAMES_PER_BUFFER = 256,
|
||||
FRAMES_PER_BUFFER = 512,
|
||||
};
|
||||
|
||||
PaStreamParameters outputParameters;
|
||||
|
@ -192,7 +192,7 @@ int pa_init() {
|
|||
}
|
||||
outputParameters.channelCount = CHANNELS;
|
||||
outputParameters.sampleFormat = paInt16;
|
||||
outputParameters.suggestedLatency = 0.02;
|
||||
outputParameters.suggestedLatency = 0.04;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
err = Pa_OpenStream(
|
||||
|
|
|
@ -251,14 +251,16 @@ int opmplay_tick(opmplay_context_t* ctx, opl3_chip* opl3) {
|
|||
if (mask & OPM_CMD80_SET_MULT) OPL3_WriteRegBuffered(opl3, 0x20+op, *data++);
|
||||
if (mask & OPM_CMD80_SET_TL) OPL3_WriteRegBuffered(opl3, 0x40+op, *data++);
|
||||
if (mask & OPM_CMD80_SET_WAVEFORM) OPL3_WriteRegBuffered(opl3, 0xE0+op, *data++);
|
||||
if (mask & OPM_CMD80_END_OF_FRAME) isRun = false;
|
||||
continue;
|
||||
}
|
||||
if ((*(data) & 0xF0) == OPM_SET_ADSR) {
|
||||
int mask = *data;
|
||||
int op = (mask & OPM_CMDA0_SELECT_OPERATOR ? 3 : 0) + opmplay_opregs_channel_offset[ch];
|
||||
data++;
|
||||
if (mask & OPM_CMDA0_SET_AD) OPL3_WriteRegBuffered(opl3, 0x60 + op, *data++);
|
||||
if (mask & OPM_CMDA0_SET_SR) OPL3_WriteRegBuffered(opl3, 0x80 + op, *data++);
|
||||
if (mask & OPM_CMDA0_SET_AD) OPL3_WriteRegBuffered(opl3, 0x60 + op, *data++);
|
||||
if (mask & OPM_CMDA0_SET_SR) OPL3_WriteRegBuffered(opl3, 0x80 + op, *data++);
|
||||
if (mask & OPM_CMDA0_END_OF_FRAME) isRun = false;
|
||||
continue;
|
||||
}
|
||||
if ((*(data) & 0xF0) == OPM_SET_FREQ_FB) {
|
||||
|
@ -266,7 +268,15 @@ int opmplay_tick(opmplay_context_t* ctx, opl3_chip* opl3) {
|
|||
data++;
|
||||
if (mask & OPM_CMDB0_SET_FEEDBACK) OPL3_WriteRegBuffered(opl3, 0xC0 + ch, *data++);
|
||||
if (mask & OPM_CMDB0_SET_FREQ_LOW) OPL3_WriteRegBuffered(opl3, 0xA0 + ch, *data++);
|
||||
if (mask & OPM_CMDB0_SET_FREQ_HIGH) OPL3_WriteRegBuffered(opl3, 0xB0 + ch, *data++);
|
||||
if (mask & OPM_CMDB0_SET_FREQ_HIGH) { chctx->block = *data; OPL3_WriteRegBuffered(opl3, 0xB0 + ch, *data++); };
|
||||
if (mask & OPM_CMDB0_END_OF_FRAME) isRun = false;
|
||||
continue;
|
||||
}
|
||||
if ((*data & 0xFC) == OPM_KEY_TRIGGER) {
|
||||
if (*data & OPM_KEY_ON) chctx->block |= (1 << 5); else chctx->block &= ~(1 << 5);
|
||||
OPL3_WriteRegBuffered(opl3, 0xB0 + ch, chctx->block);
|
||||
if (*data & OPM_KEY_END_OF_FRAME) isRun = false;
|
||||
data++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ struct opmplay_io_t {
|
|||
|
||||
struct opmplay_channel_context_t {
|
||||
// TODO: internal registers (skipped atm)
|
||||
uint8_t block; // used to track key on/off changes
|
||||
|
||||
// stream data
|
||||
struct {
|
||||
|
|
|
@ -594,6 +594,7 @@ int opm_serialize_channel_stream(opm_convert_context_t* ctx, int ch) {
|
|||
opm_set_delay(s.rawdata, s.frame_dist);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// process events
|
||||
for (auto& e : s.records) {
|
||||
for (int op = 0; op < 2; op++) {
|
||||
|
@ -623,7 +624,70 @@ int opm_serialize_channel_stream(opm_convert_context_t* ctx, int ch) {
|
|||
if (ff & OPM_BLOCK) s.rawdata.push_back(e.block);
|
||||
}
|
||||
}
|
||||
s.rawdata.push_back(s.frame_dist == 0 ? OPM_STREAM_END : OPM_STREAM_END_FRAME);
|
||||
#else
|
||||
for (int i = 0; i < s.records.size(); i++) {
|
||||
// get masks for events
|
||||
auto& e = s.records[i];
|
||||
struct {
|
||||
int op[2];
|
||||
int adsr[2];
|
||||
int freq_fb;
|
||||
bool key;
|
||||
int last;
|
||||
} mask;
|
||||
|
||||
// generate masks
|
||||
mask.last = 0; int bit = 0;
|
||||
for (int op = 0; op < 2; op++) {
|
||||
mask.op[op] = ((e.flags >> (OPM_OP1_SHIFT * op)) & (OPM_MULT | OPM_KSL_TL | OPM_WAVEFORM));
|
||||
mask.last |= ((mask.op[op] ? 1 : 0) << bit++);
|
||||
mask.adsr[op] = ((e.flags >> (OPM_OP1_SHIFT * op)) & (OPM_AD | OPM_SR));
|
||||
mask.last |= ((mask.adsr[op] ? 1 : 0) << bit++);
|
||||
}
|
||||
mask.freq_fb = (e.flags & (OPM_FNUM | OPM_BLOCK | OPM_FEEDBACK));
|
||||
mask.last |= ((mask.freq_fb ? 1 : 0) << bit++);
|
||||
//mask.key = (e.flags & (OPM_FNUM | OPM_BLOCK | OPM_FEEDBACK | OPM_KEY)) == (OPM_BLOCK | OPM_KEY);
|
||||
//mask.last |= ((mask.key ? 1 : 0) << bit++);
|
||||
if (i < s.records.size() - 1) mask.last |= (1 << bit++); // prevent non-last events from emitting eof token
|
||||
|
||||
// output tokens
|
||||
for (int op = 0; op < 2; op++) {
|
||||
// mult/tl/waveform
|
||||
if (mask.last & 1) {
|
||||
s.rawdata.push_back(
|
||||
OPM_SET_MULT_WAVE_TL | (mask.op[op] >> 0) | (OPM_CMD80_SELECT_OPERATOR * op) |
|
||||
(mask.last == 1 ? OPM_CMD80_END_OF_FRAME : 0)
|
||||
);
|
||||
if (mask.op[op] & OPM_MULT) s.rawdata.push_back(e.op[op].mult);
|
||||
if (mask.op[op] & OPM_KSL_TL) s.rawdata.push_back(e.op[op].ksl_tl);
|
||||
if (mask.op[op] & OPM_WAVEFORM) s.rawdata.push_back(e.op[op].waveform);
|
||||
}
|
||||
mask.last >>= 1;
|
||||
|
||||
// ad/sr
|
||||
if (mask.last & 1) {
|
||||
s.rawdata.push_back(
|
||||
OPM_SET_ADSR | (mask.adsr[op] >> 3) | (OPM_CMDA0_SELECT_OPERATOR * op) |
|
||||
(mask.last == 1 ? OPM_CMDA0_END_OF_FRAME : 0)
|
||||
);
|
||||
if (mask.adsr[op] & OPM_AD) s.rawdata.push_back(e.op[op].ad);
|
||||
if (mask.adsr[op] & OPM_SR) s.rawdata.push_back(e.op[op].sr);
|
||||
}
|
||||
mask.last >>= 1;
|
||||
}
|
||||
// freq/feedback
|
||||
if (mask.last & 1) {
|
||||
s.rawdata.push_back(
|
||||
OPM_SET_FREQ_FB | (mask.freq_fb >> 10) |
|
||||
(mask.last == 1 ? OPM_CMDB0_END_OF_FRAME : 0)
|
||||
);
|
||||
if (mask.freq_fb & OPM_FEEDBACK) s.rawdata.push_back(e.feedback);
|
||||
if (mask.freq_fb & OPM_FNUM) s.rawdata.push_back(e.fnum);
|
||||
if (mask.freq_fb & OPM_BLOCK) s.rawdata.push_back(e.block);
|
||||
}
|
||||
mask.last >>= 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue