cutoff and resonance scaling and instrument save/load!

also mix minmod CPU usage variable initialization, and work a bit on Russian locale
This commit is contained in:
LTVA1 2024-08-16 17:37:07 +03:00
parent ba2f68f98c
commit 90e5fb79e5
27 changed files with 8068 additions and 7386 deletions

760
po/de.po

File diff suppressed because it is too large Load diff

760
po/es.po

File diff suppressed because it is too large Load diff

760
po/fi.po

File diff suppressed because it is too large Load diff

760
po/fr.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

760
po/hy.po

File diff suppressed because it is too large Load diff

760
po/id.po

File diff suppressed because it is too large Load diff

760
po/ja.po

File diff suppressed because it is too large Load diff

760
po/ko.po

File diff suppressed because it is too large Load diff

Binary file not shown.

760
po/nl.po

File diff suppressed because it is too large Load diff

760
po/pl.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

798
po/ru.po

File diff suppressed because it is too large Load diff

760
po/sk.po

File diff suppressed because it is too large Load diff

760
po/sv.po

File diff suppressed because it is too large Load diff

760
po/th.po

File diff suppressed because it is too large Load diff

760
po/tr.po

File diff suppressed because it is too large Load diff

760
po/uk.po

File diff suppressed because it is too large Load diff

