OPL: quad output

now that we have this new dispatch output method
This commit is contained in:
tildearrow 2023-01-04 18:30:29 -05:00
parent 6c834524aa
commit fd9b1dd0f5
3 changed files with 118 additions and 33 deletions

105
extern/opl/opl3.c vendored
View File

@ -946,10 +946,8 @@ static void OPL3_ChannelSetupAlg(opl3_channel *channel)
}
}
static void OPL3_ChannelWriteC0(opl3_channel *channel, uint8_t data)
static void OPL3_ChannelUpdateAlg(opl3_channel *channel)
{
channel->fb = (data & 0x0e) >> 1;
channel->con = data & 0x01;
channel->alg = channel->con;
if (channel->chip->newm)
{
@ -974,14 +972,25 @@ static void OPL3_ChannelWriteC0(opl3_channel *channel, uint8_t data)
{
OPL3_ChannelSetupAlg(channel);
}
}
static void OPL3_ChannelWriteC0(opl3_channel *channel, uint8_t data)
{
channel->fb = (data & 0x0e) >> 1;
channel->con = data & 0x01;
OPL3_ChannelUpdateAlg(channel);
if (channel->chip->newm)
{
channel->cha = ((data >> 4) & 0x01) ? ~0 : 0;
channel->chb = ((data >> 5) & 0x01) ? ~0 : 0;
channel->chc = ((data >> 6) & 0x01) ? ~0 : 0;
channel->chd = ((data >> 7) & 0x01) ? ~0 : 0;
}
else
{
channel->cha = channel->chb = (uint16_t)~0;
// TODO: Verify on real chip if DAC2 output is disabled in compat mode
channel->chc = channel->chd = 0;
}
#if OPL_ENABLE_STEREOEXT
if (!channel->chip->stereoext)
@ -1066,11 +1075,14 @@ static void OPL3_ChannelSet4Op(opl3_chip *chip, uint8_t data)
{
chip->channel[chnum].chtype = ch_4op;
chip->channel[chnum + 3].chtype = ch_4op2;
OPL3_ChannelUpdateAlg(&chip->channel[chnum]);
}
else
{
chip->channel[chnum].chtype = ch_2op;
chip->channel[chnum + 3].chtype = ch_2op;
OPL3_ChannelUpdateAlg(&chip->channel[chnum]);
OPL3_ChannelUpdateAlg(&chip->channel[chnum+3]);
}
}
}
@ -1096,17 +1108,18 @@ static void OPL3_ProcessSlot(opl3_slot *slot)
OPL3_SlotGenerate(slot);
}
void OPL3_Generate(opl3_chip *chip, int16_t *buf)
inline void OPL3_Generate4Ch(opl3_chip *chip, int16_t *buf4)
{
opl3_channel *channel;
opl3_writebuf *writebuf;
int16_t **out;
int32_t mix;
int32_t mix[2];
uint8_t ii;
int16_t accm;
uint8_t shift = 0;
buf[1] = OPL3_ClipSample(chip->mixbuff[1]);
buf4[1] = OPL3_ClipSample(chip->mixbuff[1]);
buf4[3] = OPL3_ClipSample(chip->mixbuff[3]);
#if OPL_QUIRK_CHANNELSAMPLEDELAY
for (ii = 0; ii < 15; ii++)
@ -1117,7 +1130,7 @@ void OPL3_Generate(opl3_chip *chip, int16_t *buf)
OPL3_ProcessSlot(&chip->slot[ii]);
}
mix = 0;
mix[0] = mix[1] = 0;
for (ii = 0; ii < 18; ii++)
{
channel = &chip->channel[ii];
@ -1125,12 +1138,14 @@ void OPL3_Generate(opl3_chip *chip, int16_t *buf)
out = channel->out;
accm = *out[0] + *out[1] + *out[2] + *out[3];
#if OPL_ENABLE_STEREOEXT
mix += (int16_t)((accm * channel->leftpan) >> 16);
mix[0] += (int16_t)((accm * channel->leftpan) >> 16);
#else
mix += (int16_t)(accm & channel->cha);
#endif
mix[0] += (int16_t)(accm & channel->cha);
#endif
mix[1] += (int16_t)(accm & channel->chc);
}
chip->mixbuff[0] = mix;
chip->mixbuff[0] = mix[0];
chip->mixbuff[2] = mix[1];
#if OPL_QUIRK_CHANNELSAMPLEDELAY
for (ii = 15; ii < 18; ii++)
@ -1139,7 +1154,8 @@ void OPL3_Generate(opl3_chip *chip, int16_t *buf)
}
#endif
buf[0] = OPL3_ClipSample(chip->mixbuff[0]);
buf4[0] = OPL3_ClipSample(chip->mixbuff[0]);
buf4[2] = OPL3_ClipSample(chip->mixbuff[2]);
#if OPL_QUIRK_CHANNELSAMPLEDELAY
for (ii = 18; ii < 33; ii++)
@ -1148,7 +1164,7 @@ void OPL3_Generate(opl3_chip *chip, int16_t *buf)
}
#endif
mix = 0;
mix[0] = mix[1] = 0;
for (ii = 0; ii < 18; ii++)
{
channel = &chip->channel[ii];
@ -1156,12 +1172,14 @@ void OPL3_Generate(opl3_chip *chip, int16_t *buf)
out = channel->out;
accm = *out[0] + *out[1] + *out[2] + *out[3];
#if OPL_ENABLE_STEREOEXT
mix += (int16_t)((accm * channel->rightpan) >> 16);
mix[0] += (int16_t)((accm * channel->rightpan) >> 16);
#else
mix += (int16_t)(accm & channel->chb);
#endif
mix[0] += (int16_t)(accm & channel->chb);
#endif
mix[1] += (int16_t)(accm & channel->chd);
}
chip->mixbuff[1] = mix;
chip->mixbuff[1] = mix[0];
chip->mixbuff[3] = mix[1];
#if OPL_QUIRK_CHANNELSAMPLEDELAY
for (ii = 33; ii < 36; ii++)
@ -1236,22 +1254,44 @@ void OPL3_Generate(opl3_chip *chip, int16_t *buf)
chip->writebuf_samplecnt++;
}
void OPL3_GenerateResampled(opl3_chip *chip, int16_t *buf)
void OPL3_Generate(opl3_chip *chip, int16_t *buf)
{
int16_t samples[4];
OPL3_Generate4Ch(chip, samples);
buf[0] = samples[0];
buf[1] = samples[1];
}
void OPL3_Generate4ChResampled(opl3_chip *chip, int16_t *buf4)
{
while (chip->samplecnt >= chip->rateratio)
{
chip->oldsamples[0] = chip->samples[0];
chip->oldsamples[1] = chip->samples[1];
OPL3_Generate(chip, chip->samples);
chip->oldsamples[2] = chip->samples[2];
chip->oldsamples[3] = chip->samples[3];
OPL3_Generate4Ch(chip, chip->samples);
chip->samplecnt -= chip->rateratio;
}
buf[0] = (int16_t)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt)
+ chip->samples[0] * chip->samplecnt) / chip->rateratio);
buf[1] = (int16_t)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt)
+ chip->samples[1] * chip->samplecnt) / chip->rateratio);
buf4[0] = (int16_t)((chip->oldsamples[0] * (chip->rateratio - chip->samplecnt)
+ chip->samples[0] * chip->samplecnt) / chip->rateratio);
buf4[1] = (int16_t)((chip->oldsamples[1] * (chip->rateratio - chip->samplecnt)
+ chip->samples[1] * chip->samplecnt) / chip->rateratio);
buf4[2] = (int16_t)((chip->oldsamples[2] * (chip->rateratio - chip->samplecnt)
+ chip->samples[2] * chip->samplecnt) / chip->rateratio);
buf4[3] = (int16_t)((chip->oldsamples[3] * (chip->rateratio - chip->samplecnt)
+ chip->samples[3] * chip->samplecnt) / chip->rateratio);
chip->samplecnt += 1 << RSM_FRAC;
}
void OPL3_GenerateResampled(opl3_chip *chip, int16_t *buf)
{
int16_t samples[4];
OPL3_Generate4ChResampled(chip, samples);
buf[0] = samples[0];
buf[1] = samples[1];
}
void OPL3_Reset(opl3_chip *chip, uint32_t samplerate)
{
opl3_slot *slot;
@ -1464,9 +1504,26 @@ void OPL3_WriteRegBuffered(opl3_chip *chip, uint16_t reg, uint8_t v)
chip->writebuf_last = (writebuf_last + 1) % OPL_WRITEBUF_SIZE;
}
void OPL3_Generate4ChStream(opl3_chip *chip, int16_t *sndptr1, int16_t *sndptr2, uint32_t numsamples)
{
uint_fast32_t i;
int16_t samples[4];
for(i = 0; i < numsamples; i++)
{
OPL3_Generate4ChResampled(chip, samples);
sndptr1[0] = samples[0];
sndptr1[1] = samples[1];
sndptr2[0] = samples[2];
sndptr2[1] = samples[3];
sndptr1 += 2;
sndptr2 += 2;
}
}
void OPL3_GenerateStream(opl3_chip *chip, int16_t *sndptr, uint32_t numsamples)
{
uint32_t i;
uint_fast32_t i;
for(i = 0; i < numsamples; i++)
{

11
extern/opl/opl3.h vendored
View File

@ -101,6 +101,7 @@ struct _opl3_channel {
uint8_t alg;
uint8_t ksv;
uint16_t cha, chb;
uint16_t chc, chd;
uint8_t ch_num;
uint8_t muted;
};
@ -129,7 +130,7 @@ struct _opl3_chip {
uint8_t tremoloshift;
uint32_t noise;
int16_t zeromod;
int32_t mixbuff[2];
int32_t mixbuff[4];
uint8_t rm_hh_bit2;
uint8_t rm_hh_bit3;
uint8_t rm_hh_bit7;
@ -144,8 +145,8 @@ struct _opl3_chip {
/* OPL3L */
int32_t rateratio;
int32_t samplecnt;
int16_t oldsamples[2];
int16_t samples[2];
int16_t oldsamples[4];
int16_t samples[4];
uint64_t writebuf_samplecnt;
uint32_t writebuf_cur;
@ -161,6 +162,10 @@ void OPL3_WriteReg(opl3_chip *chip, uint16_t reg, uint8_t v);
void OPL3_WriteRegBuffered(opl3_chip *chip, uint16_t reg, uint8_t v);
void OPL3_GenerateStream(opl3_chip *chip, int16_t *sndptr, uint32_t numsamples);
void OPL3_Generate4Ch(opl3_chip *chip, int16_t *buf4);
void OPL3_Generate4ChResampled(opl3_chip *chip, int16_t *buf4);
void OPL3_Generate4ChStream(opl3_chip *chip, int16_t *sndptr1, int16_t *sndptr2, uint32_t numsamples);
#ifdef __cplusplus
}
#endif

View File

@ -160,12 +160,12 @@ const int orderedOpsL[4]={
#define ADDR_LR_FB_ALG 0xc0
void DivPlatformOPL::acquire_nuked(short** buf, size_t len) {
static short o[2];
static int os[2];
static short o[4];
static int os[4];
static ymfm::ymfm_output<2> aOut;
for (size_t h=0; h<len; h++) {
os[0]=0; os[1]=0;
os[0]=0; os[1]=0; os[2]=0; os[3]=0;
if (!writes.empty() && --delay<0) {
delay=1;
QueuedWrite& w=writes.front();
@ -194,11 +194,14 @@ void DivPlatformOPL::acquire_nuked(short** buf, size_t len) {
}
if (downsample) {
OPL3_GenerateResampled(&fm,o);
OPL3_Generate4ChResampled(&fm,o);
} else {
OPL3_Generate(&fm,o);
OPL3_Generate4Ch(&fm,o);
}
os[0]+=o[0]; os[1]+=o[1];
os[0]+=o[0];
os[1]+=o[1];
os[2]+=o[2];
os[3]+=o[3];
if (adpcmChan>=0) {
adpcmB->clock();
@ -225,6 +228,12 @@ void DivPlatformOPL::acquire_nuked(short** buf, size_t len) {
if (fm.channel[i].out[1]!=NULL) {
oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[1];
}
if (fm.channel[i].out[2]!=NULL) {
oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[2];
}
if (fm.channel[i].out[3]!=NULL) {
oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[3];
}
oscBuf[i]->data[oscBuf[i]->needle]<<=1;
oscBuf[i]->needle++;
}
@ -244,6 +253,12 @@ void DivPlatformOPL::acquire_nuked(short** buf, size_t len) {
if (fm.channel[i].out[1]!=NULL) {
oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[1];
}
if (fm.channel[i].out[2]!=NULL) {
oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[2];
}
if (fm.channel[i].out[3]!=NULL) {
oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[3];
}
oscBuf[i]->data[oscBuf[i]->needle]<<=1;
oscBuf[i]->needle++;
}
@ -254,10 +269,18 @@ void DivPlatformOPL::acquire_nuked(short** buf, size_t len) {
if (os[1]<-32768) os[1]=-32768;
if (os[1]>32767) os[1]=32767;
if (os[2]<-32768) os[2]=-32768;
if (os[2]>32767) os[2]=32767;
if (os[3]<-32768) os[3]=-32768;
if (os[3]>32767) os[3]=32767;
buf[0][h]=os[0];
if (oplType==3 || oplType==759) {
buf[1][h]=os[1];
buf[2][h]=os[2];
buf[3][h]=os[3];
}
}
}