Lynx: add sample support!
This commit is contained in:
parent
f8794ae9a4
commit
1811a95e76
|
|
@ -142,7 +142,30 @@ const char* DivPlatformLynx::getEffectName(unsigned char effect) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformLynx::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
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) {
|
void DivPlatformLynx::tick(bool sysTick) {
|
||||||
|
|
@ -203,18 +226,35 @@ void DivPlatformLynx::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chan[i].freqChanged) {
|
if (chan[i].freqChanged) {
|
||||||
if (chan[i].lfsr >= 0) {
|
if (chan[i].pcm) {
|
||||||
WRITE_LFSR(i, (chan[i].lfsr&0xff));
|
double off=1.0;
|
||||||
WRITE_OTHER(i, ((chan[i].lfsr&0xf00)>>4));
|
if (chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
|
||||||
chan[i].lfsr=-1;
|
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;
|
chan[i].freqChanged=false;
|
||||||
} else if (chan[i].std.duty.had) {
|
} else if (chan[i].std.duty.had) {
|
||||||
chan[i].duty = chan[i].std.duty.val;
|
chan[i].duty = chan[i].std.duty.val;
|
||||||
|
|
@ -226,9 +266,17 @@ void DivPlatformLynx::tick(bool sysTick) {
|
||||||
|
|
||||||
int DivPlatformLynx::dispatch(DivCommand c) {
|
int DivPlatformLynx::dispatch(DivCommand c) {
|
||||||
switch (c.cmd) {
|
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) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
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].freqChanged=true;
|
||||||
chan[c.chan].note=c.value;
|
chan[c.chan].note=c.value;
|
||||||
chan[c.chan].actualNote=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)));
|
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));
|
chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_MIKEY));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case DIV_CMD_NOTE_OFF:
|
case DIV_CMD_NOTE_OFF:
|
||||||
chan[c.chan].active=false;
|
chan[c.chan].active=false;
|
||||||
WRITE_VOLUME(c.chan, 0);
|
WRITE_VOLUME(c.chan, 0);
|
||||||
|
|
|
||||||
|
|
@ -44,9 +44,9 @@ class DivPlatformLynx: public DivDispatch {
|
||||||
DivMacroInt std;
|
DivMacroInt std;
|
||||||
MikeyFreqDiv fd;
|
MikeyFreqDiv fd;
|
||||||
MikeyDuty duty;
|
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;
|
unsigned char pan;
|
||||||
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta;
|
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, pcm;
|
||||||
signed char vol, outVol;
|
signed char vol, outVol;
|
||||||
void macroInit(DivInstrument* which) {
|
void macroInit(DivInstrument* which) {
|
||||||
std.init(which);
|
std.init(which);
|
||||||
|
|
@ -63,6 +63,11 @@ class DivPlatformLynx: public DivDispatch {
|
||||||
actualNote(0),
|
actualNote(0),
|
||||||
lfsr(-1),
|
lfsr(-1),
|
||||||
ins(-1),
|
ins(-1),
|
||||||
|
sample(-1),
|
||||||
|
samplePos(0),
|
||||||
|
sampleAccum(0),
|
||||||
|
sampleBaseFreq(0),
|
||||||
|
sampleFreq(0),
|
||||||
pan(0xff),
|
pan(0xff),
|
||||||
active(false),
|
active(false),
|
||||||
insChanged(true),
|
insChanged(true),
|
||||||
|
|
@ -70,6 +75,7 @@ class DivPlatformLynx: public DivDispatch {
|
||||||
keyOn(false),
|
keyOn(false),
|
||||||
keyOff(false),
|
keyOff(false),
|
||||||
inPorta(false),
|
inPorta(false),
|
||||||
|
pcm(false),
|
||||||
vol(127),
|
vol(127),
|
||||||
outVol(127) {}
|
outVol(127) {}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1655,7 +1655,7 @@ void DivEngine::registerSystems() {
|
||||||
{"CH1", "CH2", "CH3", "CH4"},
|
{"CH1", "CH2", "CH3", "CH4"},
|
||||||
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
{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_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;},
|
[](int,unsigned char,unsigned char) -> bool {return false;},
|
||||||
[this](int ch, unsigned char effect, unsigned char effectVal) -> bool {
|
[this](int ch, unsigned char effect, unsigned char effectVal) -> bool {
|
||||||
if (effect>=0x30 && effect<0x40) {
|
if (effect>=0x30 && effect<0x40) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue