proper envelope, noise, start working on inst editor UI
This commit is contained in:
parent
0d4d035c1f
commit
15725acbaa
8 changed files with 479 additions and 120 deletions
|
|
@ -254,6 +254,36 @@ bool DivInstrumentESFM::Operator::operator==(const DivInstrumentESFM::Operator&
|
|||
);
|
||||
}
|
||||
|
||||
bool DivInstrumentSID3::operator==(const DivInstrumentSID3& other) {
|
||||
return (
|
||||
_C(volume) &&
|
||||
_C(sr) &&
|
||||
_C(lfsr_taps) &&
|
||||
_C(phase_mod) &&
|
||||
_C(phase_mod_source) &&
|
||||
_C(ring_mod_source) &&
|
||||
_C(sync_source) &&
|
||||
_C(specialWaveOn) &&
|
||||
_C(special_wave) &&
|
||||
_C(filter_matrix) &&
|
||||
_C(filt[0]) &&
|
||||
_C(filt[1]) &&
|
||||
_C(filt[2]) &&
|
||||
_C(filt[3])
|
||||
);
|
||||
}
|
||||
|
||||
bool DivInstrumentSID3::Filter::operator==(const DivInstrumentSID3::Filter& other) {
|
||||
return (
|
||||
_C(cutoff) &&
|
||||
_C(resonance) &&
|
||||
_C(output_volume) &&
|
||||
_C(distortion_level) &&
|
||||
_C(mode) &&
|
||||
_C(enabled)
|
||||
);
|
||||
}
|
||||
|
||||
bool DivInstrumentPowerNoise::operator==(const DivInstrumentPowerNoise& other) {
|
||||
return _C(octave);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -861,6 +861,59 @@ struct DivInstrumentSID2 {
|
|||
noiseMode(0) {}
|
||||
};
|
||||
|
||||
struct DivInstrumentSID3
|
||||
{
|
||||
unsigned char volume;
|
||||
unsigned char sr;
|
||||
unsigned int lfsr_taps;
|
||||
bool phase_mod;
|
||||
unsigned char phase_mod_source, ring_mod_source, sync_source;
|
||||
bool specialWaveOn;
|
||||
unsigned char special_wave;
|
||||
|
||||
unsigned int filter_matrix;
|
||||
|
||||
struct Filter
|
||||
{
|
||||
unsigned short cutoff;
|
||||
unsigned char resonance;
|
||||
unsigned char output_volume;
|
||||
unsigned char distortion_level;
|
||||
unsigned char mode;
|
||||
bool enabled;
|
||||
|
||||
bool operator==(const Filter& other);
|
||||
bool operator!=(const Filter& other)
|
||||
{
|
||||
return !(*this==other);
|
||||
}
|
||||
Filter():
|
||||
cutoff(0),
|
||||
resonance(0),
|
||||
output_volume(0),
|
||||
distortion_level(0),
|
||||
mode(0),
|
||||
enabled(false) {}
|
||||
} filt[4];
|
||||
|
||||
bool operator==(const DivInstrumentSID3& other);
|
||||
bool operator!=(const DivInstrumentSID3& other)
|
||||
{
|
||||
return !(*this==other);
|
||||
}
|
||||
DivInstrumentSID3():
|
||||
volume(255),
|
||||
sr(0),
|
||||
lfsr_taps(0),
|
||||
phase_mod(false),
|
||||
phase_mod_source(0),
|
||||
ring_mod_source(0),
|
||||
sync_source(0),
|
||||
specialWaveOn(false),
|
||||
special_wave(0),
|
||||
filter_matrix(0) {}
|
||||
};
|
||||
|
||||
struct DivInstrument {
|
||||
String name;
|
||||
DivInstrumentType type;
|
||||
|
|
@ -880,6 +933,7 @@ struct DivInstrument {
|
|||
DivInstrumentESFM esfm;
|
||||
DivInstrumentPowerNoise powernoise;
|
||||
DivInstrumentSID2 sid2;
|
||||
DivInstrumentSID3 sid3;
|
||||
|
||||
/**
|
||||
* these are internal functions.
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ void DivPlatformSID3::acquire(short** buf, size_t len)
|
|||
|
||||
for(int j = 0; j < SID3_NUM_CHANNELS; j++)
|
||||
{
|
||||
oscBuf[j]->data[oscBuf[j]->needle++] = sid3->channel_output[j] / 4;
|
||||
oscBuf[j]->data[oscBuf[j]->needle++] = sid3->channel_output[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -120,12 +120,27 @@ void DivPlatformSID3::updateDuty(int channel)
|
|||
rWrite(8 + channel*SID3_REGISTERS_PER_CHANNEL,chan[channel].duty & 0xff);
|
||||
}
|
||||
|
||||
void DivPlatformSID3::updateEnvelope(int channel)
|
||||
{
|
||||
rWrite(1 + channel * SID3_REGISTERS_PER_CHANNEL, chan[channel].attack); //attack
|
||||
rWrite(2 + channel * SID3_REGISTERS_PER_CHANNEL, chan[channel].decay); //decay
|
||||
rWrite(3 + channel * SID3_REGISTERS_PER_CHANNEL, chan[channel].sustain); //sustain
|
||||
rWrite(4 + channel * SID3_REGISTERS_PER_CHANNEL, chan[channel].sr); //sr
|
||||
rWrite(5 + channel * SID3_REGISTERS_PER_CHANNEL, chan[channel].release); //release
|
||||
}
|
||||
|
||||
void DivPlatformSID3::tick(bool sysTick)
|
||||
{
|
||||
for (int i=0; i<SID3_NUM_CHANNELS; i++)
|
||||
{
|
||||
chan[i].std.next();
|
||||
|
||||
if (chan[i].std.vol.had)
|
||||
{
|
||||
chan[i].outVol=VOL_SCALE_LINEAR(chan[i].vol&255,MIN(255,chan[i].std.vol.val),255);
|
||||
rWrite(13 + i * SID3_REGISTERS_PER_CHANNEL, chan[i].outVol);
|
||||
}
|
||||
|
||||
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,2,chan[i].pitch2,chipClock,CHIP_FREQBASE * 64);
|
||||
|
|
@ -133,13 +148,18 @@ void DivPlatformSID3::tick(bool sysTick)
|
|||
//if (chan[i].freq>0x1ffff) chan[i].freq=0x1ffff;
|
||||
|
||||
if (chan[i].keyOn)
|
||||
{
|
||||
rWrite(i*SID3_REGISTERS_PER_CHANNEL,SID3_CHAN_ENABLE_GATE); //gate on
|
||||
rWrite(6 + i*SID3_REGISTERS_PER_CHANNEL,SID3_WAVE_SPECIAL); //waveform
|
||||
rWrite(9 + i*SID3_REGISTERS_PER_CHANNEL,10); //special wave
|
||||
{
|
||||
rWrite(6 + i * SID3_REGISTERS_PER_CHANNEL, chan[i].wave); //waveform
|
||||
rWrite(9 + i * SID3_REGISTERS_PER_CHANNEL, chan[i].special_wave); //special wave
|
||||
|
||||
rWrite(13 + i * SID3_REGISTERS_PER_CHANNEL, chan[i].outVol); //set volume
|
||||
|
||||
updateEnvelope(i);
|
||||
|
||||
chan[i].duty = 0x1000;
|
||||
updateDuty(i);
|
||||
|
||||
rWrite(i * SID3_REGISTERS_PER_CHANNEL, SID3_CHAN_ENABLE_GATE); //gate on
|
||||
}
|
||||
if (chan[i].keyOff)
|
||||
{
|
||||
|
|
@ -174,7 +194,6 @@ int DivPlatformSID3::dispatch(DivCommand c) {
|
|||
}
|
||||
chan[c.chan].active=true;
|
||||
chan[c.chan].keyOn=true;
|
||||
chan[c.chan].test=false;
|
||||
|
||||
if (chan[c.chan].insChanged || chan[c.chan].resetDuty || ins->std.waveMacro.len>0) {
|
||||
chan[c.chan].duty=ins->c64.duty;
|
||||
|
|
@ -192,15 +211,25 @@ int DivPlatformSID3::dispatch(DivCommand c) {
|
|||
|
||||
chan[c.chan].noise_mode = ins->sid3.noiseMode;
|
||||
chan[c.chan].mix_mode = ins->sid3.mixMode;*/
|
||||
|
||||
chan[c.chan].wave = (ins->c64.triOn ? SID3_WAVE_TRIANGLE : 0) | (ins->c64.sawOn ? SID3_WAVE_SAW : 0) |
|
||||
(ins->c64.pulseOn ? SID3_WAVE_PULSE : 0) | (ins->c64.noiseOn ? SID3_WAVE_NOISE : 0) | (ins->sid3.specialWaveOn ? SID3_WAVE_SPECIAL : 0); //waveform
|
||||
chan[c.chan].special_wave = ins->sid3.special_wave; //special wave
|
||||
|
||||
chan[c.chan].attack=ins->c64.a;
|
||||
chan[c.chan].decay=ins->c64.d;
|
||||
chan[c.chan].sustain=ins->c64.s;
|
||||
chan[c.chan].sr=ins->sid3.sr;
|
||||
chan[c.chan].release=ins->c64.r;
|
||||
}
|
||||
if (chan[c.chan].insChanged || chan[c.chan].resetFilter) {
|
||||
chan[c.chan].filter=ins->c64.toFilter;
|
||||
/*chan[c.chan].filter=ins->c64.toFilter;
|
||||
if (ins->c64.initFilter) {
|
||||
chan[c.chan].filtCut=ins->c64.cut;
|
||||
chan[c.chan].filtRes=ins->c64.res;
|
||||
chan[c.chan].filtControl=(int)(ins->c64.lp)|(ins->c64.bp<<1)|(ins->c64.hp<<2);
|
||||
}
|
||||
updateFilter(c.chan);
|
||||
updateFilter(c.chan);*/
|
||||
}
|
||||
if (chan[c.chan].insChanged) {
|
||||
chan[c.chan].insChanged=false;
|
||||
|
|
@ -348,10 +377,7 @@ DivChannelModeHints DivPlatformSID3::getModeHints(int ch) {
|
|||
ret.count=1;
|
||||
ret.hint[0]=ICON_FA_BELL_SLASH_O;
|
||||
ret.type[0]=0;
|
||||
if (ch == 2 && (chan[ch].filtControl & 8)) {
|
||||
ret.type[0] = 7;
|
||||
}
|
||||
else if (!chan[ch].gate) {
|
||||
if (!chan[ch].gate) {
|
||||
ret.type[0]=4;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,12 +27,10 @@
|
|||
class DivPlatformSID3: public DivDispatch {
|
||||
struct Channel: public SharedChannel<signed short> {
|
||||
int prevFreq;
|
||||
unsigned char wave, attack, decay, sustain, release;
|
||||
unsigned char wave, special_wave, attack, decay, sustain, sr, release;
|
||||
short duty;
|
||||
bool filter;
|
||||
bool resetMask, resetFilter, resetDuty, gate, ring, sync, test;
|
||||
bool resetMask, resetFilter, resetDuty, gate, ring, sync, phase;
|
||||
unsigned char vol;
|
||||
unsigned char filtControl, filtRes;
|
||||
unsigned char noise_mode;
|
||||
unsigned char mix_mode;
|
||||
int filtCut;
|
||||
|
|
@ -40,22 +38,21 @@ class DivPlatformSID3: public DivDispatch {
|
|||
SharedChannel<signed short>(SID3_MAX_VOL),
|
||||
prevFreq(0x1ffff),
|
||||
wave(0),
|
||||
special_wave(0),
|
||||
attack(0),
|
||||
decay(0),
|
||||
sustain(0),
|
||||
sr(0),
|
||||
release(0),
|
||||
duty(0),
|
||||
filter(false),
|
||||
resetMask(false),
|
||||
resetFilter(false),
|
||||
resetDuty(false),
|
||||
gate(true),
|
||||
ring(false),
|
||||
sync(false),
|
||||
test(false),
|
||||
phase(false),
|
||||
vol(SID3_MAX_VOL),
|
||||
filtControl(0),
|
||||
filtRes(0),
|
||||
noise_mode(0),
|
||||
mix_mode(0),
|
||||
filtCut(0) {}
|
||||
|
|
@ -83,6 +80,7 @@ class DivPlatformSID3: public DivDispatch {
|
|||
void updateFilter(int channel);
|
||||
void updateFreq(int channel);
|
||||
void updateDuty(int channel);
|
||||
void updateEnvelope(int channel);
|
||||
public:
|
||||
void acquire(short** buf, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
|
|
|
|||
|
|
@ -4,12 +4,15 @@
|
|||
|
||||
#define SAFETY_HEADER if(sid3 == NULL) return;
|
||||
|
||||
enum State { ATTACK, DECAY_SUSTAIN, RELEASE }; //for envelope
|
||||
enum State { ATTACK, DECAY, SUSTAIN, RELEASE }; //for envelope
|
||||
|
||||
#ifndef M_PI
|
||||
# define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#define envspd_adr(rate) ((uint64_t)0xff0000 / ((rate == 0 ? 1 : (rate * 16)) * (rate == 0 ? 1 : (rate * 16))))
|
||||
#define envspd_sr(rate) (rate == 0 ? 0 : ((uint64_t)0xff0000 / ((256 - rate) * (256 - rate) * 256)))
|
||||
|
||||
//these 4 ones are util only
|
||||
double square(double x) {
|
||||
return fmod(x, (2 * M_PI)) >= M_PI ? -1 : 1;
|
||||
|
|
@ -2243,53 +2246,91 @@ void sid3_reset(SID3* sid3)
|
|||
for(int32_t i = 0; i < SID3_NUM_CHANNELS - 1; i++)
|
||||
{
|
||||
memset(&sid3->chan[i], 0, sizeof(sid3_channel));
|
||||
sid3->chan[i].accumulator = 0;
|
||||
sid3->chan[i].adsr.a = 0x8;
|
||||
sid3->chan[i].adsr.d = 0x8;
|
||||
/*sid3->chan[i].accumulator = 0;
|
||||
sid3->chan[i].adsr.a = 0x20;
|
||||
sid3->chan[i].adsr.d = 0x20;
|
||||
sid3->chan[i].adsr.s = 0x80;
|
||||
sid3->chan[i].adsr.r = 0x07;
|
||||
sid3->chan[i].adsr.vol = 0xf0;
|
||||
sid3->chan[i].adsr.r = 0x17;
|
||||
sid3->chan[i].adsr.vol = 0xf0;*/
|
||||
sid3->chan[i].adsr.hold_zero = true;
|
||||
sid3->chan[i].lfsr = 0x1;
|
||||
sid3->chan[i].lfsr_taps = (1 << 29) | (1 << 5) | (1 << 3) | 1; //https://docs.amd.com/v/u/en-US/xapp052 for 30 bits: 30, 6, 4, 1
|
||||
//....
|
||||
}
|
||||
|
||||
//TODO: wavetable chan
|
||||
}
|
||||
|
||||
void sid3_gate_bit(uint8_t gate_next, uint8_t gate, sid3_channel_adsr* adsr)
|
||||
void sid3_do_release_rate_period(sid3_channel_adsr* adsr)
|
||||
{
|
||||
uint32_t counter = adsr->envelope_counter >> 16;
|
||||
|
||||
if(counter >= 0xff)
|
||||
{
|
||||
adsr->rate_period = 1;
|
||||
return;
|
||||
}
|
||||
if(counter >= 0x5d)
|
||||
{
|
||||
adsr->rate_period = 2;
|
||||
return;
|
||||
}
|
||||
if(counter >= 0x36)
|
||||
{
|
||||
adsr->rate_period = 4;
|
||||
return;
|
||||
}
|
||||
if(counter >= 0x1a)
|
||||
{
|
||||
adsr->rate_period = 8;
|
||||
return;
|
||||
}
|
||||
if(counter >= 0x0e)
|
||||
{
|
||||
adsr->rate_period = 16;
|
||||
return;
|
||||
}
|
||||
if(counter >= 0x06)
|
||||
{
|
||||
adsr->rate_period = 32;
|
||||
return;
|
||||
}
|
||||
if(counter >= 0x02)
|
||||
{
|
||||
adsr->rate_period = 64;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void sid3_gate_bit(uint8_t gate, sid3_channel_adsr* adsr)
|
||||
{
|
||||
// The rate counter is never reset, thus there will be a delay before the
|
||||
// envelope counter starts counting up (attack) or down (release).
|
||||
|
||||
// Gate bit on: Start attack, decay, sustain.
|
||||
if (!gate && gate_next)
|
||||
if (gate)
|
||||
{
|
||||
adsr->state = ATTACK;
|
||||
adsr->rate_period = adsr->a << 8; //todo: make it properly
|
||||
adsr->envelope_speed = envspd_adr(adsr->a); //todo: make it properly
|
||||
//adsr->envelope_counter = 0;
|
||||
|
||||
// Switching to attack state unlocks the zero freeze.
|
||||
adsr->hold_zero = false;
|
||||
|
||||
adsr->rate_counter = 0;
|
||||
adsr->exponential_counter = 0;
|
||||
//envelope_counter = 0;
|
||||
|
||||
if(adsr->envelope_counter == 0xff)
|
||||
{
|
||||
adsr->envelope_counter--; //idk why it happens, but when envelope has max sustain and I retrigger with new note it just becomes silent so this is the only solution I found so far
|
||||
}
|
||||
adsr->rate_period = 1;
|
||||
}
|
||||
// Gate bit off: Start release.
|
||||
else if (gate && !gate_next)
|
||||
else
|
||||
{
|
||||
adsr->state = RELEASE;
|
||||
adsr->rate_period = adsr->r << 8; //todo: make it properly
|
||||
adsr->envelope_speed = envspd_adr(adsr->r); //todo: make it properly
|
||||
|
||||
adsr->rate_counter = 0;
|
||||
adsr->exponential_counter = 0;
|
||||
}
|
||||
//adsr->rate_period = 1;
|
||||
|
||||
//gate = gate_next;
|
||||
sid3_do_release_rate_period(adsr);
|
||||
}
|
||||
}
|
||||
|
||||
void sid3_adsr_clock(sid3_channel_adsr* adsr)
|
||||
|
|
@ -2304,95 +2345,90 @@ void sid3_adsr_clock(sid3_channel_adsr* adsr)
|
|||
adsr->rate_counter = adsr->rate_period; //so you can do alternating writes (e.g. writing attack 10-11-10-11-... results in the somewhat average envelope speed)
|
||||
}
|
||||
|
||||
if (adsr->rate_counter != adsr->rate_period) {
|
||||
if (adsr->rate_counter != adsr->rate_period)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
adsr->rate_counter = 0;
|
||||
|
||||
// The first envelope step in the attack state also resets the exponential
|
||||
// counter. This has been verified by sampling ENV3.
|
||||
//
|
||||
if (adsr->state == ATTACK || ++adsr->exponential_counter == adsr->exponential_counter_period)
|
||||
// Check whether the envelope counter is frozen at zero.
|
||||
if (adsr->hold_zero)
|
||||
{
|
||||
adsr->exponential_counter = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check whether the envelope counter is frozen at zero.
|
||||
if (adsr->hold_zero)
|
||||
switch (adsr->state)
|
||||
{
|
||||
case ATTACK:
|
||||
{
|
||||
return;
|
||||
}
|
||||
adsr->envelope_counter += adsr->envelope_speed;
|
||||
|
||||
switch (adsr->state)
|
||||
{
|
||||
case ATTACK:
|
||||
// The envelope counter can flip from 0xff to 0x00 by changing state to
|
||||
// release, then to attack. The envelope counter is then frozen at
|
||||
// zero; to unlock this situation the state must be changed to release,
|
||||
// then to attack. This has been verified by sampling ENV3.
|
||||
//
|
||||
adsr->envelope_counter++;
|
||||
adsr->envelope_counter &= 0xff;
|
||||
|
||||
if (adsr->envelope_counter == 0xff)
|
||||
if (adsr->envelope_counter >= 0xff0000)
|
||||
{
|
||||
adsr->state = DECAY_SUSTAIN;
|
||||
adsr->rate_period = (adsr->d << 8); //todo: do it properly
|
||||
adsr->state = DECAY;
|
||||
adsr->envelope_speed = envspd_adr(adsr->d); //todo: do it properly
|
||||
}
|
||||
break;
|
||||
case DECAY_SUSTAIN:
|
||||
if (adsr->envelope_counter != (adsr->s))
|
||||
{
|
||||
--adsr->envelope_counter;
|
||||
}
|
||||
break;
|
||||
case RELEASE:
|
||||
// The envelope counter can flip from 0x00 to 0xff by changing state to
|
||||
// attack, then to release. The envelope counter will then continue
|
||||
// counting down in the release state.
|
||||
// This has been verified by sampling ENV3.
|
||||
// NB! The operation below requires two's complement integer.
|
||||
//
|
||||
//--envelope_counter &= 0xff;
|
||||
adsr->envelope_counter--;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for change of exponential counter period.
|
||||
switch (adsr->envelope_counter)
|
||||
{
|
||||
case 0xff:
|
||||
adsr->exponential_counter_period = 1;
|
||||
break;
|
||||
case 0x5d:
|
||||
adsr->exponential_counter_period = 2;
|
||||
break;
|
||||
case 0x36:
|
||||
adsr->exponential_counter_period = 4;
|
||||
break;
|
||||
case 0x1a:
|
||||
adsr->exponential_counter_period = 8;
|
||||
break;
|
||||
case 0x0e:
|
||||
adsr->exponential_counter_period = 16;
|
||||
break;
|
||||
case 0x06:
|
||||
adsr->exponential_counter_period = 30;
|
||||
break;
|
||||
case 0x00:
|
||||
adsr->exponential_counter_period = 1;
|
||||
|
||||
// When the envelope counter is changed to zero, it is frozen at zero.
|
||||
// This has been verified by sampling ENV3.
|
||||
adsr->hold_zero = true;
|
||||
break;
|
||||
return; //do not do exponential approximation of attack
|
||||
}
|
||||
break;
|
||||
case DECAY:
|
||||
{
|
||||
adsr->envelope_counter -= adsr->envelope_speed;
|
||||
|
||||
if(adsr->envelope_counter <= ((uint32_t)adsr->s << 16) || adsr->envelope_counter > 0xff0000)
|
||||
{
|
||||
adsr->state = SUSTAIN;
|
||||
adsr->envelope_counter = (uint32_t)adsr->s << 16;
|
||||
adsr->envelope_speed = envspd_sr(adsr->sr); //todo: do it properly
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SUSTAIN:
|
||||
case RELEASE:
|
||||
{
|
||||
adsr->envelope_counter -= adsr->envelope_speed;
|
||||
|
||||
if(adsr->envelope_counter <= adsr->envelope_speed || adsr->envelope_counter > 0xff0000)
|
||||
{
|
||||
adsr->envelope_counter = 0;
|
||||
adsr->hold_zero = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for change of exponential counter period.
|
||||
switch (adsr->envelope_counter >> 16)
|
||||
{
|
||||
case 0xff:
|
||||
adsr->rate_period = 1;
|
||||
break;
|
||||
case 0x5d:
|
||||
adsr->rate_period = 2;
|
||||
break;
|
||||
case 0x36:
|
||||
adsr->rate_period = 4;
|
||||
break;
|
||||
case 0x1a:
|
||||
adsr->rate_period = 8;
|
||||
break;
|
||||
case 0x0e:
|
||||
adsr->rate_period = 16;
|
||||
break;
|
||||
case 0x06:
|
||||
adsr->rate_period = 32;
|
||||
break;
|
||||
case 0x02:
|
||||
adsr->rate_period = 64;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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)adsr->vol / (int64_t)SID3_MAX_VOL / (int64_t)SID3_MAX_VOL);
|
||||
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!
|
||||
}
|
||||
|
||||
void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
|
||||
|
|
@ -2411,15 +2447,15 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
|
|||
{
|
||||
if(channel != SID3_NUM_CHANNELS - 1)
|
||||
{
|
||||
uint8_t prev_flags = sid3->chan[channel].flags & SID3_CHAN_ENABLE_GATE;
|
||||
//uint8_t prev_flags = sid3->chan[channel].flags & SID3_CHAN_ENABLE_GATE;
|
||||
sid3->chan[channel].flags = data;
|
||||
sid3_gate_bit(sid3->chan[channel].flags & SID3_CHAN_ENABLE_GATE, prev_flags, &sid3->chan[channel].adsr);
|
||||
sid3_gate_bit(sid3->chan[channel].flags & SID3_CHAN_ENABLE_GATE, &sid3->chan[channel].adsr);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t prev_flags = sid3->chan[channel].flags & SID3_CHAN_ENABLE_GATE;
|
||||
//uint8_t prev_flags = sid3->chan[channel].flags & SID3_CHAN_ENABLE_GATE;
|
||||
sid3->wave_chan.flags = data;
|
||||
sid3_gate_bit(sid3->wave_chan.flags & SID3_CHAN_ENABLE_GATE, prev_flags, &sid3->wave_chan.adsr);
|
||||
sid3_gate_bit(sid3->wave_chan.flags & SID3_CHAN_ENABLE_GATE, &sid3->wave_chan.adsr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -2571,6 +2607,18 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case 13:
|
||||
{
|
||||
if(channel != SID3_NUM_CHANNELS - 1)
|
||||
{
|
||||
sid3->chan[channel].adsr.vol = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
sid3->wave_chan.adsr.vol = data;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
|
@ -2592,12 +2640,18 @@ inline uint16_t sid3_triangle(uint32_t acc)
|
|||
|
||||
void sid3_clock_lfsr(sid3_channel* ch)
|
||||
{
|
||||
uint32_t feedback = ch->lfsr & 1;
|
||||
ch->lfsr >>= 1;
|
||||
|
||||
if (feedback)
|
||||
{
|
||||
ch->lfsr ^= ch->lfsr_taps;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t sid3_noise(uint32_t lfsr, bool one_bit)
|
||||
{
|
||||
return 0;
|
||||
return one_bit ? ((lfsr & 1) ? 0xffff : 0) : (lfsr & 0xffff);
|
||||
}
|
||||
|
||||
inline uint16_t sid3_special_wave(SID3* sid3, uint32_t acc, uint8_t wave)
|
||||
|
|
@ -2668,6 +2722,11 @@ void sid3_clock(SID3* sid3)
|
|||
|
||||
ch->accumulator &= SID3_ACC_MASK;
|
||||
|
||||
if((prev_acc & ((uint32_t)1 << (SID3_ACC_BITS - 6))) != (ch->accumulator & ((uint32_t)1 << (SID3_ACC_BITS - 6))))
|
||||
{
|
||||
sid3_clock_lfsr(ch);
|
||||
}
|
||||
|
||||
//todo: phase mod
|
||||
|
||||
int32_t waveform = sid3_get_waveform(sid3, ch);
|
||||
|
|
|
|||
|
|
@ -75,6 +75,8 @@ typedef struct
|
|||
|
||||
uint8_t mode;
|
||||
|
||||
uint8_t output_volume;
|
||||
|
||||
bool channel_output; //output to the channel master output
|
||||
} sid3_filter;
|
||||
|
||||
|
|
@ -90,9 +92,8 @@ typedef struct
|
|||
|
||||
uint32_t rate_counter;
|
||||
uint32_t rate_period;
|
||||
uint16_t exponential_counter;
|
||||
uint16_t exponential_counter_period;
|
||||
uint8_t envelope_counter;
|
||||
uint32_t envelope_counter;
|
||||
uint32_t envelope_speed;
|
||||
bool hold_zero;
|
||||
} sid3_channel_adsr;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue