From 441e3e0b56a7468d1c1711fa5a25d1a0048c5b5d Mon Sep 17 00:00:00 2001 From: LTVA1 <87536432+LTVA1@users.noreply.github.com> Date: Fri, 2 Aug 2024 14:18:13 +0300 Subject: [PATCH] initial filters functionality (without connection matrix control yet!) --- src/engine/instrument.cpp | 5 +- src/engine/instrument.h | 15 +- src/engine/platform/sid3.cpp | 55 +++++-- src/engine/platform/sid3.h | 27 +++- src/engine/platform/sound/sid3.c | 253 ++++++++++++++++++++++++++++++- src/engine/platform/sound/sid3.h | 33 +++- src/gui/insEdit.cpp | 81 +++++++++- 7 files changed, 433 insertions(+), 36 deletions(-) diff --git a/src/engine/instrument.cpp b/src/engine/instrument.cpp index 5912efa2a..48e7d52c9 100644 --- a/src/engine/instrument.cpp +++ b/src/engine/instrument.cpp @@ -266,7 +266,6 @@ bool DivInstrumentSID3::operator==(const DivInstrumentSID3& other) { _C(specialWaveOn) && _C(oneBitNoise) && _C(special_wave) && - _C(filter_matrix) && _C(filt[0]) && _C(filt[1]) && _C(filt[2]) && @@ -281,7 +280,9 @@ bool DivInstrumentSID3::Filter::operator==(const DivInstrumentSID3::Filter& othe _C(output_volume) && _C(distortion_level) && _C(mode) && - _C(enabled) + _C(enabled) && + _C(init) && + _C(filter_matrix) ); } diff --git a/src/engine/instrument.h b/src/engine/instrument.h index 4b17efd02..d08c0aa12 100644 --- a/src/engine/instrument.h +++ b/src/engine/instrument.h @@ -872,8 +872,6 @@ struct DivInstrumentSID3 bool oneBitNoise; unsigned char special_wave; - unsigned int filter_matrix; - struct Filter { unsigned short cutoff; @@ -882,6 +880,8 @@ struct DivInstrumentSID3 unsigned char distortion_level; unsigned char mode; bool enabled; + bool init; + unsigned char filter_matrix; bool operator==(const Filter& other); bool operator!=(const Filter& other) @@ -894,7 +894,9 @@ struct DivInstrumentSID3 output_volume(0), distortion_level(0), mode(0), - enabled(false) {} + enabled(false), + init(false), + filter_matrix(0) {} } filt[4]; bool operator==(const DivInstrumentSID3& other); @@ -912,8 +914,11 @@ struct DivInstrumentSID3 sync_source(0), specialWaveOn(false), oneBitNoise(false), - special_wave(0), - filter_matrix(0) {} + special_wave(0) + { + filt[0].mode = 16 | 32; //default settings so filter just works, connect to input and channel output + filt[0].output_volume = 0xff; + } }; struct DivInstrument { diff --git a/src/engine/platform/sid3.cpp b/src/engine/platform/sid3.cpp index 5a51ae831..a215845fb 100644 --- a/src/engine/platform/sid3.cpp +++ b/src/engine/platform/sid3.cpp @@ -78,7 +78,7 @@ void DivPlatformSID3::acquire(short** buf, size_t len) if (!writes.empty()) { QueuedWrite w=writes.front(); - sid3_write(sid3, w.addr,w.val); + sid3_write(sid3, w.addr, w.val); regPool[w.addr % SID3_NUM_REGISTERS]=w.val; writes.pop(); } @@ -112,11 +112,27 @@ void DivPlatformSID3::updateFlags(int channel, bool gate) (chan[channel].oneBitNoise ? SID3_CHAN_1_BIT_NOISE : 0)); } -void DivPlatformSID3::updateFilter(int channel) +void DivPlatformSID3::updateFilter(int channel, int filter) { - //rWrite(0x15 + 3 * channel,(chan[channel].filtCut&15) | ((chan[channel].filtControl & 7) << 4) | (chan[channel].filter << 7)); - //rWrite(0x16 + 3 * channel,(chan[channel].filtCut >> 4)); - //rWrite(0x17 + 3 * channel,chan[channel].filtRes); + rWrite(SID3_REGISTER_FILT_MODE + filter * SID3_REGISTERS_PER_FILTER + channel*SID3_REGISTERS_PER_CHANNEL, + chan[channel].filt[filter].mode | (chan[channel].filt[filter].enabled ? SID3_FILTER_ENABLE : 0)); + + rWrite(SID3_REGISTER_FILT_CUTOFF_HIGH + filter * SID3_REGISTERS_PER_FILTER + channel*SID3_REGISTERS_PER_CHANNEL, + chan[channel].filt[filter].cutoff >> 8); + rWrite(SID3_REGISTER_FILT_CUTOFF_LOW + filter * SID3_REGISTERS_PER_FILTER + channel*SID3_REGISTERS_PER_CHANNEL, + chan[channel].filt[filter].cutoff & 0xff); + + rWrite(SID3_REGISTER_FILT_RESONANCE + filter * SID3_REGISTERS_PER_FILTER + channel*SID3_REGISTERS_PER_CHANNEL, + chan[channel].filt[filter].resonance); + + rWrite(SID3_REGISTER_FILT_DISTORTION + filter * SID3_REGISTERS_PER_FILTER + channel*SID3_REGISTERS_PER_CHANNEL, + chan[channel].filt[filter].distortion_level); + + rWrite(SID3_REGISTER_FILT_CONNECTION + filter * SID3_REGISTERS_PER_FILTER + channel*SID3_REGISTERS_PER_CHANNEL, + chan[channel].filt[filter].filter_matrix); + + rWrite(SID3_REGISTER_FILT_OUTPUT_VOLUME + filter * SID3_REGISTERS_PER_FILTER + channel*SID3_REGISTERS_PER_CHANNEL, + chan[channel].filt[filter].output_volume); } void DivPlatformSID3::updateFreq(int channel) @@ -252,6 +268,21 @@ int DivPlatformSID3::dispatch(DivCommand c) { chan[c.chan].ringSrc = ins->sid3.ring_mod_source; chan[c.chan].syncSrc = ins->sid3.sync_source; + + for(int j = 0; j < SID3_NUM_FILTERS; j++) + { + if(ins->sid3.filt[j].init) + { + chan[c.chan].filt[j].cutoff = ins->sid3.filt[j].cutoff; + chan[c.chan].filt[j].resonance = ins->sid3.filt[j].resonance; + chan[c.chan].filt[j].distortion_level = ins->sid3.filt[j].distortion_level; + chan[c.chan].filt[j].enabled = ins->sid3.filt[j].enabled; + chan[c.chan].filt[j].filter_matrix = ins->sid3.filt[j].filter_matrix; + chan[c.chan].filt[j].mode = ins->sid3.filt[j].mode; + chan[c.chan].filt[j].output_volume = ins->sid3.filt[j].output_volume; + updateFilter(c.chan, j); + } + } } if (chan[c.chan].insChanged || chan[c.chan].resetFilter) { /*chan[c.chan].filter=ins->c64.toFilter; @@ -377,7 +408,7 @@ void DivPlatformSID3::forceIns() { chan[i].keyOn=true; chan[i].freqChanged=true; } - updateFilter(i); + //updateFilter(i); } } @@ -438,13 +469,11 @@ void DivPlatformSID3::reset() { chan[i].std.setEngine(parent); chan[i].vol = SID3_MAX_VOL; - /*chan[i].filtControl = 7; - chan[i].filtRes = 0; - chan[i].filtCut = 4095; - - chan[i].noise_mode = 0;*/ - - //rWrite(0x3 + 7 * i,0xf0); + for(int j = 0; j < SID3_NUM_FILTERS; j++) + { + chan[i].filt[j].enabled = false; + updateFilter(i, j); + } } sid3_reset(sid3); diff --git a/src/engine/platform/sid3.h b/src/engine/platform/sid3.h index 3cb149cd5..8ddc2516b 100644 --- a/src/engine/platform/sid3.h +++ b/src/engine/platform/sid3.h @@ -36,6 +36,27 @@ class DivPlatformSID3: public DivDispatch { unsigned char mix_mode; unsigned char ringSrc, syncSrc, phaseSrc; int filtCut; + + struct Filter + { + unsigned short cutoff; + unsigned char resonance; + unsigned char output_volume; + unsigned char distortion_level; + unsigned char mode; + bool enabled; + unsigned char filter_matrix; + + Filter(): + cutoff(0), + resonance(0), + output_volume(0), + distortion_level(0), + mode(0), + enabled(false), + filter_matrix(0) {} + } filt[SID3_NUM_FILTERS]; + Channel(): SharedChannel(SID3_MAX_VOL), prevFreq(0x1ffff), @@ -69,10 +90,10 @@ class DivPlatformSID3: public DivDispatch { Channel chan[SID3_NUM_CHANNELS]; DivDispatchOscBuffer* oscBuf[SID3_NUM_CHANNELS]; struct QueuedWrite { - unsigned char addr; + unsigned short addr; unsigned char val; QueuedWrite(): addr(0), val(0) {} - QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {} + QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {} }; FixedQueue writes; @@ -87,7 +108,7 @@ class DivPlatformSID3: public DivDispatch { friend void putDispatchChan(void*,int,int); void updateFlags(int channel, bool gate); - void updateFilter(int channel); + void updateFilter(int channel, int filter); void updateFreq(int channel); void updateDuty(int channel); void updateEnvelope(int channel); diff --git a/src/engine/platform/sound/sid3.c b/src/engine/platform/sound/sid3.c index d305230cb..d771ca173 100644 --- a/src/engine/platform/sound/sid3.c +++ b/src/engine/platform/sound/sid3.c @@ -2497,7 +2497,22 @@ 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)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_set_filter_settings(sid3_filter* filt) +{ + const double pi = 3.1415926535897932385; + + // Multiply with 1.048576 to facilitate division by 1 000 000 by right- + // shifting 20 times (2 ^ 20 = 1048576). + filt->w0 = (2.0*pi*(float)filt->cutoff) / 500000.0 / 6.0; // "/ 12.0" bc we have 16 bit cutoff instead of 12-bit + + // Limit f0 to 16kHz to keep 1 cycle filter stable. + const float w0_max_1 = (2.0*pi*16000.0) / 500000.0; + filt->w0_ceil_1 = filt->w0 <= w0_max_1 ? filt->w0 : w0_max_1; + + filt->_1024_div_Q = (1.0/(0.707 + 3.0*(float)filt->resonance/(float)0x0ff)); +} + +void sid3_write(SID3* sid3, uint16_t address, uint8_t data) { SAFETY_HEADER @@ -2725,6 +2740,137 @@ void sid3_write(SID3* sid3, uint8_t address, uint8_t data) } break; } + case SID3_REGISTER_FILT_MODE: + case SID3_REGISTER_FILT_MODE + 1 * SID3_REGISTERS_PER_FILTER: + case SID3_REGISTER_FILT_MODE + 2 * SID3_REGISTERS_PER_FILTER: + case SID3_REGISTER_FILT_MODE + 3 * SID3_REGISTERS_PER_FILTER: + { + uint8_t filter = ((address % SID3_REGISTERS_PER_CHANNEL) - SID3_REGISTER_FILT_MODE) / SID3_REGISTERS_PER_FILTER; + + if(channel != SID3_NUM_CHANNELS - 1) + { + sid3->chan[channel].filt.filt[filter].mode = data; + //sid3_set_filter_settings(&sid3->chan[channel].filt.filt[filter]); + } + else + { + sid3->wave_chan.filt.filt[filter].mode = data; + //sid3_set_filter_settings(&sid3->wave_chan.filt.filt[filter]); + } + break; + } + case SID3_REGISTER_FILT_CUTOFF_HIGH: + case SID3_REGISTER_FILT_CUTOFF_HIGH + 1 * SID3_REGISTERS_PER_FILTER: + case SID3_REGISTER_FILT_CUTOFF_HIGH + 2 * SID3_REGISTERS_PER_FILTER: + case SID3_REGISTER_FILT_CUTOFF_HIGH + 3 * SID3_REGISTERS_PER_FILTER: + { + uint8_t filter = ((address % SID3_REGISTERS_PER_CHANNEL) - SID3_REGISTER_FILT_MODE) / SID3_REGISTERS_PER_FILTER; + + if(channel != SID3_NUM_CHANNELS - 1) + { + sid3->chan[channel].filt.filt[filter].cutoff &= 0x00ff; + sid3->chan[channel].filt.filt[filter].cutoff |= data << 8; + sid3_set_filter_settings(&sid3->chan[channel].filt.filt[filter]); + } + else + { + sid3->wave_chan.filt.filt[filter].cutoff &= 0x00ff; + sid3->wave_chan.filt.filt[filter].cutoff |= data << 8; + sid3_set_filter_settings(&sid3->wave_chan.filt.filt[filter]); + } + break; + } + case SID3_REGISTER_FILT_CUTOFF_LOW: + case SID3_REGISTER_FILT_CUTOFF_LOW + 1 * SID3_REGISTERS_PER_FILTER: + case SID3_REGISTER_FILT_CUTOFF_LOW + 2 * SID3_REGISTERS_PER_FILTER: + case SID3_REGISTER_FILT_CUTOFF_LOW + 3 * SID3_REGISTERS_PER_FILTER: + { + uint8_t filter = ((address % SID3_REGISTERS_PER_CHANNEL) - SID3_REGISTER_FILT_MODE) / SID3_REGISTERS_PER_FILTER; + + if(channel != SID3_NUM_CHANNELS - 1) + { + sid3->chan[channel].filt.filt[filter].cutoff &= 0xff00; + sid3->chan[channel].filt.filt[filter].cutoff |= data; + sid3_set_filter_settings(&sid3->chan[channel].filt.filt[filter]); + } + else + { + sid3->wave_chan.filt.filt[filter].cutoff &= 0xff00; + sid3->wave_chan.filt.filt[filter].cutoff |= data; + sid3_set_filter_settings(&sid3->wave_chan.filt.filt[filter]); + } + break; + } + case SID3_REGISTER_FILT_RESONANCE: + case SID3_REGISTER_FILT_RESONANCE + 1 * SID3_REGISTERS_PER_FILTER: + case SID3_REGISTER_FILT_RESONANCE + 2 * SID3_REGISTERS_PER_FILTER: + case SID3_REGISTER_FILT_RESONANCE + 3 * SID3_REGISTERS_PER_FILTER: + { + uint8_t filter = ((address % SID3_REGISTERS_PER_CHANNEL) - SID3_REGISTER_FILT_MODE) / SID3_REGISTERS_PER_FILTER; + + if(channel != SID3_NUM_CHANNELS - 1) + { + sid3->chan[channel].filt.filt[filter].resonance = data; + sid3_set_filter_settings(&sid3->chan[channel].filt.filt[filter]); + } + else + { + sid3->wave_chan.filt.filt[filter].resonance = data; + sid3_set_filter_settings(&sid3->wave_chan.filt.filt[filter]); + } + break; + } + case SID3_REGISTER_FILT_DISTORTION: + case SID3_REGISTER_FILT_DISTORTION + 1 * SID3_REGISTERS_PER_FILTER: + case SID3_REGISTER_FILT_DISTORTION + 2 * SID3_REGISTERS_PER_FILTER: + case SID3_REGISTER_FILT_DISTORTION + 3 * SID3_REGISTERS_PER_FILTER: + { + uint8_t filter = ((address % SID3_REGISTERS_PER_CHANNEL) - SID3_REGISTER_FILT_MODE) / SID3_REGISTERS_PER_FILTER; + + if(channel != SID3_NUM_CHANNELS - 1) + { + sid3->chan[channel].filt.filt[filter].distortion_level = data; + } + else + { + sid3->wave_chan.filt.filt[filter].distortion_level = data; + } + break; + } + case SID3_REGISTER_FILT_CONNECTION: + case SID3_REGISTER_FILT_CONNECTION + 1 * SID3_REGISTERS_PER_FILTER: + case SID3_REGISTER_FILT_CONNECTION + 2 * SID3_REGISTERS_PER_FILTER: + case SID3_REGISTER_FILT_CONNECTION + 3 * SID3_REGISTERS_PER_FILTER: + { + uint8_t filter = ((address % SID3_REGISTERS_PER_CHANNEL) - SID3_REGISTER_FILT_MODE) / SID3_REGISTERS_PER_FILTER; + + if(channel != SID3_NUM_CHANNELS - 1) + { + sid3->chan[channel].filt.connection_matrix[filter] = data; + } + else + { + sid3->wave_chan.filt.connection_matrix[filter] = data; + } + break; + } + case SID3_REGISTER_FILT_OUTPUT_VOLUME: + case SID3_REGISTER_FILT_OUTPUT_VOLUME + 1 * SID3_REGISTERS_PER_FILTER: + case SID3_REGISTER_FILT_OUTPUT_VOLUME + 2 * SID3_REGISTERS_PER_FILTER: + case SID3_REGISTER_FILT_OUTPUT_VOLUME + 3 * SID3_REGISTERS_PER_FILTER: + { + uint8_t filter = ((address % SID3_REGISTERS_PER_CHANNEL) - SID3_REGISTER_FILT_MODE) / SID3_REGISTERS_PER_FILTER; + + if(channel != SID3_NUM_CHANNELS - 1) + { + sid3->chan[channel].filt.filt[filter].output_volume = data; + } + else + { + sid3->wave_chan.filt.filt[filter].output_volume = data; + } + break; + } default: break; } } @@ -3016,6 +3162,90 @@ int32_t sid3_get_waveform(SID3* sid3, sid3_channel* ch) return wave; } +int32_t sid3_process_filters_block(sid3_channel* ch) +{ + int32_t output = 0; + + for(uint8_t i = 0; i < SID3_NUM_FILTERS; i++) + { + ch->filt.filt[i].input = 0; + } + + for(uint8_t i = 0; i < SID3_NUM_FILTERS; i++) + { + if(ch->filt.filt[i].mode & SID3_FILTER_CHANNEL_INPUT) + { + ch->filt.filt[i].input += ch->output_before_filter; + } + + for(uint8_t j = 0; j < SID3_NUM_FILTERS; j++) + { + if(ch->filt.connection_matrix[i] & (1 << j)) + { + ch->filt.filt[i].input += ch->filt.filt[j].output; + } + } + } + + for(uint8_t i = 0; i < SID3_NUM_FILTERS; i++) + { + if(ch->filt.filt[i].mode & SID3_FILTER_ENABLE) + { + float Vi = ch->filt.filt[i].input; + + float dVbp = (ch->filt.filt[i].w0_ceil_1 * ch->filt.filt[i].Vhp); + float dVlp = (ch->filt.filt[i].w0_ceil_1 * ch->filt.filt[i].Vbp); + ch->filt.filt[i].Vbp -= dVbp; + ch->filt.filt[i].Vlp -= dVlp; + ch->filt.filt[i].Vhp = (ch->filt.filt[i].Vbp * ch->filt.filt[i]._1024_div_Q) - ch->filt.filt[i].Vlp - Vi; + + float Vo; + + switch(ch->filt.filt[i].mode & SID3_FILTER_MODES_MASK) + { + case 0x0: + default: + Vo = 0; + break; + case SID3_FILTER_LP: + Vo = ch->filt.filt[i].Vlp; + break; + case SID3_FILTER_HP: + Vo = ch->filt.filt[i].Vhp; + break; + case SID3_FILTER_LP | SID3_FILTER_HP: + Vo = ch->filt.filt[i].Vlp + ch->filt.filt[i].Vhp; + break; + case SID3_FILTER_BP: + Vo = ch->filt.filt[i].Vbp; + break; + case SID3_FILTER_BP | SID3_FILTER_LP: + Vo = ch->filt.filt[i].Vlp + ch->filt.filt[i].Vbp; + break; + case SID3_FILTER_BP | SID3_FILTER_HP: + Vo = ch->filt.filt[i].Vhp + ch->filt.filt[i].Vbp; + break; + case SID3_FILTER_BP | SID3_FILTER_HP | SID3_FILTER_LP: + Vo = ch->filt.filt[i].Vlp + ch->filt.filt[i].Vbp + ch->filt.filt[i].Vhp; + break; + } + + ch->filt.filt[i].output = Vo * ch->filt.filt[i].output_volume / 0xff; + } + else + { + ch->filt.filt[i].output = 0; + } + + if(ch->filt.filt[i].mode & SID3_FILTER_OUTPUT) + { + output += ch->filt.filt[i].output; + } + } + + return output; +} + void sid3_clock(SID3* sid3) { //SAFETY_HEADER @@ -3066,10 +3296,25 @@ void sid3_clock(SID3* sid3) } sid3_adsr_clock(&ch->adsr); - sid3->output_l += sid3_adsr_output(&ch->adsr, waveform); - sid3->output_r += sid3_adsr_output(&ch->adsr, waveform); - sid3->channel_output[i] = sid3_adsr_output(&ch->adsr, waveform); + ch->output_before_filter = sid3_adsr_output(&ch->adsr, waveform); + + int32_t output = 0; + + if((ch->filt.filt[0].mode & SID3_FILTER_ENABLE) || (ch->filt.filt[1].mode & SID3_FILTER_ENABLE) || + (ch->filt.filt[2].mode & SID3_FILTER_ENABLE) || (ch->filt.filt[3].mode & SID3_FILTER_ENABLE)) + { + output = sid3_process_filters_block(ch); + } + else + { + output = ch->output_before_filter; + } + + sid3->output_l += output; + sid3->output_r += output; + + sid3->channel_output[i] = output; } } diff --git a/src/engine/platform/sound/sid3.h b/src/engine/platform/sound/sid3.h index 7092b976d..967ff057c 100644 --- a/src/engine/platform/sound/sid3.h +++ b/src/engine/platform/sound/sid3.h @@ -13,6 +13,7 @@ extern "C" { #define SID3_NUM_CHANNELS 7 #define SID3_NUM_FILTERS 4 #define SID3_REGISTERS_PER_CHANNEL 64 +#define SID3_REGISTERS_PER_FILTER 8 #define SID3_NUM_REGISTERS (SID3_NUM_CHANNELS * SID3_REGISTERS_PER_CHANNEL) #define SID3_MAX_VOL 255 @@ -57,6 +58,19 @@ enum Mixmodes SID3_MIX_SUM = 4, }; +enum Filter_modes +{ + SID3_FILTER_LP = 1, + SID3_FILTER_HP = 2, + SID3_FILTER_BP = 4, + + SID3_FILTER_MODES_MASK = 7, + + SID3_FILTER_ENABLE = 8, + SID3_FILTER_CHANNEL_INPUT = 16, //add channel input to filter input + SID3_FILTER_OUTPUT = 32, //output sound from this filter to channel output +}; + enum Registers { SID3_REGISTER_FLAGS = 0, @@ -84,6 +98,15 @@ enum Registers SID3_REGISTER_RING_MOD_SRC = 15, SID3_REGISTER_SYNC_SRC = 16, + + SID3_REGISTER_FILT_BASE = 17, + SID3_REGISTER_FILT_MODE = 17, + SID3_REGISTER_FILT_CUTOFF_HIGH = 18, + SID3_REGISTER_FILT_CUTOFF_LOW = 19, + SID3_REGISTER_FILT_RESONANCE = 20, + SID3_REGISTER_FILT_DISTORTION = 21, + SID3_REGISTER_FILT_CONNECTION = 22, + SID3_REGISTER_FILT_OUTPUT_VOLUME = 23, }; typedef struct @@ -107,14 +130,12 @@ typedef struct uint8_t mode; uint8_t output_volume; - - bool channel_output; //output to the channel master output } sid3_filter; typedef struct { sid3_filter filt[SID3_NUM_FILTERS]; - uint32_t connection_matrix; + uint8_t connection_matrix[SID3_NUM_FILTERS]; } sid3_filters_block; typedef struct @@ -158,6 +179,8 @@ typedef struct uint8_t panning_left, panning_right; bool invert_left, invert_right; //invert channel signal + + int32_t output_before_filter; } sid3_channel; typedef struct @@ -184,6 +207,8 @@ typedef struct uint8_t panning_left, panning_right; bool invert_left, invert_right; //invert channel signal + + int32_t output_before_filter; } sid3_wavetable_chan; typedef struct @@ -204,7 +229,7 @@ typedef struct SID3* sid3_create(); void sid3_reset(SID3* sid3); -void sid3_write(SID3* sid3, uint8_t address, uint8_t data); +void sid3_write(SID3* sid3, uint16_t address, uint8_t data); void sid3_clock(SID3* sid3); void sid3_set_is_muted(SID3* sid3, uint8_t ch, bool mute); void sid3_free(SID3* sid3); diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 8ca26f5eb..0f1af4f71 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -5631,19 +5631,19 @@ void FurnaceGUI::drawInsSID3(DivInstrument* ins) ins->c64.ringMod=ringMod; } - char buffer[20]; + char buffer[40]; if(ins->sid3.ring_mod_source == SID3_NUM_CHANNELS) { - snprintf(buffer, 20, _("Self")); + snprintf(buffer, 40, _("Self")); } else if(ins->sid3.ring_mod_source == SID3_NUM_CHANNELS - 1) { - snprintf(buffer, 20, _("PCM channel")); + snprintf(buffer, 40, _("PCM channel")); } else { - snprintf(buffer, 20, "%d", ins->sid3.ring_mod_source + 1); + snprintf(buffer, 40, "%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)); @@ -5653,7 +5653,7 @@ void FurnaceGUI::drawInsSID3(DivInstrument* ins) ins->c64.oscSync=oscSync; } - snprintf(buffer, 20, "%d", ins->sid3.sync_source + 1); + snprintf(buffer, 40, "%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; @@ -5661,6 +5661,77 @@ void FurnaceGUI::drawInsSID3(DivInstrument* ins) ins->sid3.phase_mod=phaseMod; } + for(int i = 0; i < SID3_NUM_FILTERS; i++) + { + DivInstrumentSID3::Filter* filt = &ins->sid3.filt[i]; + + bool enable=filt->enabled; + snprintf(buffer, 40, _("Enable filter %d"), i + 1); + if (ImGui::Checkbox(buffer,&enable)) { PARAMETER + filt->enabled=enable; + } + + if(filt->enabled) + { + bool init=filt->init; + snprintf(buffer, 40, _("Initialize filter %d"), i + 1); + if (ImGui::Checkbox(buffer,&init)) { PARAMETER + filt->init=init; + } + ImGui::SameLine(); + snprintf(buffer, 40, _("Connect to channel input##contoinput%d"), i + 1); + bool toInput=filt->mode & SID3_FILTER_CHANNEL_INPUT; + if (ImGui::Checkbox(buffer,&toInput)) { PARAMETER + filt->mode ^= SID3_FILTER_CHANNEL_INPUT; + } + + snprintf(buffer, 40, _("Cutoff##fcut%d"), i + 1); + P(CWSliderScalar(buffer,ImGuiDataType_U16,&filt->cutoff,&_ZERO,&_SIXTY_FIVE_THOUSAND_FIVE_HUNDRED_THIRTY_FIVE)); rightClickable + snprintf(buffer, 40, _("Resonance##fres%d"), i + 1); + P(CWSliderScalar(buffer,ImGuiDataType_U8,&filt->resonance,&_ZERO,&_TWO_HUNDRED_FIFTY_FIVE)); rightClickable + snprintf(buffer, 40, _("Output volume##foutvol%d"), i + 1); + P(CWSliderScalar(buffer,ImGuiDataType_U8,&filt->output_volume,&_ZERO,&_TWO_HUNDRED_FIFTY_FIVE)); rightClickable + + ImGui::AlignTextToFramePadding(); + ImGui::Text(_("Filter Mode")); + ImGui::SameLine(); + + bool lp=filt->mode & SID3_FILTER_LP; + pushToggleColors(lp); + snprintf(buffer, 40, _("low##flow%d"), i + 1); + if (ImGui::Button(buffer)) { PARAMETER + filt->mode ^= SID3_FILTER_LP; + } + popToggleColors(); + ImGui::SameLine(); + + bool bp=filt->mode & SID3_FILTER_BP; + pushToggleColors(bp); + snprintf(buffer, 40, _("band##fband%d"), i + 1); + if (ImGui::Button(buffer)) { PARAMETER + filt->mode ^= SID3_FILTER_BP; + } + popToggleColors(); + ImGui::SameLine(); + + bool hp=filt->mode & SID3_FILTER_HP; + pushToggleColors(hp); + snprintf(buffer, 40, _("high##fhigh%d"), i + 1); + if (ImGui::Button(buffer)) { PARAMETER + filt->mode ^= SID3_FILTER_HP; + } + popToggleColors(); + + + ImGui::SameLine(); + snprintf(buffer, 40, _("Connect to channel output##contooutput%d"), i + 1); + bool toOutput=filt->mode & SID3_FILTER_OUTPUT; + if (ImGui::Checkbox(buffer,&toOutput)) { PARAMETER + filt->mode ^= SID3_FILTER_OUTPUT; + } + } + } + ImGui::EndTabItem(); }