halve clock speed, add ring mod and hard sync

This commit is contained in:
LTVA1 2024-08-02 11:13:04 +03:00
parent d0a990dcfa
commit 365062ac21
7 changed files with 196 additions and 59 deletions

View file

@ -88,7 +88,7 @@ void DivPlatformSID3::acquire(short** buf, size_t len)
buf[0][i]=sid3->output_l; buf[0][i]=sid3->output_l;
buf[1][i]=sid3->output_r; buf[1][i]=sid3->output_r;
if (++writeOscBuf>=16) if (++writeOscBuf>=8)
{ {
writeOscBuf=0; writeOscBuf=0;
@ -100,6 +100,18 @@ void DivPlatformSID3::acquire(short** buf, size_t len)
} }
} }
void DivPlatformSID3::updateFlags(int channel, bool gate)
{
rWrite(SID3_REGISTER_FLAGS + channel * SID3_REGISTERS_PER_CHANNEL, (gate ? 1 : 0) |
(chan[channel].ring ? SID3_CHAN_ENABLE_RING_MOD : 0) |
(chan[channel].sync ? SID3_CHAN_ENABLE_HARD_SYNC : 0) |
(chan[channel].phase ? SID3_CHAN_ENABLE_PHASE_MOD : 0) |
(chan[channel].phaseReset ? SID3_CHAN_PHASE_RESET : 0) |
(chan[channel].envReset ? SID3_CHAN_ENV_RESET : 0) |
(chan[channel].phaseResetNoise ? SID3_CHAN_NOISE_PHASE_RESET : 0) |
(chan[channel].oneBitNoise ? SID3_CHAN_1_BIT_NOISE : 0));
}
void DivPlatformSID3::updateFilter(int channel) void DivPlatformSID3::updateFilter(int channel)
{ {
//rWrite(0x15 + 3 * channel,(chan[channel].filtCut&15) | ((chan[channel].filtControl & 7) << 4) | (chan[channel].filter << 7)); //rWrite(0x15 + 3 * channel,(chan[channel].filtCut&15) | ((chan[channel].filtControl & 7) << 4) | (chan[channel].filter << 7));
@ -109,24 +121,24 @@ void DivPlatformSID3::updateFilter(int channel)
void DivPlatformSID3::updateFreq(int channel) void DivPlatformSID3::updateFreq(int channel)
{ {
rWrite(10 + channel*SID3_REGISTERS_PER_CHANNEL,(chan[channel].freq >> 16) & 0xff); rWrite(SID3_REGISTER_FREQ_HIGH + channel*SID3_REGISTERS_PER_CHANNEL,(chan[channel].freq >> 16) & 0xff);
rWrite(11 + channel*SID3_REGISTERS_PER_CHANNEL,(chan[channel].freq >> 8) & 0xff); rWrite(SID3_REGISTER_FREQ_MID + channel*SID3_REGISTERS_PER_CHANNEL,(chan[channel].freq >> 8) & 0xff);
rWrite(12 + channel*SID3_REGISTERS_PER_CHANNEL,chan[channel].freq & 0xff); rWrite(SID3_REGISTER_FREQ_LOW + channel*SID3_REGISTERS_PER_CHANNEL,chan[channel].freq & 0xff);
} }
void DivPlatformSID3::updateDuty(int channel) void DivPlatformSID3::updateDuty(int channel)
{ {
rWrite(7 + channel*SID3_REGISTERS_PER_CHANNEL,(chan[channel].duty >> 8) & 0xff); rWrite(SID3_REGISTER_PW_HIGH + channel*SID3_REGISTERS_PER_CHANNEL,(chan[channel].duty >> 8) & 0xff);
rWrite(8 + channel*SID3_REGISTERS_PER_CHANNEL,chan[channel].duty & 0xff); rWrite(SID3_REGISTER_PW_LOW + channel*SID3_REGISTERS_PER_CHANNEL,chan[channel].duty & 0xff);
} }
void DivPlatformSID3::updateEnvelope(int channel) void DivPlatformSID3::updateEnvelope(int channel)
{ {
rWrite(1 + channel * SID3_REGISTERS_PER_CHANNEL, chan[channel].attack); //attack rWrite(SID3_REGISTER_ADSR_A + channel * SID3_REGISTERS_PER_CHANNEL, chan[channel].attack); //attack
rWrite(2 + channel * SID3_REGISTERS_PER_CHANNEL, chan[channel].decay); //decay rWrite(SID3_REGISTER_ADSR_D + channel * SID3_REGISTERS_PER_CHANNEL, chan[channel].decay); //decay
rWrite(3 + channel * SID3_REGISTERS_PER_CHANNEL, chan[channel].sustain); //sustain rWrite(SID3_REGISTER_ADSR_S + channel * SID3_REGISTERS_PER_CHANNEL, chan[channel].sustain); //sustain
rWrite(4 + channel * SID3_REGISTERS_PER_CHANNEL, chan[channel].sr); //sr rWrite(SID3_REGISTER_ADSR_SR + channel * SID3_REGISTERS_PER_CHANNEL, chan[channel].sr); //sr
rWrite(5 + channel * SID3_REGISTERS_PER_CHANNEL, chan[channel].release); //release rWrite(SID3_REGISTER_ADSR_R + channel * SID3_REGISTERS_PER_CHANNEL, chan[channel].release); //release
} }
void DivPlatformSID3::tick(bool sysTick) void DivPlatformSID3::tick(bool sysTick)
@ -149,23 +161,26 @@ void DivPlatformSID3::tick(bool sysTick)
if (chan[i].keyOn) if (chan[i].keyOn)
{ {
rWrite(6 + i * SID3_REGISTERS_PER_CHANNEL, chan[i].wave); //waveform rWrite(SID3_REGISTER_WAVEFORM + i * SID3_REGISTERS_PER_CHANNEL, chan[i].wave); //waveform
rWrite(9 + i * SID3_REGISTERS_PER_CHANNEL, chan[i].special_wave); //special wave rWrite(SID3_REGISTER_SPECIAL_WAVE + i * SID3_REGISTERS_PER_CHANNEL, chan[i].special_wave); //special wave
rWrite(13 + i * SID3_REGISTERS_PER_CHANNEL, chan[i].outVol); //set volume rWrite(SID3_REGISTER_ADSR_VOL + i * SID3_REGISTERS_PER_CHANNEL, chan[i].outVol); //set volume
rWrite(14 + i * SID3_REGISTERS_PER_CHANNEL, chan[i].mix_mode); //mixmode rWrite(SID3_REGISTER_MIXMODE + i * SID3_REGISTERS_PER_CHANNEL, chan[i].mix_mode); //mixmode
rWrite(SID3_REGISTER_RING_MOD_SRC + i * SID3_REGISTERS_PER_CHANNEL, chan[i].ringSrc); //ring mod source
rWrite(SID3_REGISTER_SYNC_SRC + i * SID3_REGISTERS_PER_CHANNEL, chan[i].syncSrc); //hard sync source
updateEnvelope(i); updateEnvelope(i);
//chan[i].duty = 0x1000; //chan[i].duty = 0x1000;
updateDuty(i); updateDuty(i);
rWrite(i * SID3_REGISTERS_PER_CHANNEL, 0 | (chan[i].oneBitNoise ? SID3_CHAN_1_BIT_NOISE : 0)); //gate off TODO: make it properly? updateFlags(i, false); //gate off TODO: make it properly?
rWrite(i * SID3_REGISTERS_PER_CHANNEL, SID3_CHAN_ENABLE_GATE | (chan[i].oneBitNoise ? SID3_CHAN_1_BIT_NOISE : 0)); //gate on updateFlags(i, true); //gate on
} }
if (chan[i].keyOff) if (chan[i].keyOff)
{ {
rWrite(i * SID3_REGISTERS_PER_CHANNEL, 0 | (chan[i].oneBitNoise ? SID3_CHAN_1_BIT_NOISE : 0)); updateFlags(i, false); //gate off
} }
if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq<0) chan[i].freq=0;
@ -226,9 +241,17 @@ int DivPlatformSID3::dispatch(DivCommand c) {
chan[c.chan].duty=ins->c64.duty; chan[c.chan].duty=ins->c64.duty;
chan[c.chan].sync = ins->c64.oscSync;
chan[c.chan].ring = ins->c64.ringMod;
chan[c.chan].phase = ins->sid3.phase_mod;
chan[c.chan].oneBitNoise = ins->sid3.oneBitNoise;
chan[c.chan].oneBitNoise = ins->sid3.oneBitNoise;
chan[c.chan].oneBitNoise = ins->sid3.oneBitNoise; chan[c.chan].oneBitNoise = ins->sid3.oneBitNoise;
chan[c.chan].mix_mode = ins->sid2.mixMode; chan[c.chan].mix_mode = ins->sid2.mixMode;
chan[c.chan].ringSrc = ins->sid3.ring_mod_source;
chan[c.chan].syncSrc = ins->sid3.sync_source;
} }
if (chan[c.chan].insChanged || chan[c.chan].resetFilter) { if (chan[c.chan].insChanged || chan[c.chan].resetFilter) {
/*chan[c.chan].filter=ins->c64.toFilter; /*chan[c.chan].filter=ins->c64.toFilter;
@ -446,22 +469,11 @@ void DivPlatformSID3::poke(std::vector<DivRegWrite>& wlist) {
} }
void DivPlatformSID3::setFlags(const DivConfig& flags) { void DivPlatformSID3::setFlags(const DivConfig& flags) {
switch (flags.getInt("clockSel",0)) { chipClock=500000;
case 0x0: // NTSC C64
chipClock=COLOR_NTSC*2.0/7.0;
break;
case 0x1: // PAL C64
chipClock=COLOR_PAL*2.0/9.0;
break;
case 0x2: // SSI 2001
default:
chipClock=14318180.0/16.0;
break;
}
CHECK_CUSTOM_CLOCK; CHECK_CUSTOM_CLOCK;
rate=chipClock; rate=chipClock;
for (int i=0; i<SID3_NUM_CHANNELS; i++) { for (int i=0; i<SID3_NUM_CHANNELS; i++) {
oscBuf[i]->rate=rate/16; oscBuf[i]->rate=rate/8;
} }
} }

View file

@ -28,11 +28,13 @@ class DivPlatformSID3: public DivDispatch {
struct Channel: public SharedChannel<signed short> { struct Channel: public SharedChannel<signed short> {
int prevFreq; int prevFreq;
unsigned char wave, special_wave, attack, decay, sustain, sr, release; unsigned char wave, special_wave, attack, decay, sustain, sr, release;
short duty; unsigned short duty;
bool resetMask, resetFilter, resetDuty, gate, ring, sync, phase, oneBitNoise; bool resetMask, resetFilter, resetDuty, gate, ring, sync, phase, oneBitNoise;
bool phaseReset, envReset, phaseResetNoise;
unsigned char vol; unsigned char vol;
unsigned char noise_mode; unsigned char noise_mode;
unsigned char mix_mode; unsigned char mix_mode;
unsigned char ringSrc, syncSrc, phaseSrc;
int filtCut; int filtCut;
Channel(): Channel():
SharedChannel<signed short>(SID3_MAX_VOL), SharedChannel<signed short>(SID3_MAX_VOL),
@ -53,9 +55,15 @@ class DivPlatformSID3: public DivDispatch {
sync(false), sync(false),
phase(false), phase(false),
oneBitNoise(false), oneBitNoise(false),
phaseReset(false),
envReset(false),
phaseResetNoise(false),
vol(SID3_MAX_VOL), vol(SID3_MAX_VOL),
noise_mode(0), noise_mode(0),
mix_mode(0), mix_mode(0),
ringSrc(0),
syncSrc(0),
phaseSrc(0),
filtCut(0) {} filtCut(0) {}
}; };
Channel chan[SID3_NUM_CHANNELS]; Channel chan[SID3_NUM_CHANNELS];
@ -78,6 +86,7 @@ class DivPlatformSID3: public DivDispatch {
friend void putDispatchChip(void*,int); friend void putDispatchChip(void*,int);
friend void putDispatchChan(void*,int,int); friend void putDispatchChan(void*,int,int);
void updateFlags(int channel, bool gate);
void updateFilter(int channel); void updateFilter(int channel);
void updateFreq(int channel); void updateFreq(int channel);
void updateDuty(int channel); void updateDuty(int channel);

View file

@ -10,8 +10,10 @@ enum State { ATTACK, DECAY, SUSTAIN, RELEASE }; //for envelope
# define M_PI 3.14159265358979323846 # define M_PI 3.14159265358979323846
#endif #endif
#define envspd_adr(rate) ((uint64_t)0xff0000 / ((rate == 0 ? 1 : (rate * 16)) * (rate == 0 ? 1 : (rate * 16)))) #define envspd_factor 6
#define envspd_sr(rate) (rate == 0 ? 0 : ((uint64_t)0xff0000 / ((256 - rate) * (256 - rate) * 256)))
#define envspd_adr(rate) ((uint64_t)0x7f0000 / ((rate == 0 ? 1 : (rate * envspd_factor)) * (rate == 0 ? 1 : (rate * envspd_factor))))
#define envspd_sr(rate) (rate == 0 ? 0 : ((uint64_t)0x7f0000 / ((256 - rate) * (256 - rate) * envspd_factor * envspd_factor)))
//these 4 ones are util only //these 4 ones are util only
double square(double x) { double square(double x) {
@ -2319,7 +2321,7 @@ void sid3_reset(SID3* sid3)
void sid3_do_release_rate_period(sid3_channel_adsr* adsr) void sid3_do_release_rate_period(sid3_channel_adsr* adsr)
{ {
uint32_t counter = adsr->envelope_counter >> 16; uint32_t counter = adsr->envelope_counter >> 15;
if(counter >= 0xff) if(counter >= 0xff)
{ {
@ -2420,7 +2422,7 @@ void sid3_adsr_clock(sid3_channel_adsr* adsr)
{ {
adsr->envelope_counter += adsr->envelope_speed; adsr->envelope_counter += adsr->envelope_speed;
if (adsr->envelope_counter >= 0xff0000) if (adsr->envelope_counter >= 0x7f0000)
{ {
adsr->state = DECAY; adsr->state = DECAY;
adsr->envelope_speed = envspd_adr(adsr->d); adsr->envelope_speed = envspd_adr(adsr->d);
@ -2433,16 +2435,16 @@ void sid3_adsr_clock(sid3_channel_adsr* adsr)
{ {
adsr->envelope_counter -= adsr->envelope_speed; adsr->envelope_counter -= adsr->envelope_speed;
if(adsr->envelope_counter > 0xff0f00) adsr->envelope_counter = 0xff0000; if(adsr->envelope_counter > 0x7f0f00) adsr->envelope_counter = 0x7f0000;
if(adsr->envelope_counter <= ((uint32_t)adsr->s << 16)) if(adsr->envelope_counter <= ((uint32_t)adsr->s << 15))
{ {
adsr->state = SUSTAIN; adsr->state = SUSTAIN;
adsr->envelope_counter = (uint32_t)adsr->s << 16; adsr->envelope_counter = (uint32_t)adsr->s << 15;
adsr->envelope_speed = envspd_sr(adsr->sr); adsr->envelope_speed = envspd_sr(adsr->sr);
} }
if(adsr->envelope_counter <= adsr->envelope_speed || adsr->envelope_counter > 0xfff0000) if(adsr->envelope_counter <= adsr->envelope_speed || adsr->envelope_counter > 0x7ff0000)
{ {
adsr->envelope_counter = 0; adsr->envelope_counter = 0;
adsr->hold_zero = true; adsr->hold_zero = true;
@ -2454,7 +2456,7 @@ void sid3_adsr_clock(sid3_channel_adsr* adsr)
{ {
adsr->envelope_counter -= adsr->envelope_speed; adsr->envelope_counter -= adsr->envelope_speed;
if(adsr->envelope_counter <= adsr->envelope_speed || adsr->envelope_counter > 0xfff0000) if(adsr->envelope_counter <= adsr->envelope_speed || adsr->envelope_counter > 0x7ff0000)
{ {
adsr->envelope_counter = 0; adsr->envelope_counter = 0;
adsr->hold_zero = true; adsr->hold_zero = true;
@ -2492,7 +2494,7 @@ void sid3_adsr_clock(sid3_channel_adsr* adsr)
int32_t sid3_adsr_output(sid3_channel_adsr* adsr, int32_t input) int32_t sid3_adsr_output(sid3_channel_adsr* adsr, int32_t input)
{ {
return (int32_t)((int64_t)input * (int64_t)adsr->envelope_counter / (int64_t)0xff0000 / (int64_t)4 * (int64_t)adsr->vol / (int64_t)SID3_MAX_VOL); //"/ (int64_t)4" so that there's enough amplitude for all 7 chans! return (int32_t)((int64_t)input * (int64_t)adsr->envelope_counter / (int64_t)0x7f0000 / (int64_t)8 * (int64_t)adsr->vol / (int64_t)SID3_MAX_VOL); //"/ (int64_t)8" so that there's enough amplitude for all 7 chans!
} }
void sid3_write(SID3* sid3, uint8_t address, uint8_t data) void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
@ -2507,7 +2509,7 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
//are x + y*n, where x is address of channel 0 register, y is number of current channel and n is how many registers you have //are x + y*n, where x is address of channel 0 register, y is number of current channel and n is how many registers you have
//for each channel //for each channel
{ {
case 0: case SID3_REGISTER_FLAGS:
{ {
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
@ -2531,7 +2533,7 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
} }
break; break;
} }
case 1: case SID3_REGISTER_ADSR_A:
{ {
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
@ -2543,7 +2545,7 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
} }
break; break;
} }
case 2: case SID3_REGISTER_ADSR_D:
{ {
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
@ -2555,7 +2557,7 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
} }
break; break;
} }
case 3: case SID3_REGISTER_ADSR_S:
{ {
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
@ -2567,7 +2569,7 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
} }
break; break;
} }
case 4: case SID3_REGISTER_ADSR_SR:
{ {
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
@ -2579,7 +2581,7 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
} }
break; break;
} }
case 5: case SID3_REGISTER_ADSR_R:
{ {
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
@ -2591,7 +2593,7 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
} }
break; break;
} }
case 6: case SID3_REGISTER_WAVEFORM:
{ {
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
@ -2603,7 +2605,7 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
} }
break; break;
} }
case 7: case SID3_REGISTER_PW_HIGH:
{ {
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
@ -2616,7 +2618,7 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
} }
break; break;
} }
case 8: case SID3_REGISTER_PW_LOW:
{ {
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
@ -2629,7 +2631,7 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
} }
break; break;
} }
case 9: case SID3_REGISTER_SPECIAL_WAVE:
{ {
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
@ -2637,7 +2639,7 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
} }
break; break;
} }
case 10: case SID3_REGISTER_FREQ_HIGH:
{ {
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
@ -2651,7 +2653,7 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
} }
break; break;
} }
case 11: case SID3_REGISTER_FREQ_MID:
{ {
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
@ -2665,7 +2667,7 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
} }
break; break;
} }
case 12: case SID3_REGISTER_FREQ_LOW:
{ {
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
@ -2679,7 +2681,7 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
} }
break; break;
} }
case 13: case SID3_REGISTER_ADSR_VOL:
{ {
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
@ -2691,7 +2693,7 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
} }
break; break;
} }
case 14: case SID3_REGISTER_MIXMODE:
{ {
if(channel != SID3_NUM_CHANNELS - 1) if(channel != SID3_NUM_CHANNELS - 1)
{ {
@ -2699,6 +2701,30 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
} }
break; break;
} }
case SID3_REGISTER_RING_MOD_SRC:
{
if(channel != SID3_NUM_CHANNELS - 1)
{
sid3->chan[channel].ring_mod_src = data;
}
else
{
sid3->wave_chan.ring_mod_src = data;
}
break;
}
case SID3_REGISTER_SYNC_SRC:
{
if(channel != SID3_NUM_CHANNELS - 1)
{
sid3->chan[channel].hard_sync_src = data;
}
else
{
sid3->wave_chan.hard_sync_src = data;
}
break;
}
default: break; default: break;
} }
} }
@ -3011,6 +3037,14 @@ void sid3_clock(SID3* sid3)
ch->sync_bit = 1; ch->sync_bit = 1;
} }
if(ch->flags & SID3_CHAN_ENABLE_HARD_SYNC)
{
if(sid3->chan[ch->hard_sync_src].sync_bit)
{
ch->accumulator = 0;
}
}
ch->accumulator &= SID3_ACC_MASK; ch->accumulator &= SID3_ACC_MASK;
if((prev_acc & ((uint32_t)1 << (SID3_ACC_BITS - 6))) != (ch->accumulator & ((uint32_t)1 << (SID3_ACC_BITS - 6)))) if((prev_acc & ((uint32_t)1 << (SID3_ACC_BITS - 6))) != (ch->accumulator & ((uint32_t)1 << (SID3_ACC_BITS - 6))))
@ -3022,6 +3056,15 @@ void sid3_clock(SID3* sid3)
int32_t waveform = sid3_get_waveform(sid3, ch); int32_t waveform = sid3_get_waveform(sid3, ch);
sid3->channel_signals_before_ADSR[i] = waveform;
if(ch->flags & SID3_CHAN_ENABLE_RING_MOD)
{
uint8_t ring_mod_src = ch->ring_mod_src == SID3_NUM_CHANNELS ? i : ch->ring_mod_src; //SID3_NUM_CHANNELS = self-mod
waveform = waveform * sid3->channel_signals_before_ADSR[ring_mod_src] / (int32_t)0xffff; //ring modulation is just multiplication of two signals!
}
sid3_adsr_clock(&ch->adsr); sid3_adsr_clock(&ch->adsr);
sid3->output_l += sid3_adsr_output(&ch->adsr, waveform); sid3->output_l += sid3_adsr_output(&ch->adsr, waveform);
sid3->output_r += sid3_adsr_output(&ch->adsr, waveform); sid3->output_r += sid3_adsr_output(&ch->adsr, waveform);

View file

@ -12,7 +12,7 @@ extern "C" {
#define SID3_NUM_CHANNELS 7 #define SID3_NUM_CHANNELS 7
#define SID3_NUM_FILTERS 4 #define SID3_NUM_FILTERS 4
#define SID3_REGISTERS_PER_CHANNEL 32 #define SID3_REGISTERS_PER_CHANNEL 64
#define SID3_NUM_REGISTERS (SID3_NUM_CHANNELS * SID3_REGISTERS_PER_CHANNEL) #define SID3_NUM_REGISTERS (SID3_NUM_CHANNELS * SID3_REGISTERS_PER_CHANNEL)
#define SID3_MAX_VOL 255 #define SID3_MAX_VOL 255
@ -57,6 +57,35 @@ enum Mixmodes
SID3_MIX_SUM = 4, SID3_MIX_SUM = 4,
}; };
enum Registers
{
SID3_REGISTER_FLAGS = 0,
SID3_REGISTER_ADSR_A = 1,
SID3_REGISTER_ADSR_D = 2,
SID3_REGISTER_ADSR_S = 3,
SID3_REGISTER_ADSR_SR = 4,
SID3_REGISTER_ADSR_R = 5,
SID3_REGISTER_WAVEFORM = 6,
SID3_REGISTER_PW_HIGH = 7,
SID3_REGISTER_PW_LOW = 8,
SID3_REGISTER_SPECIAL_WAVE = 9,
SID3_REGISTER_FREQ_HIGH = 10,
SID3_REGISTER_FREQ_MID = 11,
SID3_REGISTER_FREQ_LOW = 12,
SID3_REGISTER_ADSR_VOL = 13,
SID3_REGISTER_MIXMODE = 14,
SID3_REGISTER_RING_MOD_SRC = 15,
SID3_REGISTER_SYNC_SRC = 16,
};
typedef struct typedef struct
{ {
int32_t input; int32_t input;
@ -147,6 +176,10 @@ typedef struct
uint8_t flags; uint8_t flags;
uint8_t mode; uint8_t mode;
uint8_t ring_mod_src;
uint8_t hard_sync_src;
uint8_t phase_mod_source;
sid3_filters_block filt; sid3_filters_block filt;
uint8_t panning_left, panning_right; uint8_t panning_left, panning_right;
@ -162,6 +195,7 @@ typedef struct
int32_t output_l, output_r; int32_t output_l, output_r;
int32_t channel_signals_before_ADSR[SID3_NUM_CHANNELS];
int32_t channel_output[SID3_NUM_CHANNELS]; int32_t channel_output[SID3_NUM_CHANNELS];
//emulation-only helpers //emulation-only helpers

View file

@ -5626,6 +5626,41 @@ void FurnaceGUI::drawInsSID3(DivInstrument* ins)
P(CWSliderScalar(_("Wave Mix Mode"),ImGuiDataType_U8,&ins->sid2.mixMode,&_ZERO,&_FOUR,sid3WaveMixModes[ins->sid2.mixMode % 5])); P(CWSliderScalar(_("Wave Mix Mode"),ImGuiDataType_U8,&ins->sid2.mixMode,&_ZERO,&_FOUR,sid3WaveMixModes[ins->sid2.mixMode % 5]));
P(CWSliderScalar(_("Duty"),ImGuiDataType_U16,&ins->c64.duty,&_ZERO,&_SIXTY_FIVE_THOUSAND_FIVE_HUNDRED_THIRTY_FIVE)); rightClickable P(CWSliderScalar(_("Duty"),ImGuiDataType_U16,&ins->c64.duty,&_ZERO,&_SIXTY_FIVE_THOUSAND_FIVE_HUNDRED_THIRTY_FIVE)); rightClickable
bool ringMod=ins->c64.ringMod;
if (ImGui::Checkbox(_("Ring Modulation"),&ringMod)) { PARAMETER
ins->c64.ringMod=ringMod;
}
char buffer[20];
if(ins->sid3.ring_mod_source == SID3_NUM_CHANNELS)
{
snprintf(buffer, 20, _("Self"));
}
else if(ins->sid3.ring_mod_source == SID3_NUM_CHANNELS - 1)
{
snprintf(buffer, 20, _("PCM channel"));
}
else
{
snprintf(buffer, 20, "%d", ins->sid3.ring_mod_source + 1);
}
P(CWSliderScalar(_("Ring mod source channel"),ImGuiDataType_U8,&ins->sid3.ring_mod_source,&_ZERO,&_SID3_NUM_CHANNELS,buffer));
bool oscSync=ins->c64.oscSync;
if (ImGui::Checkbox(_("Oscillator Sync"),&oscSync)) { PARAMETER
ins->c64.oscSync=oscSync;
}
snprintf(buffer, 20, "%d", ins->sid3.sync_source + 1);
P(CWSliderScalar(_("Sync source channel"),ImGuiDataType_U8,&ins->sid3.sync_source,&_ZERO,&_SID3_NUM_CHANNELS_MINUS_ONE));
bool phaseMod=ins->sid3.phase_mod;
if (ImGui::Checkbox(_("Phase modulation"),&phaseMod)) { PARAMETER
ins->sid3.phase_mod=phaseMod;
}
ImGui::EndTabItem(); ImGui::EndTabItem();
} }

View file

@ -44,4 +44,6 @@ const int _MINUS_TWENTY_FOUR=-24;
const int _MINUS_ONE_HUNDRED_TWENTY_SEVEN=-127; const int _MINUS_ONE_HUNDRED_TWENTY_SEVEN=-127;
const int _MINUS_ONE_HUNDRED_TWENTY_EIGHT=-128; const int _MINUS_ONE_HUNDRED_TWENTY_EIGHT=-128;
const int _SID3_SPECIAL_WAVES=SID3_NUM_SPECIAL_WAVES - 1; const int _SID3_SPECIAL_WAVES=SID3_NUM_SPECIAL_WAVES - 1;
const int _SID3_NUM_CHANNELS=SID3_NUM_CHANNELS;
const int _SID3_NUM_CHANNELS_MINUS_ONE=SID3_NUM_CHANNELS - 1;

View file

@ -45,3 +45,5 @@ extern const int _MINUS_ONE_HUNDRED_TWENTY_SEVEN;
extern const int _MINUS_ONE_HUNDRED_TWENTY_EIGHT; extern const int _MINUS_ONE_HUNDRED_TWENTY_EIGHT;
extern const int _SID3_SPECIAL_WAVES; extern const int _SID3_SPECIAL_WAVES;
extern const int _SID3_NUM_CHANNELS;
extern const int _SID3_NUM_CHANNELS_MINUS_ONE;