mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-26 14:33:01 +00:00
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:
parent
2fb518231a
commit
bfbc92e1f3
6 changed files with 145 additions and 9 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in a new issue