mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-24 05:25:12 +00:00
Lynx: add sample support!
This commit is contained in:
parent
f8794ae9a4
commit
1811a95e76
3 changed files with 71 additions and 16 deletions
|
@ -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);
|
||||
|
|
|
@ -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) {}
|
||||
};
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue