it plays basic waves with reSID envelope for now
This commit is contained in:
parent
719cec89b1
commit
8ac7fa7de5
|
@ -107,6 +107,19 @@ void DivPlatformSID3::updateFilter(int channel)
|
||||||
//rWrite(0x17 + 3 * channel,chan[channel].filtRes);
|
//rWrite(0x17 + 3 * channel,chan[channel].filtRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformSID3::updateFreq(int channel)
|
||||||
|
{
|
||||||
|
rWrite(10 + channel*SID3_REGISTERS_PER_CHANNEL,(chan[channel].freq >> 16) & 0xff);
|
||||||
|
rWrite(11 + channel*SID3_REGISTERS_PER_CHANNEL,(chan[channel].freq >> 8) & 0xff);
|
||||||
|
rWrite(12 + channel*SID3_REGISTERS_PER_CHANNEL,chan[channel].freq & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformSID3::updateDuty(int channel)
|
||||||
|
{
|
||||||
|
rWrite(7 + channel*SID3_REGISTERS_PER_CHANNEL,(chan[channel].duty >> 8) & 0xff);
|
||||||
|
rWrite(8 + channel*SID3_REGISTERS_PER_CHANNEL,chan[channel].duty & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
void DivPlatformSID3::tick(bool sysTick)
|
void DivPlatformSID3::tick(bool sysTick)
|
||||||
{
|
{
|
||||||
for (int i=0; i<SID3_NUM_CHANNELS; i++)
|
for (int i=0; i<SID3_NUM_CHANNELS; i++)
|
||||||
|
@ -115,13 +128,17 @@ void DivPlatformSID3::tick(bool sysTick)
|
||||||
|
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff)
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff)
|
||||||
{
|
{
|
||||||
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,8,chan[i].pitch2,chipClock,CHIP_FREQBASE);
|
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,2,chan[i].pitch2,chipClock,CHIP_FREQBASE * 64);
|
||||||
//if (chan[i].freq<0) chan[i].freq=0;
|
//if (chan[i].freq<0) chan[i].freq=0;
|
||||||
//if (chan[i].freq>0x1ffff) chan[i].freq=0x1ffff;
|
//if (chan[i].freq>0x1ffff) chan[i].freq=0x1ffff;
|
||||||
|
|
||||||
if (chan[i].keyOn)
|
if (chan[i].keyOn)
|
||||||
{
|
{
|
||||||
rWrite(i*SID3_REGISTERS_PER_CHANNEL,SID3_CHAN_ENABLE_GATE);
|
rWrite(i*SID3_REGISTERS_PER_CHANNEL,SID3_CHAN_ENABLE_GATE);
|
||||||
|
rWrite(6 + i*SID3_REGISTERS_PER_CHANNEL,SID3_WAVE_PULSE);
|
||||||
|
|
||||||
|
chan[i].duty = 0x1000;
|
||||||
|
updateDuty(i);
|
||||||
}
|
}
|
||||||
if (chan[i].keyOff)
|
if (chan[i].keyOff)
|
||||||
{
|
{
|
||||||
|
@ -129,7 +146,9 @@ void DivPlatformSID3::tick(bool sysTick)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chan[i].freq<0) chan[i].freq=0;
|
if (chan[i].freq<0) chan[i].freq=0;
|
||||||
if (chan[i].freq>0x1ffff) chan[i].freq=0x1ffff;
|
if (chan[i].freq>0xffffff) chan[i].freq=0xffffff;
|
||||||
|
|
||||||
|
updateFreq(i);
|
||||||
|
|
||||||
//rWrite(i*7,chan[i].freq&0xff);
|
//rWrite(i*7,chan[i].freq&0xff);
|
||||||
//rWrite(i*7+1,chan[i].freq>>8);
|
//rWrite(i*7+1,chan[i].freq>>8);
|
||||||
|
|
|
@ -81,6 +81,8 @@ class DivPlatformSID3: public DivDispatch {
|
||||||
friend void putDispatchChan(void*,int,int);
|
friend void putDispatchChan(void*,int,int);
|
||||||
|
|
||||||
void updateFilter(int channel);
|
void updateFilter(int channel);
|
||||||
|
void updateFreq(int channel);
|
||||||
|
void updateDuty(int channel);
|
||||||
public:
|
public:
|
||||||
void acquire(short** buf, size_t len);
|
void acquire(short** buf, size_t len);
|
||||||
int dispatch(DivCommand c);
|
int dispatch(DivCommand c);
|
||||||
|
|
|
@ -159,6 +159,8 @@ SID3* sid3_create()
|
||||||
{
|
{
|
||||||
SID3* sid3 = (SID3*)malloc(sizeof(SID3));
|
SID3* sid3 = (SID3*)malloc(sizeof(SID3));
|
||||||
|
|
||||||
|
memset(sid3, 0, sizeof(SID3));
|
||||||
|
|
||||||
for(int i = 0; i < SID3_NUM_SPECIAL_WAVES; i++)
|
for(int i = 0; i < SID3_NUM_SPECIAL_WAVES; i++)
|
||||||
{
|
{
|
||||||
for(int j = 0; j < SID3_SPECIAL_WAVE_LENGTH; j++)
|
for(int j = 0; j < SID3_SPECIAL_WAVE_LENGTH; j++)
|
||||||
|
@ -182,7 +184,8 @@ void sid3_reset(SID3* sid3)
|
||||||
sid3->chan[i].adsr.d = 0x8;
|
sid3->chan[i].adsr.d = 0x8;
|
||||||
sid3->chan[i].adsr.s = 0x80;
|
sid3->chan[i].adsr.s = 0x80;
|
||||||
sid3->chan[i].adsr.r = 0x07;
|
sid3->chan[i].adsr.r = 0x07;
|
||||||
sid3->chan[i].adsr.vol = 0x20;
|
sid3->chan[i].adsr.vol = 0xf0;
|
||||||
|
sid3->chan[i].adsr.hold_zero = true;
|
||||||
//....
|
//....
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,7 +328,7 @@ void sid3_adsr_clock(sid3_channel_adsr* adsr)
|
||||||
|
|
||||||
int sid3_adsr_output(sid3_channel_adsr* adsr, int input)
|
int sid3_adsr_output(sid3_channel_adsr* adsr, int input)
|
||||||
{
|
{
|
||||||
return (int)(input * ((int64_t)adsr->envelope_counter * (int64_t)adsr->vol / (int64_t)SID3_MAX_VOL));
|
return (int)((int64_t)input * (int64_t)adsr->envelope_counter * (int64_t)adsr->vol / (int64_t)SID3_MAX_VOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
|
void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
|
||||||
|
@ -462,6 +465,93 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 10:
|
||||||
|
{
|
||||||
|
if(channel != SID3_NUM_CHANNELS - 1)
|
||||||
|
{
|
||||||
|
sid3->chan[channel].frequency &= 0x00ffff;
|
||||||
|
sid3->chan[channel].frequency |= data << 16;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sid3->wave_chan.frequency &= 0x00ffff;
|
||||||
|
sid3->wave_chan.frequency |= data << 16;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 11:
|
||||||
|
{
|
||||||
|
if(channel != SID3_NUM_CHANNELS - 1)
|
||||||
|
{
|
||||||
|
sid3->chan[channel].frequency &= 0xff00ff;
|
||||||
|
sid3->chan[channel].frequency |= data << 8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sid3->wave_chan.frequency &= 0xff00ff;
|
||||||
|
sid3->wave_chan.frequency |= data << 8;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 12:
|
||||||
|
{
|
||||||
|
if(channel != SID3_NUM_CHANNELS - 1)
|
||||||
|
{
|
||||||
|
sid3->chan[channel].frequency &= 0xffff00;
|
||||||
|
sid3->chan[channel].frequency |= data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sid3->wave_chan.frequency &= 0xffff00;
|
||||||
|
sid3->wave_chan.frequency |= data;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t sid3_pulse(uint32_t acc, uint16_t pw) // 0-FFFF pulse width range
|
||||||
|
{
|
||||||
|
return (((acc >> ((SID3_ACC_BITS - 16))) >= ((pw == 0xffff ? pw + 1 : pw)) ? (0xffff) : 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t sid3_saw(uint32_t acc)
|
||||||
|
{
|
||||||
|
return (acc >> (SID3_ACC_BITS - 16)) & (0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t sid3_triangle(uint32_t acc)
|
||||||
|
{
|
||||||
|
return (((acc < (1 << (SID3_ACC_BITS - 1))) ? ~acc : acc) >> (SID3_ACC_BITS - 17));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t sid3_get_waveform(sid3_channel* ch)
|
||||||
|
{
|
||||||
|
switch(ch->mix_mode)
|
||||||
|
{
|
||||||
|
case SID3_MIX_8580:
|
||||||
|
{
|
||||||
|
switch(ch->waveform)
|
||||||
|
{
|
||||||
|
case SID3_WAVE_TRIANGLE:
|
||||||
|
{
|
||||||
|
return sid3_triangle(ch->accumulator);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SID3_WAVE_SAW:
|
||||||
|
{
|
||||||
|
return sid3_saw(ch->accumulator);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SID3_WAVE_PULSE:
|
||||||
|
{
|
||||||
|
return sid3_pulse(ch->accumulator, ch->pw);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -470,13 +560,37 @@ void sid3_clock(SID3* sid3)
|
||||||
{
|
{
|
||||||
SAFETY_HEADER
|
SAFETY_HEADER
|
||||||
|
|
||||||
|
sid3->output_l = sid3->output_r = 0;
|
||||||
|
|
||||||
for(int i = 0; i < SID3_NUM_CHANNELS - 1; i++)
|
for(int i = 0; i < SID3_NUM_CHANNELS - 1; i++)
|
||||||
{
|
{
|
||||||
sid3_adsr_clock(&sid3->chan[i].adsr);
|
sid3_channel* ch = &sid3->chan[i];
|
||||||
sid3->output_l = sid3_adsr_output(&sid3->chan[i].adsr, 0xff);
|
|
||||||
sid3->output_r = sid3_adsr_output(&sid3->chan[i].adsr, 0xff);
|
|
||||||
|
|
||||||
sid3->channel_output[i] = sid3_adsr_output(&sid3->chan[i].adsr, 0xff);
|
uint32_t prev_acc = ch->accumulator;
|
||||||
|
|
||||||
|
ch->accumulator += ch->frequency;
|
||||||
|
|
||||||
|
if(ch->accumulator & (1 << SID3_ACC_BITS))
|
||||||
|
{
|
||||||
|
ch->sync_bit = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ch->sync_bit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ch->accumulator &= SID3_ACC_MASK;
|
||||||
|
|
||||||
|
//todo: phase mod
|
||||||
|
|
||||||
|
int waveform = sid3_get_waveform(ch);
|
||||||
|
waveform -= 0x7fff;
|
||||||
|
|
||||||
|
sid3_adsr_clock(&ch->adsr);
|
||||||
|
sid3->output_l += sid3_adsr_output(&ch->adsr, waveform / 1024);
|
||||||
|
sid3->output_r += sid3_adsr_output(&ch->adsr, waveform / 1024);
|
||||||
|
|
||||||
|
sid3->channel_output[i] = sid3_adsr_output(&ch->adsr, waveform / 1024);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,9 @@ extern "C" {
|
||||||
#define SID3_NUM_SPECIAL_WAVES 28
|
#define SID3_NUM_SPECIAL_WAVES 28
|
||||||
#define SID3_SPECIAL_WAVE_LENGTH 16384
|
#define SID3_SPECIAL_WAVE_LENGTH 16384
|
||||||
|
|
||||||
|
#define SID3_ACC_BITS 30
|
||||||
|
#define SID3_ACC_MASK ((1UL << SID3_ACC_BITS) - 1)
|
||||||
|
|
||||||
enum Flags
|
enum Flags
|
||||||
{
|
{
|
||||||
SID3_CHAN_ENABLE_GATE = 1,
|
SID3_CHAN_ENABLE_GATE = 1,
|
||||||
|
@ -95,6 +98,7 @@ typedef struct
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint32_t accumulator;
|
uint32_t accumulator;
|
||||||
|
uint8_t sync_bit;
|
||||||
uint32_t frequency;
|
uint32_t frequency;
|
||||||
|
|
||||||
uint32_t noise_accumulator;
|
uint32_t noise_accumulator;
|
||||||
|
@ -125,6 +129,7 @@ typedef struct
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint32_t accumulator;
|
uint32_t accumulator;
|
||||||
|
uint8_t sync_bit;
|
||||||
uint32_t frequency;
|
uint32_t frequency;
|
||||||
|
|
||||||
uint16_t streamed_sample;
|
uint16_t streamed_sample;
|
||||||
|
|
Loading…
Reference in a new issue