760
po/zh.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -257,7 +257,6 @@ bool DivInstrumentESFM::Operator::operator==(const DivInstrumentESFM::Operator&
bool DivInstrumentSID3::operator==(const DivInstrumentSID3& other) {
return (
_C(volume) &&
_C(sr) &&
_C(lfsr_taps) &&
_C(phase_mod) &&
@ -293,10 +292,12 @@ bool DivInstrumentSID3::Filter::operator==(const DivInstrumentSID3::Filter& othe
_C(bindCutoffToNoteStrength) &&
_C(bindCutoffToNoteCenter) &&
_C(bindCutoffToNoteDir) &&
_C(bindCutoffOnNote) &&
_C(bindResonanceToNote) &&
_C(bindResonanceToNoteStrength) &&
_C(bindResonanceToNoteCenter) &&
_C(bindResonanceToNoteDir)
_C(bindResonanceToNoteDir) &&
_C(bindResonanceOnNote)
);
}
@ -903,6 +904,55 @@ void DivInstrument::writeFeatureS3(SafeWriter* w) {
w->writeC(sid3.sr);
w->writeC(c64.r);
w->writeC(
(sid3.phase_mod?0x80:0)|
(sid3.specialWaveOn?0x40:0)|
(sid3.oneBitNoise?0x20:0)|
(sid3.separateNoisePitch?0x10:0)|
(sid3.doWavetable?8:0)
);
w->writeI(sid3.lfsr_taps);
w->writeC(sid3.phase_mod_source);
w->writeC(sid3.ring_mod_source);
w->writeC(sid3.sync_source);
w->writeC(sid3.special_wave);
w->writeC(sid3.phaseInv);
w->writeC(sid3.feedback);
w->writeC(4); //number of filters
for(int i = 0; i < 4; i++)
{
w->writeC(
(sid3.filt[i].enabled?0x80:0)|
(sid3.filt[i].init?0x40:0)|
(sid3.filt[i].absoluteCutoff?0x20:0)|
(sid3.filt[i].bindCutoffToNote?0x10:0)|
(sid3.filt[i].bindCutoffToNoteDir?8:0)|
(sid3.filt[i].bindCutoffOnNote?4:0)|
(sid3.filt[i].bindResonanceToNote?2:0)|
(sid3.filt[i].bindResonanceToNoteDir?1:0)
);
w->writeC(
(sid3.filt[i].bindResonanceOnNote?0x80:0)
);
w->writeS(sid3.filt[i].cutoff);
w->writeC(sid3.filt[i].resonance);
w->writeC(sid3.filt[i].output_volume);
w->writeC(sid3.filt[i].distortion_level);
w->writeC(sid3.filt[i].mode);
w->writeC(sid3.filt[i].filter_matrix);
w->writeC(sid3.filt[i].bindCutoffToNoteStrength);
w->writeC(sid3.filt[i].bindCutoffToNoteCenter);
w->writeC(sid3.filt[i].bindResonanceToNoteStrength);
w->writeC(sid3.filt[i].bindResonanceToNoteCenter);
}
FEATURE_END;
}
@ -1730,7 +1780,14 @@ void DivInstrument::readFeature64(SafeReader& reader, bool& volIsCutoff, short v
c64.r=next&15;
}
c64.duty=reader.readS()&4095;
if(type == DIV_INS_SID3)
{
c64.duty = reader.readS();
}
else
{
c64.duty=reader.readS()&4095;
}
unsigned short cr=reader.readS();
c64.cut=cr&4095;
@ -2278,6 +2335,55 @@ void DivInstrument::readFeatureS3(SafeReader& reader, short version) {
sid3.sr=reader.readC();
c64.r=reader.readC();
unsigned char next = reader.readC();
sid3.phase_mod = next&0x80;
sid3.specialWaveOn = next&0x40;
sid3.oneBitNoise = next&0x20;
sid3.separateNoisePitch = next&0x10;
sid3.doWavetable = next&8;
sid3.lfsr_taps = reader.readI();
sid3.phase_mod_source = reader.readC();
sid3.ring_mod_source = reader.readC();
sid3.sync_source = reader.readC();
sid3.special_wave = reader.readC();
sid3.phaseInv = reader.readC();
sid3.feedback = reader.readC();
unsigned char numFilters = reader.readC();
for(int i = 0; i < numFilters; i++)
{
next = reader.readC();
sid3.filt[i].enabled = next&0x80;
sid3.filt[i].init = next&0x40;
sid3.filt[i].absoluteCutoff = next&0x20;
sid3.filt[i].bindCutoffToNote = next&0x10;
sid3.filt[i].bindCutoffToNoteDir = next&8;
sid3.filt[i].bindCutoffOnNote = next&4;
sid3.filt[i].bindResonanceToNote = next&2;
sid3.filt[i].bindResonanceToNoteDir = next&1;
next = reader.readC();
sid3.filt[i].bindResonanceOnNote = next&0x80;
sid3.filt[i].cutoff = reader.readS();
sid3.filt[i].resonance = reader.readC();
sid3.filt[i].output_volume = reader.readC();
sid3.filt[i].distortion_level = reader.readC();
sid3.filt[i].mode = reader.readC();
sid3.filt[i].filter_matrix = reader.readC();
sid3.filt[i].bindCutoffToNoteStrength = reader.readC();
sid3.filt[i].bindCutoffToNoteCenter = reader.readC();
sid3.filt[i].bindResonanceToNoteStrength = reader.readC();
sid3.filt[i].bindResonanceToNoteCenter = reader.readC();
}
READ_FEAT_END;
}

View file

@ -864,7 +864,6 @@ struct DivInstrumentSID2 {
struct DivInstrumentSID3
{
unsigned char volume;
unsigned char sr;
unsigned int lfsr_taps;
bool phase_mod;
@ -894,11 +893,13 @@ struct DivInstrumentSID3
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 bindCutoffOnNote; //only do cutoff scaling once, on new note
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 bindResonanceOnNote; //only do resonance scaling once, on new note
bool operator==(const Filter& other);
bool operator!=(const Filter& other)
@ -919,10 +920,12 @@ struct DivInstrumentSID3
bindCutoffToNoteStrength(0),
bindCutoffToNoteCenter(0),
bindCutoffToNoteDir(false),
bindCutoffOnNote(false),
bindResonanceToNote(false),
bindResonanceToNoteStrength(0),
bindResonanceToNoteCenter(0),
bindResonanceToNoteDir(false) {}
bindResonanceToNoteDir(false),
bindResonanceOnNote(false) {}
} filt[4];
bool operator==(const DivInstrumentSID3& other);
@ -931,7 +934,6 @@ struct DivInstrumentSID3
return !(*this==other);
}
DivInstrumentSID3():
volume(255),
sr(0),
lfsr_taps(0),
phase_mod(false),

View file

@ -771,6 +771,8 @@ int DivPlatformGBAMinMod::init(DivEngine* p, int channels, int sugRate, const Di
setFlags(flags);
reset();
maxCPU = 0.0; //initialize!
return 16;
}

View file

@ -28,6 +28,10 @@
#define CHIP_FREQBASE 524288
#define CHIP_DIVIDER 1
#define CURRENT_FREQ_IN_HZ() ((double)chipClock / pow(2.0, (double)SID3_ACC_BITS) * (double)chan[i].freq)
#define c_5_FREQ() (parent->song.tuning / pow(2, (12.0 * 9.0 + 9.0) / 12.0))
#define FREQ_FOR_NOTE(note) (c_5_FREQ() * pow(2, (double)note / 12.0))
const char* regCheatSheetSID3[]={
"FreqL0", "00",
"FreqH0", "01",
@ -278,6 +282,8 @@ void DivPlatformSID3::tick(bool sysTick)
{
chan[i].std.next();
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SID3);
bool panChanged = false;
bool flagsChanged = false;
bool envChanged = false;
@ -507,7 +513,6 @@ void DivPlatformSID3::tick(bool sysTick)
for(int j = 0; j < SID3_NUM_FILTERS; j++) //filter macros
{
DivMacroInt::IntOp* op = &chan[i].std.op[j];
DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_SID3);
DivPlatformSID3::Channel::Filter* ch_filt = &chan[i].filt[j];
DivInstrumentSID3::Filter* ins_filt = &ins->sid3.filt[j];
@ -634,6 +639,50 @@ void DivPlatformSID3::tick(bool sysTick)
if (chan[i].freq>0xffffff) chan[i].freq=0xffffff;
updateFreq(i);
for(int j = 0; j < SID3_NUM_FILTERS; j++)
{
bool doUpdateFilter = false;
if(chan[i].filt[j].bindCutoffToNote && (!ins->sid3.filt[j].bindCutoffOnNote || chan[i].keyOn))
{
double scaling = CURRENT_FREQ_IN_HZ() / FREQ_FOR_NOTE(chan[i].filt[j].bindCutoffToNoteCenter) - 1.0;
if (chan[i].filt[j].bindCutoffToNoteDir)
{
scaling *= -1.0;
}
int cutoff = ins->sid3.filt[j].cutoff + (int)(scaling * (double)chan[i].filt[j].bindCutoffToNoteStrength * 80.0);
if(cutoff > 0xffff) cutoff = 0xffff;
if(cutoff < 0) cutoff = 0;
chan[i].filt[j].cutoff = cutoff;
doUpdateFilter = true;
}
if(chan[i].filt[j].bindResonanceToNote && (!ins->sid3.filt[j].bindResonanceOnNote || chan[i].keyOn))
{
double scaling = CURRENT_FREQ_IN_HZ() / FREQ_FOR_NOTE(chan[i].filt[j].bindResonanceToNoteCenter) - 1.0;
if (chan[i].filt[j].bindResonanceToNoteDir)
{
scaling *= -1.0;
}
int res = ins->sid3.filt[j].resonance + (int)(scaling * (double)chan[i].filt[j].bindResonanceToNoteStrength * 80.0 / 256.0);
if(res > 0xff) res = 0xff;
if(res < 0) res = 0;
chan[i].filt[j].resonance = res;
doUpdateFilter = true;
}
if(doUpdateFilter)
{
updateFilter(i, j);
}
}
if (chan[i].pcm && i == SID3_NUM_CHANNELS - 1) {
double off=1.0;
@ -803,6 +852,17 @@ int DivPlatformSID3::dispatch(DivCommand c) {
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;
chan[c.chan].filt[j].bindCutoffToNote = ins->sid3.filt[j].bindCutoffToNote;
chan[c.chan].filt[j].bindCutoffToNoteStrength = ins->sid3.filt[j].bindCutoffToNoteStrength;
chan[c.chan].filt[j].bindCutoffToNoteCenter = ins->sid3.filt[j].bindCutoffToNoteCenter;
chan[c.chan].filt[j].bindCutoffToNoteDir = ins->sid3.filt[j].bindCutoffToNoteDir;
chan[c.chan].filt[j].bindResonanceToNote = ins->sid3.filt[j].bindResonanceToNote;
chan[c.chan].filt[j].bindResonanceToNoteStrength = ins->sid3.filt[j].bindResonanceToNoteStrength;
chan[c.chan].filt[j].bindResonanceToNoteCenter = ins->sid3.filt[j].bindResonanceToNoteCenter;
chan[c.chan].filt[j].bindResonanceToNoteDir = ins->sid3.filt[j].bindResonanceToNoteDir;
updateFilter(c.chan, j);
}
}

View file

@ -54,6 +54,16 @@ class DivPlatformSID3: public DivDispatch {
short cutoff_slide;
bool bindCutoffToNote; //cutoff scaling
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
Filter():
cutoff(0),
resonance(0),
@ -62,7 +72,15 @@ class DivPlatformSID3: public DivDispatch {
mode(0),
enabled(false),
filter_matrix(0),
cutoff_slide(0) {}
cutoff_slide(0),
bindCutoffToNote(false),
bindCutoffToNoteStrength(0),
bindCutoffToNoteCenter(0),
bindCutoffToNoteDir(false),
bindResonanceToNote(false),
bindResonanceToNoteStrength(0),
bindResonanceToNoteCenter(0),
bindResonanceToNoteDir(false) {}
} filt[SID3_NUM_FILTERS];
int noise_baseNoteOverride;

View file

@ -6166,6 +6166,12 @@ void FurnaceGUI::drawInsSID3(DivInstrument* ins)
{
ImGui::SetTooltip(_("How much cutoff changes for given pitch change."));
}
snprintf(buffer, 100, _("Scale cutoff only once on new note##bindcutnn%d"), i + 1);
P(ImGui::Checkbox(buffer,&filt->bindCutoffOnNote));
if (ImGui::IsItemHovered())
{
ImGui::SetTooltip(_("Filter cutoff will be changed only once on new note.\nIf this option is disabled, cutoff scaling will be applied\nevery time a pitch change happens."));
}
}
snprintf(buffer, 100, _("Change resonance with pitch##bindres%d"), i + 1);
@ -6199,6 +6205,12 @@ void FurnaceGUI::drawInsSID3(DivInstrument* ins)
{
ImGui::SetTooltip(_("How much resonance changes for given pitch change."));
}
snprintf(buffer, 100, _("Scale resonance only once on new note##bindresnn%d"), i + 1);
P(ImGui::Checkbox(buffer,&filt->bindResonanceOnNote));
if (ImGui::IsItemHovered())
{
ImGui::SetTooltip(_("Filter resonance will be changed only once on new note.\nIf this option is disabled, resonance scaling will be applied\nevery time a pitch change happens."));
}
}
}
}