Add LFSR feedback bits, 1-bit noise and wave mix mode macros. I hope I am done with main macros now

This commit is contained in:
LTVA1 2024-08-05 15:50:48 +03:00
parent 2fb518231a
commit bfbc92e1f3
6 changed files with 145 additions and 9 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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));