Lynx: add sample support!

This commit is contained in:
tildearrow 2022-05-26 00:29:04 -05:00
parent f8794ae9a4
commit 1811a95e76
3 changed files with 71 additions and 16 deletions

View File

@ -142,7 +142,30 @@ const char* DivPlatformLynx::getEffectName(unsigned char effect) {
}
void DivPlatformLynx::acquire(short* bufL, short* bufR, size_t start, size_t len) {
mikey->sampleAudio( bufL + start, bufR + start, len, oscBuf );
for (size_t h=start; h<start+len; h++) {
for (int i=0; i<4; i++) {
if (chan[i].pcm && chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
chan[i].sampleAccum-=chan[i].sampleFreq;
if (chan[i].sampleAccum<0) {
chan[i].sampleAccum+=rate;
DivSample* s=parent->getSample(chan[i].sample);
if (s!=NULL) {
if (isMuted[i]) {
WRITE_VOLUME(i,0);
chan[i].samplePos++;
} else {
WRITE_VOLUME(i,s->data8[chan[i].samplePos++]);
}
if (chan[i].samplePos>=(int)s->samples) {
chan[i].sample=-1;
}
}
}
}
}
mikey->sampleAudio( bufL + h, bufR + h, 1, oscBuf );
}
}
void DivPlatformLynx::tick(bool sysTick) {
@ -203,18 +226,35 @@ void DivPlatformLynx::tick(bool sysTick) {
}
if (chan[i].freqChanged) {
if (chan[i].lfsr >= 0) {
WRITE_LFSR(i, (chan[i].lfsr&0xff));
WRITE_OTHER(i, ((chan[i].lfsr&0xf00)>>4));
chan[i].lfsr=-1;
if (chan[i].pcm) {
double off=1.0;
if (chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[i].sample);
if (s->centerRate<1) {
off=1.0;
} else {
off=(double)s->centerRate/8363.0;
}
}
chan[i].sampleFreq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,2,chan[i].pitch2,off,1);
WRITE_LFSR(i,0);
WRITE_OTHER(i,0);
WRITE_CONTROL(i,0x18);
WRITE_BACKUP(i,2);
} else {
if (chan[i].lfsr >= 0) {
WRITE_LFSR(i, (chan[i].lfsr&0xff));
WRITE_OTHER(i, ((chan[i].lfsr&0xf00)>>4));
chan[i].lfsr=-1;
}
chan[i].fd=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
if (chan[i].std.duty.had) {
chan[i].duty=chan[i].std.duty.val;
WRITE_FEEDBACK(i, chan[i].duty.feedback);
}
WRITE_CONTROL(i, (chan[i].fd.clockDivider|0x18|chan[i].duty.int_feedback7));
WRITE_BACKUP( i, chan[i].fd.backup );
}
chan[i].fd=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
if (chan[i].std.duty.had) {
chan[i].duty=chan[i].std.duty.val;
WRITE_FEEDBACK(i, chan[i].duty.feedback);
}
WRITE_CONTROL(i, (chan[i].fd.clockDivider|0x18|chan[i].duty.int_feedback7));
WRITE_BACKUP( i, chan[i].fd.backup );
chan[i].freqChanged=false;
} else if (chan[i].std.duty.had) {
chan[i].duty = chan[i].std.duty.val;
@ -226,9 +266,17 @@ void DivPlatformLynx::tick(bool sysTick) {
int DivPlatformLynx::dispatch(DivCommand c) {
switch (c.cmd) {
case DIV_CMD_NOTE_ON:
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_MIKEY);
chan[c.chan].pcm=(ins->type==DIV_INS_AMIGA);
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
if (chan[c.chan].pcm) {
chan[c.chan].sampleBaseFreq=parent->calcBaseFreq(1.0,1.0,c.value,false);
chan[c.chan].sample=ins->amiga.getSample(c.value);
chan[c.chan].sampleAccum=0;
chan[c.chan].samplePos=0;
}
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
chan[c.chan].actualNote=c.value;
@ -239,6 +287,7 @@ int DivPlatformLynx::dispatch(DivCommand c) {
WRITE_VOLUME(c.chan,(isMuted[c.chan]?0:(chan[c.chan].vol&127)));
chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_MIKEY));
break;
}
case DIV_CMD_NOTE_OFF:
chan[c.chan].active=false;
WRITE_VOLUME(c.chan, 0);

View File

@ -44,9 +44,9 @@ class DivPlatformLynx: public DivDispatch {
DivMacroInt std;
MikeyFreqDiv fd;
MikeyDuty duty;
int baseFreq, pitch, pitch2, note, actualNote, lfsr, ins;
int baseFreq, pitch, pitch2, note, actualNote, lfsr, ins, sample, samplePos, sampleAccum, sampleBaseFreq, sampleFreq;
unsigned char pan;
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta;
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, pcm;
signed char vol, outVol;
void macroInit(DivInstrument* which) {
std.init(which);
@ -63,6 +63,11 @@ class DivPlatformLynx: public DivDispatch {
actualNote(0),
lfsr(-1),
ins(-1),
sample(-1),
samplePos(0),
sampleAccum(0),
sampleBaseFreq(0),
sampleFreq(0),
pan(0xff),
active(false),
insChanged(true),
@ -70,6 +75,7 @@ class DivPlatformLynx: public DivDispatch {
keyOn(false),
keyOff(false),
inPorta(false),
pcm(false),
vol(127),
outVol(127) {}
};

View File

@ -1655,7 +1655,7 @@ void DivEngine::registerSystems() {
{"CH1", "CH2", "CH3", "CH4"},
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
{DIV_INS_MIKEY, DIV_INS_MIKEY, DIV_INS_MIKEY, DIV_INS_MIKEY},
{},
{DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA},
[](int,unsigned char,unsigned char) -> bool {return false;},
[this](int ch, unsigned char effect, unsigned char effectVal) -> bool {
if (effect>=0x30 && effect<0x40) {