Merge branch 'master' of https://github.com/tildearrow/furnace into es5506_alt
* 'master' of https://github.com/tildearrow/furnace: sysDef refactor, part 2 sysDef refactor, part 1 - PLEASE READ NOTE prepare for macroInt preview in instrument editor GUI: fix #400 fix metronome in low-latency mode # Conflicts: # src/engine/dispatch.h # src/engine/dispatchContainer.cpp # src/engine/instrument.h # src/engine/song.h # src/engine/sysDef.cpp # src/gui/dataList.cpp # src/gui/gui.h # src/gui/guiConst.cpp
This commit is contained in:
commit
0209ebda03
22 changed files with 1333 additions and 1591 deletions
|
|
@ -29,6 +29,10 @@ void* DivDispatch::getChanState(int chan) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
DivMacroInt* DivDispatch::getChanMacroInt(int chan) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned char* DivDispatch::getRegisterPool() {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,15 +22,20 @@
|
|||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#define CHIP_FREQBASE 2048
|
||||
|
||||
void DivPlatformDummy::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
for (size_t i=start; i<start+len; i++) {
|
||||
bufL[i]=0;
|
||||
int out=0;
|
||||
for (unsigned char j=0; j<chans; j++) {
|
||||
if (chan[j].active) {
|
||||
if (!isMuted[j]) bufL[i]+=(((signed short)chan[j].pos)*chan[j].amp*chan[j].vol)>>13;
|
||||
if (!isMuted[j]) out+=(((signed short)chan[j].pos)*chan[j].amp*chan[j].vol)>>12;
|
||||
chan[j].pos+=chan[j].freq;
|
||||
}
|
||||
}
|
||||
if (out<-32768) out=-32768;
|
||||
if (out>32767) out=32767;
|
||||
bufL[i]=out;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -41,8 +46,8 @@ void DivPlatformDummy::muteChannel(int ch, bool mute) {
|
|||
void DivPlatformDummy::tick(bool sysTick) {
|
||||
for (unsigned char i=0; i<chans; i++) {
|
||||
if (sysTick) {
|
||||
chan[i].amp-=3;
|
||||
if (chan[i].amp<16) chan[i].amp=16;
|
||||
chan[i].amp-=7;
|
||||
if (chan[i].amp<15) chan[i].amp=15;
|
||||
}
|
||||
|
||||
if (chan[i].freqChanged) {
|
||||
|
|
@ -60,7 +65,7 @@ int DivPlatformDummy::dispatch(DivCommand c) {
|
|||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON:
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=65.6f*pow(2.0f,((float)c.value/12.0f));
|
||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
||||
chan[c.chan].freqChanged=true;
|
||||
}
|
||||
chan[c.chan].active=true;
|
||||
|
|
@ -80,8 +85,28 @@ int DivPlatformDummy::dispatch(DivCommand c) {
|
|||
chan[c.chan].pitch=c.value;
|
||||
chan[c.chan].freqChanged=true;
|
||||
break;
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
int destFreq=NOTE_FREQUENCY(c.value2);
|
||||
bool return2=false;
|
||||
if (destFreq>chan[c.chan].baseFreq) {
|
||||
chan[c.chan].baseFreq+=c.value;
|
||||
if (chan[c.chan].baseFreq>=destFreq) {
|
||||
chan[c.chan].baseFreq=destFreq;
|
||||
return2=true;
|
||||
}
|
||||
} else {
|
||||
chan[c.chan].baseFreq-=c.value;
|
||||
if (chan[c.chan].baseFreq<=destFreq) {
|
||||
chan[c.chan].baseFreq=destFreq;
|
||||
return2=true;
|
||||
}
|
||||
}
|
||||
chan[c.chan].freqChanged=true;
|
||||
if (return2) return 2;
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_LEGATO:
|
||||
chan[c.chan].baseFreq=65.6f*pow(2.0f,((float)c.value/12.0f));
|
||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
||||
chan[c.chan].freqChanged=true;
|
||||
break;
|
||||
case DIV_CMD_GET_VOLMAX:
|
||||
|
|
@ -108,6 +133,7 @@ int DivPlatformDummy::init(DivEngine* p, int channels, int sugRate, unsigned int
|
|||
isMuted[i]=false;
|
||||
}
|
||||
rate=65536;
|
||||
chipClock=65536;
|
||||
chans=channels;
|
||||
reset();
|
||||
return channels;
|
||||
|
|
|
|||
|
|
@ -23,8 +23,7 @@
|
|||
// used when a DivDispatch for a system is not found.
|
||||
class DivPlatformDummy: public DivDispatch {
|
||||
struct Channel {
|
||||
unsigned short freq, baseFreq;
|
||||
short pitch;
|
||||
int freq, baseFreq, pitch;
|
||||
unsigned short pos;
|
||||
bool active, freqChanged;
|
||||
unsigned char vol;
|
||||
|
|
|
|||
261
src/engine/platform/sound/su.cpp
Normal file
261
src/engine/platform/sound/su.cpp
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
#include "su.h"
|
||||
#include <string.h>
|
||||
|
||||
#define minval(a,b) (((a)<(b))?(a):(b))
|
||||
#define maxval(a,b) (((a)>(b))?(a):(b))
|
||||
|
||||
void SoundUnit::NextSample(short* l, short* r) {
|
||||
for (int i=0; i<8; i++) {
|
||||
if (chan[i].vol==0 && !chan[i].flags.swvol) {fns[i]=0; continue;}
|
||||
if (chan[i].flags.pcm) {
|
||||
ns[i]=pcm[chan[i].pcmpos];
|
||||
} else switch (chan[i].flags.shape) {
|
||||
case 0:
|
||||
ns[i]=(((cycle[i]>>15)&127)>chan[i].duty)*127;
|
||||
break;
|
||||
case 1:
|
||||
ns[i]=cycle[i]>>14;
|
||||
break;
|
||||
case 2:
|
||||
ns[i]=SCsine[(cycle[i]>>14)&255];
|
||||
break;
|
||||
case 3:
|
||||
ns[i]=SCtriangle[(cycle[i]>>14)&255];
|
||||
break;
|
||||
case 4: case 5:
|
||||
ns[i]=(lfsr[i]&1)*127;
|
||||
break;
|
||||
case 6:
|
||||
ns[i]=((((cycle[i]>>15)&127)>chan[i].duty)*127)^(short)SCsine[(cycle[i]>>14)&255];
|
||||
break;
|
||||
case 7:
|
||||
ns[i]=((((cycle[i]>>15)&127)>chan[i].duty)*127)^(short)SCtriangle[(cycle[i]>>14)&255];
|
||||
break;
|
||||
}
|
||||
|
||||
if (chan[i].flags.pcm) {
|
||||
if (chan[i].freq>0x8000) {
|
||||
pcmdec[i]+=0x8000;
|
||||
} else {
|
||||
pcmdec[i]+=chan[i].freq;
|
||||
}
|
||||
if (pcmdec[i]>=32768) {
|
||||
pcmdec[i]-=32768;
|
||||
if (chan[i].pcmpos<chan[i].pcmbnd) {
|
||||
chan[i].pcmpos++;
|
||||
chan[i].wc++;
|
||||
if (chan[i].pcmpos==chan[i].pcmbnd) {
|
||||
if (chan[i].flags.pcmloop) {
|
||||
chan[i].pcmpos=chan[i].pcmrst;
|
||||
}
|
||||
}
|
||||
chan[i].pcmpos&=(SOUNDCHIP_PCM_SIZE-1);
|
||||
} else if (chan[i].flags.pcmloop) {
|
||||
chan[i].pcmpos=chan[i].pcmrst;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ocycle[i]=cycle[i];
|
||||
if (chan[i].flags.shape==5) {
|
||||
switch ((chan[i].duty>>4)&3) {
|
||||
case 0:
|
||||
cycle[i]+=chan[i].freq*1-(chan[i].freq>>3);
|
||||
break;
|
||||
case 1:
|
||||
cycle[i]+=chan[i].freq*2-(chan[i].freq>>3);
|
||||
break;
|
||||
case 2:
|
||||
cycle[i]+=chan[i].freq*4-(chan[i].freq>>3);
|
||||
break;
|
||||
case 3:
|
||||
cycle[i]+=chan[i].freq*8-(chan[i].freq>>3);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
cycle[i]+=chan[i].freq;
|
||||
}
|
||||
if ((cycle[i]&0xf80000)!=(ocycle[i]&0xf80000)) {
|
||||
if (chan[i].flags.shape==4) {
|
||||
lfsr[i]=(lfsr[i]>>1|(((lfsr[i]) ^ (lfsr[i] >> 2) ^ (lfsr[i] >> 3) ^ (lfsr[i] >> 5) ) & 1)<<31);
|
||||
} else {
|
||||
switch ((chan[i].duty>>4)&3) {
|
||||
case 0:
|
||||
lfsr[i]=(lfsr[i]>>1|(((lfsr[i] >> 3) ^ (lfsr[i] >> 4) ) & 1)<<5);
|
||||
break;
|
||||
case 1:
|
||||
lfsr[i]=(lfsr[i]>>1|(((lfsr[i] >> 2) ^ (lfsr[i] >> 3) ) & 1)<<5);
|
||||
break;
|
||||
case 2:
|
||||
lfsr[i]=(lfsr[i]>>1|(((lfsr[i]) ^ (lfsr[i] >> 2) ^ (lfsr[i] >> 3) ) & 1)<<5);
|
||||
break;
|
||||
case 3:
|
||||
lfsr[i]=(lfsr[i]>>1|(((lfsr[i]) ^ (lfsr[i] >> 2) ^ (lfsr[i] >> 3) ^ (lfsr[i] >> 5) ) & 1)<<5);
|
||||
break;
|
||||
}
|
||||
if ((lfsr[i]&63)==0) {
|
||||
lfsr[i]=0xaaaa;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chan[i].flags.restim) {
|
||||
if (--rcycle[i]<=0) {
|
||||
cycle[i]=0;
|
||||
rcycle[i]=chan[i].restimer;
|
||||
lfsr[i]=0xaaaa;
|
||||
}
|
||||
}
|
||||
}
|
||||
fns[i]=ns[i]*chan[i].vol*2;
|
||||
if (chan[i].flags.fmode!=0) {
|
||||
int ff=chan[i].cutoff;
|
||||
nslow[i]=nslow[i]+(((ff)*nsband[i])>>16);
|
||||
nshigh[i]=fns[i]-nslow[i]-(((256-chan[i].reson)*nsband[i])>>8);
|
||||
nsband[i]=(((ff)*nshigh[i])>>16)+nsband[i];
|
||||
fns[i]=(((chan[i].flags.fmode&1)?(nslow[i]):(0))+((chan[i].flags.fmode&2)?(nshigh[i]):(0))+((chan[i].flags.fmode&4)?(nsband[i]):(0)));
|
||||
}
|
||||
nsL[i]=(fns[i]*SCpantabL[(unsigned char)chan[i].pan])>>8;
|
||||
nsR[i]=(fns[i]*SCpantabR[(unsigned char)chan[i].pan])>>8;
|
||||
oldfreq[i]=chan[i].freq;
|
||||
oldflags[i]=chan[i].flags.flags;
|
||||
if (chan[i].flags.swvol) {
|
||||
if (--swvolt[i]<=0) {
|
||||
swvolt[i]=chan[i].swvol.speed;
|
||||
if (chan[i].swvol.dir) {
|
||||
chan[i].vol+=chan[i].swvol.amt;
|
||||
if (chan[i].vol>chan[i].swvol.bound && !chan[i].swvol.loop) {
|
||||
chan[i].vol=chan[i].swvol.bound;
|
||||
}
|
||||
if (chan[i].vol&0x80) {
|
||||
if (chan[i].swvol.loop) {
|
||||
if (chan[i].swvol.loopi) {
|
||||
chan[i].swvol.dir=!chan[i].swvol.dir;
|
||||
chan[i].vol=0xff-chan[i].vol;
|
||||
} else {
|
||||
chan[i].vol&=~0x80;
|
||||
}
|
||||
} else {
|
||||
chan[i].vol=0x7f;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
chan[i].vol-=chan[i].swvol.amt;
|
||||
if (chan[i].vol&0x80) {
|
||||
if (chan[i].swvol.loop) {
|
||||
if (chan[i].swvol.loopi) {
|
||||
chan[i].swvol.dir=!chan[i].swvol.dir;
|
||||
chan[i].vol=-chan[i].vol;
|
||||
} else {
|
||||
chan[i].vol&=~0x80;
|
||||
}
|
||||
} else {
|
||||
chan[i].vol=0x0;
|
||||
}
|
||||
}
|
||||
if (chan[i].vol<chan[i].swvol.bound && !chan[i].swvol.loop) {
|
||||
chan[i].vol=chan[i].swvol.bound;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chan[i].flags.swfreq) {
|
||||
if (--swfreqt[i]<=0) {
|
||||
swfreqt[i]=chan[i].swfreq.speed;
|
||||
if (chan[i].swfreq.dir) {
|
||||
if (chan[i].freq>(0xffff-chan[i].swfreq.amt)) {
|
||||
chan[i].freq=0xffff;
|
||||
} else {
|
||||
chan[i].freq=(chan[i].freq*(0x80+chan[i].swfreq.amt))>>7;
|
||||
if ((chan[i].freq>>8)>chan[i].swfreq.bound) {
|
||||
chan[i].freq=chan[i].swfreq.bound<<8;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (chan[i].freq<chan[i].swfreq.amt) {
|
||||
chan[i].freq=0;
|
||||
} else {
|
||||
chan[i].freq=(chan[i].freq*(0xff-chan[i].swfreq.amt))>>8;
|
||||
if ((chan[i].freq>>8)<chan[i].swfreq.bound) {
|
||||
chan[i].freq=chan[i].swfreq.bound<<8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chan[i].flags.swcut) {
|
||||
if (--swcutt[i]<=0) {
|
||||
swcutt[i]=chan[i].swcut.speed;
|
||||
if (chan[i].swcut.dir) {
|
||||
if (chan[i].cutoff>(0xffff-chan[i].swcut.amt)) {
|
||||
chan[i].cutoff=0xffff;
|
||||
} else {
|
||||
chan[i].cutoff+=chan[i].swcut.amt;
|
||||
if ((chan[i].cutoff>>8)>chan[i].swcut.bound) {
|
||||
chan[i].cutoff=chan[i].swcut.bound<<8;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (chan[i].cutoff<chan[i].swcut.amt) {
|
||||
chan[i].cutoff=0;
|
||||
} else {
|
||||
chan[i].cutoff=((2048-(unsigned int)chan[i].swcut.amt)*(unsigned int)chan[i].cutoff)>>11;
|
||||
if ((chan[i].cutoff>>8)<chan[i].swcut.bound) {
|
||||
chan[i].cutoff=chan[i].swcut.bound<<8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chan[i].flags.resosc) {
|
||||
cycle[i]=0;
|
||||
rcycle[i]=chan[i].restimer;
|
||||
ocycle[i]=0;
|
||||
chan[i].flags.resosc=0;
|
||||
}
|
||||
}
|
||||
tnsL=(nsL[0]+nsL[1]+nsL[2]+nsL[3]+nsL[4]+nsL[5]+nsL[6]+nsL[7])>>2;
|
||||
tnsR=(nsR[0]+nsR[1]+nsR[2]+nsR[3]+nsR[4]+nsR[5]+nsR[6]+nsR[7])>>2;
|
||||
|
||||
*l=minval(32767,maxval(-32767,tnsL));
|
||||
*r=minval(32767,maxval(-32767,tnsR));
|
||||
}
|
||||
|
||||
void SoundUnit::Init() {
|
||||
Reset();
|
||||
memset(pcm,0,SOUNDCHIP_PCM_SIZE);
|
||||
for (int i=0; i<256; i++) {
|
||||
SCsine[i]=sin((i/128.0f)*M_PI)*127;
|
||||
SCtriangle[i]=(i>127)?(255-i):(i);
|
||||
SCpantabL[i]=127;
|
||||
SCpantabR[i]=127;
|
||||
}
|
||||
for (int i=0; i<128; i++) {
|
||||
SCpantabL[i]=127-i;
|
||||
SCpantabR[128+i]=i-1;
|
||||
}
|
||||
SCpantabR[128]=0;
|
||||
}
|
||||
|
||||
void SoundUnit::Reset() {
|
||||
for (int i=0; i<8; i++) {
|
||||
cycle[i]=0;
|
||||
resetfreq[i]=0;
|
||||
voldcycles[i]=0;
|
||||
volicycles[i]=0;
|
||||
fscycles[i]=0;
|
||||
sweep[i]=0;
|
||||
ns[i]=0;
|
||||
swvolt[i]=1;
|
||||
swfreqt[i]=1;
|
||||
swcutt[i]=1;
|
||||
lfsr[i]=0xaaaa;
|
||||
}
|
||||
memset(chan,0,sizeof(SUChannel)*8);
|
||||
}
|
||||
|
||||
void SoundUnit::Write(unsigned char addr, unsigned char data) {
|
||||
((unsigned char*)chan)[addr]=data;
|
||||
}
|
||||
|
||||
SoundUnit::SoundUnit() {
|
||||
Init();
|
||||
}
|
||||
93
src/engine/platform/sound/su.h
Normal file
93
src/engine/platform/sound/su.h
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define SOUNDCHIP_PCM_SIZE 8192
|
||||
|
||||
class SoundUnit {
|
||||
signed char SCsine[256];
|
||||
signed char SCtriangle[256];
|
||||
signed char SCpantabL[256];
|
||||
signed char SCpantabR[256];
|
||||
unsigned int ocycle[8];
|
||||
unsigned int cycle[8];
|
||||
int rcycle[8];
|
||||
unsigned int lfsr[8];
|
||||
signed char ns[8];
|
||||
int fns[8];
|
||||
int nsL[8];
|
||||
int nsR[8];
|
||||
int nslow[8];
|
||||
int nshigh[8];
|
||||
int nsband[8];
|
||||
int tnsL, tnsR;
|
||||
unsigned short oldfreq[8];
|
||||
unsigned short oldflags[8];
|
||||
public:
|
||||
unsigned short resetfreq[8];
|
||||
unsigned short voldcycles[8];
|
||||
unsigned short volicycles[8];
|
||||
unsigned short fscycles[8];
|
||||
unsigned char sweep[8];
|
||||
unsigned short swvolt[8];
|
||||
unsigned short swfreqt[8];
|
||||
unsigned short swcutt[8];
|
||||
unsigned short pcmdec[8];
|
||||
struct SUChannel {
|
||||
unsigned short freq;
|
||||
signed char vol;
|
||||
signed char pan;
|
||||
union {
|
||||
unsigned short flags;
|
||||
struct {
|
||||
unsigned char shape: 3;
|
||||
unsigned char pcm: 1;
|
||||
unsigned char ring: 1;
|
||||
unsigned char fmode: 3;
|
||||
unsigned char resosc: 1;
|
||||
unsigned char resfilt: 1;
|
||||
unsigned char pcmloop: 1;
|
||||
unsigned char restim: 1;
|
||||
unsigned char swfreq: 1;
|
||||
unsigned char swvol: 1;
|
||||
unsigned char swcut: 1;
|
||||
unsigned char padding: 1;
|
||||
};
|
||||
} flags;
|
||||
unsigned short cutoff;
|
||||
unsigned char duty;
|
||||
unsigned char reson;
|
||||
unsigned short pcmpos;
|
||||
unsigned short pcmbnd;
|
||||
unsigned short pcmrst;
|
||||
struct {
|
||||
unsigned short speed;
|
||||
unsigned char amt: 7;
|
||||
unsigned char dir: 1;
|
||||
unsigned char bound;
|
||||
} swfreq;
|
||||
struct {
|
||||
unsigned short speed;
|
||||
unsigned char amt: 5;
|
||||
unsigned char dir: 1;
|
||||
unsigned char loop: 1;
|
||||
unsigned char loopi: 1;
|
||||
unsigned char bound;
|
||||
} swvol;
|
||||
struct {
|
||||
unsigned short speed;
|
||||
unsigned char amt: 7;
|
||||
unsigned char dir: 1;
|
||||
unsigned char bound;
|
||||
} swcut;
|
||||
unsigned short wc;
|
||||
unsigned short restimer;
|
||||
} chan[8];
|
||||
signed char pcm[SOUNDCHIP_PCM_SIZE];
|
||||
void Write(unsigned char addr, unsigned char data);
|
||||
void NextSample(short* l, short* r);
|
||||
void Init();
|
||||
void Reset();
|
||||
SoundUnit();
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue