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:
@@ -51,9 +51,21 @@
|
|||||||
#include <86box/device.h>
|
#include <86box/device.h>
|
||||||
#include <86box/snd_opl.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. */
|
/* Quirk: Some FM channels are output one sample later on the left side than the right. */
|
||||||
#ifndef OPL_QUIRK_CHANNELSAMPLEDELAY
|
#ifndef OPL_QUIRK_CHANNELSAMPLEDELAY
|
||||||
#define OPL_QUIRK_CHANNELSAMPLEDELAY 1
|
#define OPL_QUIRK_CHANNELSAMPLEDELAY (!OPL_ENABLE_STEREOEXT)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WRBUF_SIZE 1024
|
#define WRBUF_SIZE 1024
|
||||||
@@ -124,6 +136,10 @@ typedef struct chan {
|
|||||||
struct chan *pair;
|
struct chan *pair;
|
||||||
struct chip *dev;
|
struct chip *dev;
|
||||||
int16_t *out[4];
|
int16_t *out[4];
|
||||||
|
#if OPL_ENABLE_STEREOEXT
|
||||||
|
int32_t leftpan;
|
||||||
|
int32_t rightpan;
|
||||||
|
#endif
|
||||||
uint8_t chtype;
|
uint8_t chtype;
|
||||||
uint16_t f_num;
|
uint16_t f_num;
|
||||||
uint8_t block;
|
uint8_t block;
|
||||||
@@ -168,6 +184,10 @@ typedef struct chip {
|
|||||||
uint8_t rm_tc_bit3;
|
uint8_t rm_tc_bit3;
|
||||||
uint8_t rm_tc_bit5;
|
uint8_t rm_tc_bit5;
|
||||||
|
|
||||||
|
#if OPL_ENABLE_STEREOEXT
|
||||||
|
uint8_t stereoext;
|
||||||
|
#endif
|
||||||
|
|
||||||
// OPL3L
|
// OPL3L
|
||||||
int32_t rateratio;
|
int32_t rateratio;
|
||||||
int32_t samplecnt;
|
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
|
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
|
// Envelope generator
|
||||||
typedef int16_t (*env_sinfunc)(uint16_t phase, uint16_t envelope);
|
typedef int16_t (*env_sinfunc)(uint16_t phase, uint16_t envelope);
|
||||||
typedef void (*env_genfunc)(slot_t *slot);
|
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;
|
ch->chb = ((data >> 5) & 0x01) ? ~0 : 0;
|
||||||
} else
|
} else
|
||||||
ch->cha = ch->chb = (uint16_t) ~0;
|
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
|
static void
|
||||||
channel_key_on(chan_t *ch)
|
channel_key_on(chan_t *ch)
|
||||||
{
|
{
|
||||||
@@ -1162,6 +1209,9 @@ nuked_write_reg(void *priv, uint16_t reg, uint8_t val)
|
|||||||
|
|
||||||
case 0x05:
|
case 0x05:
|
||||||
dev->newm = val & 0x01;
|
dev->newm = val & 0x01;
|
||||||
|
#if OPL_ENABLE_STEREOEXT
|
||||||
|
dev->stereoext = (val >> 1) & 0x01;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
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);
|
channel_write_c0(&dev->chan[9 * high + (regm & 0x0f)], val);
|
||||||
break;
|
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 0xe0:
|
||||||
case 0xf0:
|
case 0xf0:
|
||||||
if (ad_slot[regm & 0x1f] >= 0)
|
if (ad_slot[regm & 0x1f] >= 0)
|
||||||
@@ -1305,7 +1362,11 @@ nuked_generate(void *priv, int32_t *bufp)
|
|||||||
ch = &dev->chan[i];
|
ch = &dev->chan[i];
|
||||||
out = ch->out;
|
out = ch->out;
|
||||||
accm = *out[0] + *out[1] + *out[2] + *out[3];
|
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);
|
mix += (int16_t) (accm & ch->cha);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->mixbuff[0] = mix;
|
dev->mixbuff[0] = mix;
|
||||||
@@ -1328,7 +1389,11 @@ nuked_generate(void *priv, int32_t *bufp)
|
|||||||
ch = &dev->chan[i];
|
ch = &dev->chan[i];
|
||||||
out = ch->out;
|
out = ch->out;
|
||||||
accm = *out[0] + *out[1] + *out[2] + *out[3];
|
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);
|
mix += (int16_t) (accm & ch->chb);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->mixbuff[1] = mix;
|
dev->mixbuff[1] = mix;
|
||||||
@@ -1468,6 +1533,10 @@ nuked_init(nuked_t *dev, uint32_t samplerate)
|
|||||||
ch->chtype = ch_2op;
|
ch->chtype = ch_2op;
|
||||||
ch->cha = 0xffff;
|
ch->cha = 0xffff;
|
||||||
ch->chb = 0xffff;
|
ch->chb = 0xffff;
|
||||||
|
#if OPL_ENABLE_STEREOEXT
|
||||||
|
ch->leftpan = 0x10000;
|
||||||
|
ch->rightpan = 0x10000;
|
||||||
|
#endif
|
||||||
ch->ch_num = i;
|
ch->ch_num = i;
|
||||||
|
|
||||||
channel_setup_alg(ch);
|
channel_setup_alg(ch);
|
||||||
@@ -1477,6 +1546,15 @@ nuked_init(nuked_t *dev, uint32_t samplerate)
|
|||||||
dev->rateratio = (samplerate << RSM_FRAC) / 49716;
|
dev->rateratio = (samplerate << RSM_FRAC) / 49716;
|
||||||
dev->tremoloshift = 4;
|
dev->tremoloshift = 4;
|
||||||
dev->vibshift = 1;
|
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
|
static void
|
||||||
|
Reference in New Issue
Block a user