halve clock speed, add ring mod and hard sync
This commit is contained in:
parent
d0a990dcfa
commit
365062ac21
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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;
|
||||||
Loading…
Reference in a new issue