ZX beeper: implement overlay drums
1-bit samples up to 2048 bits in length triggered with 17xx
This commit is contained in:
parent
6ec8674072
commit
2ada4ee393
1
TODO.md
1
TODO.md
|
@ -1,7 +1,6 @@
|
||||||
# to-do for 0.6pre1
|
# to-do for 0.6pre1
|
||||||
|
|
||||||
- RF5C68 system
|
- RF5C68 system
|
||||||
- ZX beeper system overlay percussion
|
|
||||||
- ADPCM chips
|
- ADPCM chips
|
||||||
- Game Boy envelope macro/sequence
|
- Game Boy envelope macro/sequence
|
||||||
- rewrite the system name detection function anyway
|
- rewrite the system name detection function anyway
|
||||||
|
|
|
@ -43,6 +43,25 @@ void DivPlatformZXBeeper::acquire(short* bufL, short* bufR, size_t start, size_t
|
||||||
for (size_t h=start; h<start+len; h++) {
|
for (size_t h=start; h<start+len; h++) {
|
||||||
// clock here
|
// clock here
|
||||||
bool o=false;
|
bool o=false;
|
||||||
|
if (curSample>=0 && curSample<parent->song.sampleLen) {
|
||||||
|
if (--curSamplePeriod<0) {
|
||||||
|
DivSample* s=parent->getSample(curSample);
|
||||||
|
if (s->samples<=0) {
|
||||||
|
curSample=-1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
o=s->data8[curSamplePos++];
|
||||||
|
bufL[h]=o?16384:0;
|
||||||
|
if (curSamplePos>=s->samples) curSample=-1;
|
||||||
|
// 256 bits
|
||||||
|
if (curSamplePos>2047) curSample=-1;
|
||||||
|
|
||||||
|
curSamplePeriod=15;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned short oldPos=chan[curChan].sPosition;
|
unsigned short oldPos=chan[curChan].sPosition;
|
||||||
|
|
||||||
if (sOffTimer) {
|
if (sOffTimer) {
|
||||||
|
@ -128,9 +147,7 @@ int DivPlatformZXBeeper::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_NOTE_OFF:
|
case DIV_CMD_NOTE_OFF:
|
||||||
chan[c.chan].dacSample=-1;
|
|
||||||
if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0);
|
if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0);
|
||||||
chan[c.chan].pcm=false;
|
|
||||||
chan[c.chan].active=false;
|
chan[c.chan].active=false;
|
||||||
chan[c.chan].keyOff=true;
|
chan[c.chan].keyOff=true;
|
||||||
chan[c.chan].macroInit(NULL);
|
chan[c.chan].macroInit(NULL);
|
||||||
|
@ -190,13 +207,9 @@ int DivPlatformZXBeeper::dispatch(DivCommand c) {
|
||||||
chan[c.chan].duty=c.value;
|
chan[c.chan].duty=c.value;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_SAMPLE_MODE:
|
case DIV_CMD_SAMPLE_MODE:
|
||||||
chan[c.chan].pcm=c.value;
|
curSample=c.value;
|
||||||
break;
|
curSamplePos=0;
|
||||||
case DIV_CMD_SAMPLE_BANK:
|
curSamplePeriod=0;
|
||||||
sampleBank=c.value;
|
|
||||||
if (sampleBank>(parent->song.sample.size()/12)) {
|
|
||||||
sampleBank=parent->song.sample.size()/12;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_LEGATO:
|
case DIV_CMD_LEGATO:
|
||||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val):(0)));
|
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value+((chan[c.chan].std.arp.will && !chan[c.chan].std.arp.mode)?(chan[c.chan].std.arp.val):(0)));
|
||||||
|
@ -265,8 +278,10 @@ void DivPlatformZXBeeper::reset() {
|
||||||
cycles=0;
|
cycles=0;
|
||||||
curChan=0;
|
curChan=0;
|
||||||
sOffTimer=0;
|
sOffTimer=0;
|
||||||
sampleBank=0;
|
|
||||||
ulaOut=0;
|
ulaOut=0;
|
||||||
|
curSample=-1;
|
||||||
|
curSamplePos=0;
|
||||||
|
curSamplePeriod=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DivPlatformZXBeeper::keyOffAffectsArp(int ch) {
|
bool DivPlatformZXBeeper::keyOffAffectsArp(int ch) {
|
||||||
|
|
|
@ -27,10 +27,8 @@
|
||||||
class DivPlatformZXBeeper: public DivDispatch {
|
class DivPlatformZXBeeper: public DivDispatch {
|
||||||
struct Channel {
|
struct Channel {
|
||||||
int freq, baseFreq, pitch, pitch2, note;
|
int freq, baseFreq, pitch, pitch2, note;
|
||||||
int dacPeriod, dacRate;
|
int ins;
|
||||||
unsigned int dacPos;
|
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta;
|
||||||
int dacSample, ins;
|
|
||||||
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, noise, pcm, furnaceDac;
|
|
||||||
signed char vol, outVol;
|
signed char vol, outVol;
|
||||||
unsigned short sPosition;
|
unsigned short sPosition;
|
||||||
unsigned char duty;
|
unsigned char duty;
|
||||||
|
@ -45,10 +43,6 @@ class DivPlatformZXBeeper: public DivDispatch {
|
||||||
pitch(0),
|
pitch(0),
|
||||||
pitch2(0),
|
pitch2(0),
|
||||||
note(0),
|
note(0),
|
||||||
dacPeriod(0),
|
|
||||||
dacRate(0),
|
|
||||||
dacPos(0),
|
|
||||||
dacSample(-1),
|
|
||||||
ins(-1),
|
ins(-1),
|
||||||
active(false),
|
active(false),
|
||||||
insChanged(true),
|
insChanged(true),
|
||||||
|
@ -56,9 +50,6 @@ class DivPlatformZXBeeper: public DivDispatch {
|
||||||
keyOn(false),
|
keyOn(false),
|
||||||
keyOff(false),
|
keyOff(false),
|
||||||
inPorta(false),
|
inPorta(false),
|
||||||
noise(false),
|
|
||||||
pcm(false),
|
|
||||||
furnaceDac(false),
|
|
||||||
vol(1),
|
vol(1),
|
||||||
outVol(1),
|
outVol(1),
|
||||||
sPosition(0),
|
sPosition(0),
|
||||||
|
@ -75,10 +66,10 @@ class DivPlatformZXBeeper: public DivDispatch {
|
||||||
std::queue<QueuedWrite> writes;
|
std::queue<QueuedWrite> writes;
|
||||||
unsigned char lastPan, ulaOut;
|
unsigned char lastPan, ulaOut;
|
||||||
|
|
||||||
int cycles, curChan, sOffTimer, delay;
|
int cycles, curChan, sOffTimer, delay, curSample, curSamplePeriod;
|
||||||
|
unsigned int curSamplePos;
|
||||||
int tempL[32];
|
int tempL[32];
|
||||||
int tempR[32];
|
int tempR[32];
|
||||||
unsigned char sampleBank, lfoMode, lfoSpeed;
|
|
||||||
unsigned char regPool[128];
|
unsigned char regPool[128];
|
||||||
friend void putDispatchChan(void*,int,int);
|
friend void putDispatchChan(void*,int,int);
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1522,7 +1522,21 @@ void DivEngine::registerSystems() {
|
||||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6"},
|
{"Channel 1", "Channel 2", "Channel 3", "Channel 4", "Channel 5", "Channel 6"},
|
||||||
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6"},
|
{"CH1", "CH2", "CH3", "CH4", "CH5", "CH6"},
|
||||||
{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_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE},
|
||||||
{DIV_INS_BEEPER, DIV_INS_BEEPER, DIV_INS_BEEPER, DIV_INS_BEEPER, DIV_INS_BEEPER, DIV_INS_BEEPER}
|
{DIV_INS_BEEPER, DIV_INS_BEEPER, DIV_INS_BEEPER, DIV_INS_BEEPER, DIV_INS_BEEPER, DIV_INS_BEEPER},
|
||||||
|
{},
|
||||||
|
[this](int ch, unsigned char effect, unsigned char effectVal) -> bool {
|
||||||
|
switch (effect) {
|
||||||
|
case 0x12: // pulse width
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_MODE,ch,effectVal));
|
||||||
|
break;
|
||||||
|
case 0x17: // overlay sample
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_SAMPLE_MODE,ch,effectVal));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_YM2612_EXT]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_YM2612_EXT]=new DivSysDef(
|
||||||
|
|
Loading…
Reference in a new issue