mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-18 02:25:11 +00:00
per-channel oscilloscope, part 2
AY8930, K00, C64 and NES
This commit is contained in:
parent
b3b747a67a
commit
c738ece374
10 changed files with 102 additions and 5 deletions
|
@ -149,6 +149,12 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l
|
||||||
bufR[i+start]=bufL[i+start];
|
bufR[i+start]=bufL[i+start];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int ch=0; ch<3; ch++) {
|
||||||
|
for (size_t i=0; i<len; i++) {
|
||||||
|
oscBuf[ch]->data[oscBuf[ch]->needle++]=ayBuf[ch][i];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformAY8930::updateOutSel(bool immediate) {
|
void DivPlatformAY8930::updateOutSel(bool immediate) {
|
||||||
|
@ -523,6 +529,10 @@ void* DivPlatformAY8930::getChanState(int ch) {
|
||||||
return &chan[ch];
|
return &chan[ch];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DivDispatchOscBuffer* DivPlatformAY8930::getOscBuffer(int ch) {
|
||||||
|
return oscBuf[ch];
|
||||||
|
}
|
||||||
|
|
||||||
unsigned char* DivPlatformAY8930::getRegisterPool() {
|
unsigned char* DivPlatformAY8930::getRegisterPool() {
|
||||||
return regPool;
|
return regPool;
|
||||||
}
|
}
|
||||||
|
@ -629,6 +639,10 @@ void DivPlatformAY8930::setFlags(unsigned int flags) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rate=chipClock/8;
|
rate=chipClock/8;
|
||||||
|
for (int i=0; i<3; i++) {
|
||||||
|
oscBuf[i]->rate=rate;
|
||||||
|
}
|
||||||
|
|
||||||
stereo=flags>>6;
|
stereo=flags>>6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,6 +652,7 @@ int DivPlatformAY8930::init(DivEngine* p, int channels, int sugRate, unsigned in
|
||||||
skipRegisterWrites=false;
|
skipRegisterWrites=false;
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i<3; i++) {
|
||||||
isMuted[i]=false;
|
isMuted[i]=false;
|
||||||
|
oscBuf[i]=new DivDispatchOscBuffer;
|
||||||
}
|
}
|
||||||
setFlags(flags);
|
setFlags(flags);
|
||||||
ay=new ay8930_device(rate);
|
ay=new ay8930_device(rate);
|
||||||
|
@ -649,6 +664,9 @@ int DivPlatformAY8930::init(DivEngine* p, int channels, int sugRate, unsigned in
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformAY8930::quit() {
|
void DivPlatformAY8930::quit() {
|
||||||
for (int i=0; i<3; i++) delete[] ayBuf[i];
|
for (int i=0; i<3; i++) {
|
||||||
|
delete oscBuf[i];
|
||||||
|
delete[] ayBuf[i];
|
||||||
|
}
|
||||||
delete ay;
|
delete ay;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ class DivPlatformAY8930: public DivDispatch {
|
||||||
};
|
};
|
||||||
std::queue<QueuedWrite> writes;
|
std::queue<QueuedWrite> writes;
|
||||||
ay8930_device* ay;
|
ay8930_device* ay;
|
||||||
|
DivDispatchOscBuffer* oscBuf[3];
|
||||||
unsigned char regPool[32];
|
unsigned char regPool[32];
|
||||||
unsigned char ayNoiseAnd, ayNoiseOr;
|
unsigned char ayNoiseAnd, ayNoiseOr;
|
||||||
bool bank;
|
bool bank;
|
||||||
|
@ -79,6 +80,7 @@ class DivPlatformAY8930: public DivDispatch {
|
||||||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||||
int dispatch(DivCommand c);
|
int dispatch(DivCommand c);
|
||||||
void* getChanState(int chan);
|
void* getChanState(int chan);
|
||||||
|
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||||
unsigned char* getRegisterPool();
|
unsigned char* getRegisterPool();
|
||||||
int getRegisterPoolSize();
|
int getRegisterPoolSize();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
|
@ -49,6 +49,7 @@ const char* DivPlatformBubSysWSG::getEffectName(unsigned char effect) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformBubSysWSG::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
void DivPlatformBubSysWSG::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||||
|
int chanOut=0;
|
||||||
for (size_t h=start; h<start+len; h++) {
|
for (size_t h=start; h<start+len; h++) {
|
||||||
signed int out=0;
|
signed int out=0;
|
||||||
// K005289 part
|
// K005289 part
|
||||||
|
@ -56,8 +57,14 @@ void DivPlatformBubSysWSG::acquire(short* bufL, short* bufR, size_t start, size_
|
||||||
|
|
||||||
// Wavetable part
|
// Wavetable part
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i<2; i++) {
|
||||||
if (isMuted[i]) continue;
|
if (isMuted[i]) {
|
||||||
out+=chan[i].waveROM[k005289->addr(i)]*(regPool[2+i]&0xf);
|
oscBuf[i]->data[oscBuf[i]->needle++]=0;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
chanOut=chan[i].waveROM[k005289->addr(i)]*(regPool[2+i]&0xf);
|
||||||
|
out+=chanOut;
|
||||||
|
oscBuf[i]->data[oscBuf[i]->needle++]=chanOut;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out<<=6; // scale output to 16 bit
|
out<<=6; // scale output to 16 bit
|
||||||
|
@ -267,6 +274,10 @@ void* DivPlatformBubSysWSG::getChanState(int ch) {
|
||||||
return &chan[ch];
|
return &chan[ch];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DivDispatchOscBuffer* DivPlatformBubSysWSG::getOscBuffer(int ch) {
|
||||||
|
return oscBuf[ch];
|
||||||
|
}
|
||||||
|
|
||||||
unsigned char* DivPlatformBubSysWSG::getRegisterPool() {
|
unsigned char* DivPlatformBubSysWSG::getRegisterPool() {
|
||||||
return (unsigned char*)regPool;
|
return (unsigned char*)regPool;
|
||||||
}
|
}
|
||||||
|
@ -335,6 +346,7 @@ int DivPlatformBubSysWSG::init(DivEngine* p, int channels, int sugRate, unsigned
|
||||||
skipRegisterWrites=false;
|
skipRegisterWrites=false;
|
||||||
for (int i=0; i<2; i++) {
|
for (int i=0; i<2; i++) {
|
||||||
isMuted[i]=false;
|
isMuted[i]=false;
|
||||||
|
oscBuf[i]=new DivDispatchOscBuffer;
|
||||||
}
|
}
|
||||||
setFlags(flags);
|
setFlags(flags);
|
||||||
k005289=new k005289_core();
|
k005289=new k005289_core();
|
||||||
|
@ -343,6 +355,9 @@ int DivPlatformBubSysWSG::init(DivEngine* p, int channels, int sugRate, unsigned
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformBubSysWSG::quit() {
|
void DivPlatformBubSysWSG::quit() {
|
||||||
|
for (int i=0; i<2; i++) {
|
||||||
|
delete oscBuf[i];
|
||||||
|
}
|
||||||
delete k005289;
|
delete k005289;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@ class DivPlatformBubSysWSG: public DivDispatch {
|
||||||
wave(-1) {}
|
wave(-1) {}
|
||||||
};
|
};
|
||||||
Channel chan[2];
|
Channel chan[2];
|
||||||
|
DivDispatchOscBuffer* oscBuf[2];
|
||||||
bool isMuted[2];
|
bool isMuted[2];
|
||||||
|
|
||||||
k005289_core* k005289;
|
k005289_core* k005289;
|
||||||
|
@ -66,6 +67,7 @@ class DivPlatformBubSysWSG: public DivDispatch {
|
||||||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||||
int dispatch(DivCommand c);
|
int dispatch(DivCommand c);
|
||||||
void* getChanState(int chan);
|
void* getChanState(int chan);
|
||||||
|
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||||
unsigned char* getRegisterPool();
|
unsigned char* getRegisterPool();
|
||||||
int getRegisterPoolSize();
|
int getRegisterPoolSize();
|
||||||
int getRegisterPoolDepth();
|
int getRegisterPoolDepth();
|
||||||
|
|
|
@ -112,6 +112,12 @@ void DivPlatformC64::acquire(short* bufL, short* bufR, size_t start, size_t len)
|
||||||
for (size_t i=start; i<start+len; i++) {
|
for (size_t i=start; i<start+len; i++) {
|
||||||
sid.clock();
|
sid.clock();
|
||||||
bufL[i]=sid.output();
|
bufL[i]=sid.output();
|
||||||
|
if (++writeOscBuf>=8) {
|
||||||
|
writeOscBuf=0;
|
||||||
|
oscBuf[0]->data[oscBuf[0]->needle++]=sid.last_chan_out[0];
|
||||||
|
oscBuf[1]->data[oscBuf[1]->needle++]=sid.last_chan_out[1];
|
||||||
|
oscBuf[2]->data[oscBuf[2]->needle++]=sid.last_chan_out[2];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,6 +491,10 @@ void* DivPlatformC64::getChanState(int ch) {
|
||||||
return &chan[ch];
|
return &chan[ch];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DivDispatchOscBuffer* DivPlatformC64::getOscBuffer(int ch) {
|
||||||
|
return oscBuf[ch];
|
||||||
|
}
|
||||||
|
|
||||||
unsigned char* DivPlatformC64::getRegisterPool() {
|
unsigned char* DivPlatformC64::getRegisterPool() {
|
||||||
return regPool;
|
return regPool;
|
||||||
}
|
}
|
||||||
|
@ -545,14 +555,19 @@ void DivPlatformC64::setFlags(unsigned int flags) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
chipClock=rate;
|
chipClock=rate;
|
||||||
|
for (int i=0; i<3; i++) {
|
||||||
|
oscBuf[i]->rate=rate/16;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
||||||
parent=p;
|
parent=p;
|
||||||
dumpWrites=false;
|
dumpWrites=false;
|
||||||
skipRegisterWrites=false;
|
skipRegisterWrites=false;
|
||||||
|
writeOscBuf=0;
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i<3; i++) {
|
||||||
isMuted[i]=false;
|
isMuted[i]=false;
|
||||||
|
oscBuf[i]=new DivDispatchOscBuffer;
|
||||||
}
|
}
|
||||||
setFlags(flags);
|
setFlags(flags);
|
||||||
|
|
||||||
|
@ -562,6 +577,9 @@ int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, unsigned int f
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformC64::quit() {
|
void DivPlatformC64::quit() {
|
||||||
|
for (int i=0; i<3; i++) {
|
||||||
|
delete oscBuf[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DivPlatformC64::~DivPlatformC64() {
|
DivPlatformC64::~DivPlatformC64() {
|
||||||
|
|
|
@ -70,9 +70,11 @@ class DivPlatformC64: public DivDispatch {
|
||||||
vol(15) {}
|
vol(15) {}
|
||||||
};
|
};
|
||||||
Channel chan[3];
|
Channel chan[3];
|
||||||
|
DivDispatchOscBuffer* oscBuf[3];
|
||||||
bool isMuted[3];
|
bool isMuted[3];
|
||||||
|
|
||||||
unsigned char filtControl, filtRes, vol;
|
unsigned char filtControl, filtRes, vol;
|
||||||
|
unsigned char writeOscBuf;
|
||||||
int filtCut, resetTime;
|
int filtCut, resetTime;
|
||||||
|
|
||||||
SID sid;
|
SID sid;
|
||||||
|
@ -85,6 +87,7 @@ class DivPlatformC64: public DivDispatch {
|
||||||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||||
int dispatch(DivCommand c);
|
int dispatch(DivCommand c);
|
||||||
void* getChanState(int chan);
|
void* getChanState(int chan);
|
||||||
|
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||||
unsigned char* getRegisterPool();
|
unsigned char* getRegisterPool();
|
||||||
int getRegisterPoolSize();
|
int getRegisterPoolSize();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
|
@ -115,6 +115,14 @@ void DivPlatformNES::acquire(short* bufL, short* bufR, size_t start, size_t len)
|
||||||
if (sample>32767) sample=32767;
|
if (sample>32767) sample=32767;
|
||||||
if (sample<-32768) sample=-32768;
|
if (sample<-32768) sample=-32768;
|
||||||
bufL[i]=sample;
|
bufL[i]=sample;
|
||||||
|
if (++writeOscBuf>=32) {
|
||||||
|
writeOscBuf=0;
|
||||||
|
oscBuf[0]->data[oscBuf[0]->needle++]=nes->S1.output<<7;
|
||||||
|
oscBuf[1]->data[oscBuf[1]->needle++]=nes->S2.output<<7;
|
||||||
|
oscBuf[2]->data[oscBuf[2]->needle++]=nes->TR.output<<7;
|
||||||
|
oscBuf[3]->data[oscBuf[3]->needle++]=nes->NS.output<<7;
|
||||||
|
oscBuf[4]->data[oscBuf[4]->needle++]=nes->DMC.output<<7;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,6 +482,10 @@ void* DivPlatformNES::getChanState(int ch) {
|
||||||
return &chan[ch];
|
return &chan[ch];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DivDispatchOscBuffer* DivPlatformNES::getOscBuffer(int ch) {
|
||||||
|
return oscBuf[ch];
|
||||||
|
}
|
||||||
|
|
||||||
unsigned char* DivPlatformNES::getRegisterPool() {
|
unsigned char* DivPlatformNES::getRegisterPool() {
|
||||||
return regPool;
|
return regPool;
|
||||||
}
|
}
|
||||||
|
@ -533,6 +545,9 @@ void DivPlatformNES::setFlags(unsigned int flags) {
|
||||||
nes->apu.type=apuType;
|
nes->apu.type=apuType;
|
||||||
}
|
}
|
||||||
chipClock=rate;
|
chipClock=rate;
|
||||||
|
for (int i=0; i<5; i++) {
|
||||||
|
oscBuf[i]->rate=rate/32;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformNES::notifyInsDeletion(void* ins) {
|
void DivPlatformNES::notifyInsDeletion(void* ins) {
|
||||||
|
@ -555,9 +570,11 @@ int DivPlatformNES::init(DivEngine* p, int channels, int sugRate, unsigned int f
|
||||||
dumpWrites=false;
|
dumpWrites=false;
|
||||||
skipRegisterWrites=false;
|
skipRegisterWrites=false;
|
||||||
nes=new struct NESAPU;
|
nes=new struct NESAPU;
|
||||||
|
writeOscBuf=0;
|
||||||
for (int i=0; i<5; i++) {
|
for (int i=0; i<5; i++) {
|
||||||
isMuted[i]=false;
|
isMuted[i]=false;
|
||||||
nes->muted[i]=false;
|
nes->muted[i]=false;
|
||||||
|
oscBuf[i]=new DivDispatchOscBuffer;
|
||||||
}
|
}
|
||||||
setFlags(flags);
|
setFlags(flags);
|
||||||
|
|
||||||
|
@ -567,6 +584,9 @@ int DivPlatformNES::init(DivEngine* p, int channels, int sugRate, unsigned int f
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformNES::quit() {
|
void DivPlatformNES::quit() {
|
||||||
|
for (int i=0; i<5; i++) {
|
||||||
|
delete oscBuf[i];
|
||||||
|
}
|
||||||
delete nes;
|
delete nes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,11 +57,13 @@ class DivPlatformNES: public DivDispatch {
|
||||||
wave(-1) {}
|
wave(-1) {}
|
||||||
};
|
};
|
||||||
Channel chan[5];
|
Channel chan[5];
|
||||||
|
DivDispatchOscBuffer* oscBuf[5];
|
||||||
bool isMuted[5];
|
bool isMuted[5];
|
||||||
int dacPeriod, dacRate;
|
int dacPeriod, dacRate;
|
||||||
unsigned int dacPos, dacAntiClick;
|
unsigned int dacPos, dacAntiClick;
|
||||||
int dacSample;
|
int dacSample;
|
||||||
unsigned char sampleBank;
|
unsigned char sampleBank;
|
||||||
|
unsigned char writeOscBuf;
|
||||||
unsigned char apuType;
|
unsigned char apuType;
|
||||||
bool dacAntiClickOn;
|
bool dacAntiClickOn;
|
||||||
struct NESAPU* nes;
|
struct NESAPU* nes;
|
||||||
|
@ -73,6 +75,7 @@ class DivPlatformNES: public DivDispatch {
|
||||||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||||
int dispatch(DivCommand c);
|
int dispatch(DivCommand c);
|
||||||
void* getChanState(int chan);
|
void* getChanState(int chan);
|
||||||
|
DivDispatchOscBuffer* getOscBuffer(int chan);
|
||||||
unsigned char* getRegisterPool();
|
unsigned char* getRegisterPool();
|
||||||
int getRegisterPoolSize();
|
int getRegisterPoolSize();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
|
@ -44,6 +44,10 @@ SID::SID()
|
||||||
isMuted[0]=false;
|
isMuted[0]=false;
|
||||||
isMuted[1]=false;
|
isMuted[1]=false;
|
||||||
isMuted[2]=false;
|
isMuted[2]=false;
|
||||||
|
|
||||||
|
last_chan_out[0]=0;
|
||||||
|
last_chan_out[1]=0;
|
||||||
|
last_chan_out[2]=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -638,8 +642,13 @@ void SID::clock()
|
||||||
voice[i].wave.synchronize();
|
voice[i].wave.synchronize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// write voice output
|
||||||
|
last_chan_out[0]=isMuted[0]?0:voice[0].output();
|
||||||
|
last_chan_out[1]=isMuted[1]?0:voice[1].output();
|
||||||
|
last_chan_out[2]=isMuted[2]?0:voice[2].output();
|
||||||
|
|
||||||
// Clock filter.
|
// Clock filter.
|
||||||
filter.clock(isMuted[0]?0:voice[0].output(), isMuted[1]?0:voice[1].output(), isMuted[2]?0:voice[2].output(), ext_in);
|
filter.clock(last_chan_out[0], last_chan_out[1], last_chan_out[2], ext_in);
|
||||||
|
|
||||||
// Clock external filter.
|
// Clock external filter.
|
||||||
extfilt.clock(filter.output());
|
extfilt.clock(filter.output());
|
||||||
|
@ -717,9 +726,14 @@ void SID::clock(cycle_count delta_t)
|
||||||
delta_t_osc -= delta_t_min;
|
delta_t_osc -= delta_t_min;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// write voice output
|
||||||
|
last_chan_out[0]=isMuted[0]?0:voice[0].output();
|
||||||
|
last_chan_out[1]=isMuted[1]?0:voice[1].output();
|
||||||
|
last_chan_out[2]=isMuted[2]?0:voice[2].output();
|
||||||
|
|
||||||
// Clock filter.
|
// Clock filter.
|
||||||
filter.clock(delta_t,
|
filter.clock(delta_t,
|
||||||
isMuted[0]?0:voice[0].output(), isMuted[1]?0:voice[1].output(), isMuted[2]?0:voice[2].output(), ext_in);
|
last_chan_out[0], last_chan_out[1], last_chan_out[2], ext_in);
|
||||||
|
|
||||||
// Clock external filter.
|
// Clock external filter.
|
||||||
extfilt.clock(delta_t, filter.output());
|
extfilt.clock(delta_t, filter.output());
|
||||||
|
|
|
@ -32,6 +32,8 @@ public:
|
||||||
SID();
|
SID();
|
||||||
~SID();
|
~SID();
|
||||||
|
|
||||||
|
sound_sample last_chan_out[3];
|
||||||
|
|
||||||
void set_is_muted(int ch, bool val);
|
void set_is_muted(int ch, bool val);
|
||||||
void set_chip_model(chip_model model);
|
void set_chip_model(chip_model model);
|
||||||
void enable_filter(bool enable);
|
void enable_filter(bool enable);
|
||||||
|
|
Loading…
Reference in a new issue