Add stereo extension

Co-Authored-By: Evan Ramos <1585791+hendricks266@users.noreply.github.com>
Co-Authored-By: nukeykt <alexeytf2@gmail.com>
This commit is contained in:
Jasmine Iwanek
2024-07-10 02:23:19 -04:00
parent 87cdb6ac28
commit 996e5cc784

View File

@@ -51,9 +51,21 @@
#include <86box/device.h>
#include <86box/snd_opl.h>
#ifndef OPL_ENABLE_STEREOEXT
#define OPL_ENABLE_STEREOEXT 0
#endif
#if OPL_ENABLE_STEREOEXT
#ifndef _USE_MATH_DEFINES
#define _USE_MATH_DEFINES 1
#endif
#include <math.h>
#endif
/* Quirk: Some FM channels are output one sample later on the left side than the right. */
#ifndef OPL_QUIRK_CHANNELSAMPLEDELAY
#define OPL_QUIRK_CHANNELSAMPLEDELAY 1
#define OPL_QUIRK_CHANNELSAMPLEDELAY (!OPL_ENABLE_STEREOEXT)
#endif
#define WRBUF_SIZE 1024
@@ -124,6 +136,10 @@ typedef struct chan {
struct chan *pair;
struct chip *dev;
int16_t *out[4];
#if OPL_ENABLE_STEREOEXT
int32_t leftpan;
int32_t rightpan;
#endif
uint8_t chtype;
uint16_t f_num;
uint8_t block;
@@ -168,6 +184,10 @@ typedef struct chip {
uint8_t rm_tc_bit3;
uint8_t rm_tc_bit5;
#if OPL_ENABLE_STEREOEXT
uint8_t stereoext;
#endif
// OPL3L
int32_t rateratio;
int32_t samplecnt;
@@ -343,6 +363,15 @@ static const uint8_t ch_slot[18] = {
0, 1, 2, 6, 7, 8, 12, 13, 14, 18, 19, 20, 24, 25, 26, 30, 31, 32
};
#if OPL_ENABLE_STEREOEXT
/*
stereo extension panning table
*/
static int32_t panpot_lut[256];
static uint8_t panpot_lut_build = 0;
#endif
// Envelope generator
typedef int16_t (*env_sinfunc)(uint16_t phase, uint16_t envelope);
typedef void (*env_genfunc)(slot_t *slot);
@@ -1071,8 +1100,26 @@ channel_write_c0(chan_t *ch, uint8_t data)
ch->chb = ((data >> 5) & 0x01) ? ~0 : 0;
} else
ch->cha = ch->chb = (uint16_t) ~0;
#if OPL_ENABLE_STEREOEXT
if (!ch->dev->stereoext) {
ch->leftpan = ch->cha << 16;
ch->rightpan = ch->chb << 16;
}
#endif
}
#if OPL_ENABLE_STEREOEXT
static void
channel_write_d0(chan_t *ch, uint8_t data)
{
if (ch->dev->stereoext) {
ch->leftpan = panpot_lut[data ^ 0xff];
ch->rightpan = panpot_lut[data];
}
}
#endif
static void
channel_key_on(chan_t *ch)
{
@@ -1162,6 +1209,9 @@ nuked_write_reg(void *priv, uint16_t reg, uint8_t val)
case 0x05:
dev->newm = val & 0x01;
#if OPL_ENABLE_STEREOEXT
dev->stereoext = (val >> 1) & 0x01;
#endif
break;
default:
@@ -1227,6 +1277,13 @@ nuked_write_reg(void *priv, uint16_t reg, uint8_t val)
channel_write_c0(&dev->chan[9 * high + (regm & 0x0f)], val);
break;
#if OPL_ENABLE_STEREOEXT
case 0xd0:
if ((regm & 0x0f) < 9)
channel_write_d0(&dev->chan[9 * high + (regm & 0x0f)], val);
break;
#endif
case 0xe0:
case 0xf0:
if (ad_slot[regm & 0x1f] >= 0)
@@ -1305,7 +1362,11 @@ nuked_generate(void *priv, int32_t *bufp)
ch = &dev->chan[i];
out = ch->out;
accm = *out[0] + *out[1] + *out[2] + *out[3];
#if OPL_ENABLE_STEREOEXT
mix += (int16_t)((accm * ch->leftpan) >> 16);
#else
mix += (int16_t) (accm & ch->cha);
#endif
}
dev->mixbuff[0] = mix;
@@ -1328,7 +1389,11 @@ nuked_generate(void *priv, int32_t *bufp)
ch = &dev->chan[i];
out = ch->out;
accm = *out[0] + *out[1] + *out[2] + *out[3];
#if OPL_ENABLE_STEREOEXT
mix += (int16_t)((accm * ch->leftpan) >> 16);
#else
mix += (int16_t) (accm & ch->chb);
#endif
}
dev->mixbuff[1] = mix;
@@ -1468,6 +1533,10 @@ nuked_init(nuked_t *dev, uint32_t samplerate)
ch->chtype = ch_2op;
ch->cha = 0xffff;
ch->chb = 0xffff;
#if OPL_ENABLE_STEREOEXT
ch->leftpan = 0x10000;
ch->rightpan = 0x10000;
#endif
ch->ch_num = i;
channel_setup_alg(ch);
@@ -1477,6 +1546,15 @@ nuked_init(nuked_t *dev, uint32_t samplerate)
dev->rateratio = (samplerate << RSM_FRAC) / 49716;
dev->tremoloshift = 4;
dev->vibshift = 1;
#if OPL_ENABLE_STEREOEXT
if (!panpot_lut_build) {
for (int32_t i = 0; i < 256; i++)
panpot_lut[i] = (int32_t)(sin(i * M_PI / 512.0) * 65536.0);
panpot_lut_build = 1;
}
#endif
}
static void