From c738ece3746f334edbbaaec1eb618f15ca0dee88 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 30 Apr 2022 14:36:12 -0500 Subject: [PATCH] per-channel oscilloscope, part 2 AY8930, K00, C64 and NES --- src/engine/platform/ay8930.cpp | 20 +++++++++++++++++++- src/engine/platform/ay8930.h | 2 ++ src/engine/platform/bubsyswsg.cpp | 19 +++++++++++++++++-- src/engine/platform/bubsyswsg.h | 2 ++ src/engine/platform/c64.cpp | 18 ++++++++++++++++++ src/engine/platform/c64.h | 3 +++ src/engine/platform/nes.cpp | 20 ++++++++++++++++++++ src/engine/platform/nes.h | 3 +++ src/engine/platform/sound/c64/sid.cc | 18 ++++++++++++++++-- src/engine/platform/sound/c64/sid.h | 2 ++ 10 files changed, 102 insertions(+), 5 deletions(-) diff --git a/src/engine/platform/ay8930.cpp b/src/engine/platform/ay8930.cpp index e0cbd980..13308698 100644 --- a/src/engine/platform/ay8930.cpp +++ b/src/engine/platform/ay8930.cpp @@ -149,6 +149,12 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l bufR[i+start]=bufL[i+start]; } } + + for (int ch=0; ch<3; ch++) { + for (size_t i=0; idata[oscBuf[ch]->needle++]=ayBuf[ch][i]; + } + } } void DivPlatformAY8930::updateOutSel(bool immediate) { @@ -523,6 +529,10 @@ void* DivPlatformAY8930::getChanState(int ch) { return &chan[ch]; } +DivDispatchOscBuffer* DivPlatformAY8930::getOscBuffer(int ch) { + return oscBuf[ch]; +} + unsigned char* DivPlatformAY8930::getRegisterPool() { return regPool; } @@ -629,6 +639,10 @@ void DivPlatformAY8930::setFlags(unsigned int flags) { break; } rate=chipClock/8; + for (int i=0; i<3; i++) { + oscBuf[i]->rate=rate; + } + stereo=flags>>6; } @@ -638,6 +652,7 @@ int DivPlatformAY8930::init(DivEngine* p, int channels, int sugRate, unsigned in skipRegisterWrites=false; for (int i=0; i<3; i++) { isMuted[i]=false; + oscBuf[i]=new DivDispatchOscBuffer; } setFlags(flags); ay=new ay8930_device(rate); @@ -649,6 +664,9 @@ int DivPlatformAY8930::init(DivEngine* p, int channels, int sugRate, unsigned in } 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; } diff --git a/src/engine/platform/ay8930.h b/src/engine/platform/ay8930.h index ced107fc..ff992bb5 100644 --- a/src/engine/platform/ay8930.h +++ b/src/engine/platform/ay8930.h @@ -52,6 +52,7 @@ class DivPlatformAY8930: public DivDispatch { }; std::queue writes; ay8930_device* ay; + DivDispatchOscBuffer* oscBuf[3]; unsigned char regPool[32]; unsigned char ayNoiseAnd, ayNoiseOr; bool bank; @@ -79,6 +80,7 @@ class DivPlatformAY8930: public DivDispatch { void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); + DivDispatchOscBuffer* getOscBuffer(int chan); unsigned char* getRegisterPool(); int getRegisterPoolSize(); void reset(); diff --git a/src/engine/platform/bubsyswsg.cpp b/src/engine/platform/bubsyswsg.cpp index 3224bfee..2c09cf23 100644 --- a/src/engine/platform/bubsyswsg.cpp +++ b/src/engine/platform/bubsyswsg.cpp @@ -49,6 +49,7 @@ const char* DivPlatformBubSysWSG::getEffectName(unsigned char effect) { } void DivPlatformBubSysWSG::acquire(short* bufL, short* bufR, size_t start, size_t len) { + int chanOut=0; for (size_t h=start; haddr(i)]*(regPool[2+i]&0xf); + if (isMuted[i]) { + 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 @@ -267,6 +274,10 @@ void* DivPlatformBubSysWSG::getChanState(int ch) { return &chan[ch]; } +DivDispatchOscBuffer* DivPlatformBubSysWSG::getOscBuffer(int ch) { + return oscBuf[ch]; +} + unsigned char* DivPlatformBubSysWSG::getRegisterPool() { return (unsigned char*)regPool; } @@ -335,6 +346,7 @@ int DivPlatformBubSysWSG::init(DivEngine* p, int channels, int sugRate, unsigned skipRegisterWrites=false; for (int i=0; i<2; i++) { isMuted[i]=false; + oscBuf[i]=new DivDispatchOscBuffer; } setFlags(flags); k005289=new k005289_core(); @@ -343,6 +355,9 @@ int DivPlatformBubSysWSG::init(DivEngine* p, int channels, int sugRate, unsigned } void DivPlatformBubSysWSG::quit() { + for (int i=0; i<2; i++) { + delete oscBuf[i]; + } delete k005289; } diff --git a/src/engine/platform/bubsyswsg.h b/src/engine/platform/bubsyswsg.h index a28b4ac1..8eb6726f 100644 --- a/src/engine/platform/bubsyswsg.h +++ b/src/engine/platform/bubsyswsg.h @@ -56,6 +56,7 @@ class DivPlatformBubSysWSG: public DivDispatch { wave(-1) {} }; Channel chan[2]; + DivDispatchOscBuffer* oscBuf[2]; bool isMuted[2]; k005289_core* k005289; @@ -66,6 +67,7 @@ class DivPlatformBubSysWSG: public DivDispatch { void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); + DivDispatchOscBuffer* getOscBuffer(int chan); unsigned char* getRegisterPool(); int getRegisterPoolSize(); int getRegisterPoolDepth(); diff --git a/src/engine/platform/c64.cpp b/src/engine/platform/c64.cpp index 7e9cf4d1..63f1b470 100644 --- a/src/engine/platform/c64.cpp +++ b/src/engine/platform/c64.cpp @@ -112,6 +112,12 @@ void DivPlatformC64::acquire(short* bufL, short* bufR, size_t start, size_t len) for (size_t i=start; i=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]; } +DivDispatchOscBuffer* DivPlatformC64::getOscBuffer(int ch) { + return oscBuf[ch]; +} + unsigned char* DivPlatformC64::getRegisterPool() { return regPool; } @@ -545,14 +555,19 @@ void DivPlatformC64::setFlags(unsigned int flags) { break; } 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) { parent=p; dumpWrites=false; skipRegisterWrites=false; + writeOscBuf=0; for (int i=0; i<3; i++) { isMuted[i]=false; + oscBuf[i]=new DivDispatchOscBuffer; } setFlags(flags); @@ -562,6 +577,9 @@ int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, unsigned int f } void DivPlatformC64::quit() { + for (int i=0; i<3; i++) { + delete oscBuf[i]; + } } DivPlatformC64::~DivPlatformC64() { diff --git a/src/engine/platform/c64.h b/src/engine/platform/c64.h index a4968fee..495da461 100644 --- a/src/engine/platform/c64.h +++ b/src/engine/platform/c64.h @@ -70,9 +70,11 @@ class DivPlatformC64: public DivDispatch { vol(15) {} }; Channel chan[3]; + DivDispatchOscBuffer* oscBuf[3]; bool isMuted[3]; unsigned char filtControl, filtRes, vol; + unsigned char writeOscBuf; int filtCut, resetTime; SID sid; @@ -85,6 +87,7 @@ class DivPlatformC64: public DivDispatch { void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); + DivDispatchOscBuffer* getOscBuffer(int chan); unsigned char* getRegisterPool(); int getRegisterPoolSize(); void reset(); diff --git a/src/engine/platform/nes.cpp b/src/engine/platform/nes.cpp index f7a29066..ca528d82 100644 --- a/src/engine/platform/nes.cpp +++ b/src/engine/platform/nes.cpp @@ -115,6 +115,14 @@ void DivPlatformNES::acquire(short* bufL, short* bufR, size_t start, size_t len) if (sample>32767) sample=32767; if (sample<-32768) sample=-32768; 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]; } +DivDispatchOscBuffer* DivPlatformNES::getOscBuffer(int ch) { + return oscBuf[ch]; +} + unsigned char* DivPlatformNES::getRegisterPool() { return regPool; } @@ -533,6 +545,9 @@ void DivPlatformNES::setFlags(unsigned int flags) { nes->apu.type=apuType; } chipClock=rate; + for (int i=0; i<5; i++) { + oscBuf[i]->rate=rate/32; + } } void DivPlatformNES::notifyInsDeletion(void* ins) { @@ -555,9 +570,11 @@ int DivPlatformNES::init(DivEngine* p, int channels, int sugRate, unsigned int f dumpWrites=false; skipRegisterWrites=false; nes=new struct NESAPU; + writeOscBuf=0; for (int i=0; i<5; i++) { isMuted[i]=false; nes->muted[i]=false; + oscBuf[i]=new DivDispatchOscBuffer; } setFlags(flags); @@ -567,6 +584,9 @@ int DivPlatformNES::init(DivEngine* p, int channels, int sugRate, unsigned int f } void DivPlatformNES::quit() { + for (int i=0; i<5; i++) { + delete oscBuf[i]; + } delete nes; } diff --git a/src/engine/platform/nes.h b/src/engine/platform/nes.h index d88b447f..abd23da9 100644 --- a/src/engine/platform/nes.h +++ b/src/engine/platform/nes.h @@ -57,11 +57,13 @@ class DivPlatformNES: public DivDispatch { wave(-1) {} }; Channel chan[5]; + DivDispatchOscBuffer* oscBuf[5]; bool isMuted[5]; int dacPeriod, dacRate; unsigned int dacPos, dacAntiClick; int dacSample; unsigned char sampleBank; + unsigned char writeOscBuf; unsigned char apuType; bool dacAntiClickOn; struct NESAPU* nes; @@ -73,6 +75,7 @@ class DivPlatformNES: public DivDispatch { void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); void* getChanState(int chan); + DivDispatchOscBuffer* getOscBuffer(int chan); unsigned char* getRegisterPool(); int getRegisterPoolSize(); void reset(); diff --git a/src/engine/platform/sound/c64/sid.cc b/src/engine/platform/sound/c64/sid.cc index d33a0d35..d6ebbb44 100644 --- a/src/engine/platform/sound/c64/sid.cc +++ b/src/engine/platform/sound/c64/sid.cc @@ -44,6 +44,10 @@ SID::SID() isMuted[0]=false; isMuted[1]=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(); } + // 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. - 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. extfilt.clock(filter.output()); @@ -717,9 +726,14 @@ void SID::clock(cycle_count delta_t) 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. 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. extfilt.clock(delta_t, filter.output()); diff --git a/src/engine/platform/sound/c64/sid.h b/src/engine/platform/sound/c64/sid.h index 6dbe6c59..f6b39271 100644 --- a/src/engine/platform/sound/c64/sid.h +++ b/src/engine/platform/sound/c64/sid.h @@ -32,6 +32,8 @@ public: SID(); ~SID(); + sound_sample last_chan_out[3]; + void set_is_muted(int ch, bool val); void set_chip_model(chip_model model); void enable_filter(bool enable);