From 1811a95e76468a899cc20ddcd329f75acd295deb Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 26 May 2022 00:29:04 -0500 Subject: [PATCH] Lynx: add sample support! --- src/engine/platform/lynx.cpp | 75 +++++++++++++++++++++++++++++------- src/engine/platform/lynx.h | 10 ++++- src/engine/sysDef.cpp | 2 +- 3 files changed, 71 insertions(+), 16 deletions(-) diff --git a/src/engine/platform/lynx.cpp b/src/engine/platform/lynx.cpp index 8c835fcc9..ae24312ed 100644 --- a/src/engine/platform/lynx.cpp +++ b/src/engine/platform/lynx.cpp @@ -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=0 && chan[i].samplesong.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].samplesong.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); diff --git a/src/engine/platform/lynx.h b/src/engine/platform/lynx.h index fab8b0f82..4f221d037 100644 --- a/src/engine/platform/lynx.h +++ b/src/engine/platform/lynx.h @@ -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) {} }; diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index 3399c67a1..9f3ded99f 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -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) {