From bfbc92e1f313005f1c0a1d2b306ce0b9d25ee600 Mon Sep 17 00:00:00 2001 From: LTVA1 <87536432+LTVA1@users.noreply.github.com> Date: Mon, 5 Aug 2024 15:50:48 +0300 Subject: [PATCH] Add LFSR feedback bits, 1-bit noise and wave mix mode macros. I hope I am done with main macros now --- src/engine/instrument.cpp | 39 +++++++++++++++++++++++----- src/engine/instrument.h | 23 ++++++++++++++++- src/engine/platform/sid3.cpp | 32 +++++++++++++++++++++++ src/engine/platform/sid3.h | 8 ++++-- src/engine/platform/sound/sid3.c | 44 ++++++++++++++++++++++++++++++++ src/gui/insEdit.cpp | 8 ++++++ 6 files changed, 145 insertions(+), 9 deletions(-) diff --git a/src/engine/instrument.cpp b/src/engine/instrument.cpp index 5706b260c..eb680e203 100644 --- a/src/engine/instrument.cpp +++ b/src/engine/instrument.cpp @@ -283,7 +283,16 @@ bool DivInstrumentSID3::Filter::operator==(const DivInstrumentSID3::Filter& othe _C(mode) && _C(enabled) && _C(init) && - _C(filter_matrix) + _C(filter_matrix) && + _C(absoluteCutoff) && + _C(bindCutoffToNote) && + _C(bindCutoffToNoteStrength) && + _C(bindCutoffToNoteCenter) && + _C(bindCutoffToNoteDir) && + _C(bindResonanceToNote) && + _C(bindResonanceToNoteStrength) && + _C(bindResonanceToNoteCenter) && + _C(bindResonanceToNoteDir) ); } @@ -884,6 +893,12 @@ void DivInstrument::writeFeatureS2(SafeWriter* w) { void DivInstrument::writeFeatureS3(SafeWriter* w) { FEATURE_BEGIN("S3"); + w->writeC(c64.a); + w->writeC(c64.d); + w->writeC(c64.s); + w->writeC(sid3.sr); + w->writeC(c64.r); + FEATURE_END; } @@ -1696,12 +1711,20 @@ void DivInstrument::readFeature64(SafeReader& reader, bool& volIsCutoff, short v c64.lp=next&1; next=reader.readC(); - c64.a=(next>>4)&15; - c64.d=next&15; + + if(type != DIV_INS_SID3) + { + c64.a=(next>>4)&15; + c64.d=next&15; + } next=reader.readC(); - c64.s=(next>>4)&15; - c64.r=next&15; + + if(type != DIV_INS_SID3) + { + c64.s=(next>>4)&15; + c64.r=next&15; + } c64.duty=reader.readS()&4095; @@ -2238,7 +2261,11 @@ void DivInstrument::readFeatureS2(SafeReader& reader, short version) { void DivInstrument::readFeatureS3(SafeReader& reader, short version) { READ_FEAT_BEGIN; - + c64.a=reader.readC(); + c64.d=reader.readC(); + c64.s=reader.readC(); + sid3.sr=reader.readC(); + c64.r=reader.readC(); READ_FEAT_END; } diff --git a/src/engine/instrument.h b/src/engine/instrument.h index 9ae772c07..9abaec35d 100644 --- a/src/engine/instrument.h +++ b/src/engine/instrument.h @@ -884,6 +884,18 @@ struct DivInstrumentSID3 bool init; unsigned char filter_matrix; + //this is done purely in software + bool absoluteCutoff; + bool bindCutoffToNote; + unsigned char bindCutoffToNoteStrength; //how much cutoff changes over e.g. 1 semitone + unsigned char bindCutoffToNoteCenter; //central note of the cutoff change + bool bindCutoffToNoteDir; //if we decrease or increase cutoff if e.g. we go upper in note space + + bool bindResonanceToNote; + unsigned char bindResonanceToNoteStrength; //how much resonance changes over e.g. 1 semitone + unsigned char bindResonanceToNoteCenter; //central note of the resonance change + bool bindResonanceToNoteDir; //if we decrease or increase resonance if e.g. we go upper in note space + bool operator==(const Filter& other); bool operator!=(const Filter& other) { @@ -897,7 +909,16 @@ struct DivInstrumentSID3 mode(0), enabled(false), init(false), - filter_matrix(0) {} + filter_matrix(0), + absoluteCutoff(false), + bindCutoffToNote(false), + bindCutoffToNoteStrength(0), + bindCutoffToNoteCenter(0), + bindCutoffToNoteDir(false), + bindResonanceToNote(false), + bindResonanceToNoteStrength(0), + bindResonanceToNoteCenter(0), + bindResonanceToNoteDir(false) {} } filt[4]; bool operator==(const DivInstrumentSID3& other); diff --git a/src/engine/platform/sid3.cpp b/src/engine/platform/sid3.cpp index 40981f328..881b0ffa3 100644 --- a/src/engine/platform/sid3.cpp +++ b/src/engine/platform/sid3.cpp @@ -149,6 +149,14 @@ void DivPlatformSID3::updateNoiseFreq(int channel) rWrite(SID3_REGISTER_NOISE_FREQ_LOW + channel*SID3_REGISTERS_PER_CHANNEL,chan[channel].noiseFreq & 0xff); } +void DivPlatformSID3::updateNoiseLFSRMask(int channel) +{ + rWrite(SID3_REGISTER_NOISE_LFSR_HIGHEST + channel*SID3_REGISTERS_PER_CHANNEL,(chan[channel].noiseLFSRMask >> 24) & 0xff); + rWrite(SID3_REGISTER_NOISE_LFSR_HIGH + channel*SID3_REGISTERS_PER_CHANNEL,(chan[channel].noiseLFSRMask >> 16) & 0xff); + rWrite(SID3_REGISTER_NOISE_LFSR_MID + channel*SID3_REGISTERS_PER_CHANNEL,(chan[channel].noiseLFSRMask >> 8) & 0xff); + rWrite(SID3_REGISTER_NOISE_LFSR_LOW + channel*SID3_REGISTERS_PER_CHANNEL,chan[channel].noiseLFSRMask & 0xff); +} + void DivPlatformSID3::updateDuty(int channel) { rWrite(SID3_REGISTER_PW_HIGH + channel*SID3_REGISTERS_PER_CHANNEL,(chan[channel].duty >> 8) & 0xff); @@ -302,6 +310,28 @@ void DivPlatformSID3::tick(bool sysTick) chan[i].release = chan[i].std.ex6.val & 0xff; envChanged = true; } + if (chan[i].std.ex7.had) { //noise LFSR feedback bits + chan[i].noiseLFSRMask = chan[i].std.ex7.val & 0x3fffffff; + updateNoiseLFSRMask(i); + } + if (chan[i].std.op[1].ar.had) { //1-bit noise / PCM mode for wavetable chan + if(i == SID3_NUM_CHANNELS - 1) //wave chan + { + rWrite(SID3_REGISTER_WAVEFORM + i * SID3_REGISTERS_PER_CHANNEL, chan[i].std.op[1].ar.val & 1); + } + else + { + if((uint32_t)chan[i].oneBitNoise != (chan[i].std.op[1].ar.val & 1)) + { + chan[i].oneBitNoise = chan[i].std.op[1].ar.val & 1; + flagsChanged = true; + } + } + } + if (chan[i].std.ex8.had) { //wave mix mode + chan[i].mix_mode = chan[i].std.ex8.val & 0xff; + rWrite(SID3_REGISTER_MIXMODE + i * SID3_REGISTERS_PER_CHANNEL, chan[i].mix_mode); //mixmode + } if(panChanged) { @@ -677,6 +707,8 @@ void DivPlatformSID3::reset() { chan[i].freq = chan[i].noiseFreq = 0; updatePanning(i); + + chan[i].noiseLFSRMask = (1 << 29) | (1 << 5) | (1 << 3) | 1; //https://docs.amd.com/v/u/en-US/xapp052 for 30 bits: 30, 6, 4, 1 } sid3_reset(sid3); diff --git a/src/engine/platform/sid3.h b/src/engine/platform/sid3.h index 268d58b11..31284f06c 100644 --- a/src/engine/platform/sid3.h +++ b/src/engine/platform/sid3.h @@ -37,8 +37,9 @@ class DivPlatformSID3: public DivDispatch { unsigned char mix_mode; unsigned char ringSrc, syncSrc, phaseSrc; unsigned char panLeft, panRight; - unsigned int noiseFreq; + int noiseFreq; bool independentNoiseFreq; + unsigned int noiseLFSRMask; struct Filter { @@ -154,7 +155,8 @@ class DivPlatformSID3: public DivDispatch { panLeft(0xff), panRight(0xff), noiseFreq(0), - independentNoiseFreq(false) {} + independentNoiseFreq(false), + noiseLFSRMask((1 << 29) | (1 << 5) | (1 << 3) | 1) {} //https://docs.amd.com/v/u/en-US/xapp052 for 30 bits: 30, 6, 4, 1 }; Channel chan[SID3_NUM_CHANNELS]; DivDispatchOscBuffer* oscBuf[SID3_NUM_CHANNELS]; @@ -180,9 +182,11 @@ class DivPlatformSID3: public DivDispatch { void updateFilter(int channel, int filter); void updateFreq(int channel); void updateNoiseFreq(int channel); + void updateNoiseLFSRMask(int channel); void updateDuty(int channel); void updateEnvelope(int channel); void updatePanning(int channel); + public: void acquire(short** buf, size_t len); int dispatch(DivCommand c); diff --git a/src/engine/platform/sound/sid3.c b/src/engine/platform/sound/sid3.c index 2259461b1..fe07e9b9c 100644 --- a/src/engine/platform/sound/sid3.c +++ b/src/engine/platform/sound/sid3.c @@ -3433,6 +3433,50 @@ void sid3_write(SID3* sid3, uint16_t address, uint8_t data) } break; } + case SID3_REGISTER_NOISE_LFSR_HIGHEST: + { + if(channel != SID3_NUM_CHANNELS - 1) + { + sid3->chan[channel].lfsr_taps &= 0x00ffffff; + sid3->chan[channel].lfsr_taps |= (uint32_t)data << 24; + + sid3->chan[channel].lfsr_taps &= 0x3fffffff; //30 bits limit + } + break; + } + case SID3_REGISTER_NOISE_LFSR_HIGH: + { + if(channel != SID3_NUM_CHANNELS - 1) + { + sid3->chan[channel].lfsr_taps &= 0xff00ffff; + sid3->chan[channel].lfsr_taps |= data << 16; + + sid3->chan[channel].lfsr_taps &= 0x3fffffff; + } + break; + } + case SID3_REGISTER_NOISE_LFSR_MID: + { + if(channel != SID3_NUM_CHANNELS - 1) + { + sid3->chan[channel].lfsr_taps &= 0xffff00ff; + sid3->chan[channel].lfsr_taps |= data << 8; + + sid3->chan[channel].lfsr_taps &= 0x3fffffff; + } + break; + } + case SID3_REGISTER_NOISE_LFSR_LOW: + { + if(channel != SID3_NUM_CHANNELS - 1) + { + sid3->chan[channel].lfsr_taps &= 0xffffff00; + sid3->chan[channel].lfsr_taps |= data; + + sid3->chan[channel].lfsr_taps &= 0x3fffffff; + } + break; + } default: break; } } diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 5e640dcd8..43f7b796c 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -6057,6 +6057,12 @@ void FurnaceGUI::drawInsSID3(DivInstrument* ins) if (ImGui::Checkbox(buffer,&toOutput)) { PARAMETER filt->mode ^= SID3_FILTER_OUTPUT; } + + snprintf(buffer, 40, _("Absolute cutoff macro##abscutoff%d"), i + 1); + bool absCutoff=filt->absoluteCutoff; + if (ImGui::Checkbox(buffer,&absCutoff)) { PARAMETER + filt->absoluteCutoff = !filt->absoluteCutoff; + } } } @@ -6159,6 +6165,8 @@ void FurnaceGUI::drawInsSID3(DivInstrument* ins) if (ImGui::BeginTabItem(_("Macros"))) { + ImGui::Text("Size of DivInstrument is too high... exactly %d bytes, of which SID3 shit takes %d bytes", sizeof(DivInstrument), sizeof(DivInstrumentSID3)); + macroList.push_back(FurnaceGUIMacroDesc(_("Volume"),&ins->std.volMacro,0,255,160,uiColors[GUI_COLOR_MACRO_VOLUME])); macroList.push_back(FurnaceGUIMacroDesc(_("Arpeggio"),&ins->std.arpMacro,-120,120,160,uiColors[GUI_COLOR_MACRO_PITCH],true,NULL,macroHoverNote,false,NULL,true,ins->std.arpMacro.val));