Merge branch 'master' of https://github.com/tildearrow/furnace into es5506_alt

* 'master' of https://github.com/tildearrow/furnace:
  Clang you are so arrogant
  ok so screw you
  let's hope this works
  attempt to fix CI
  per-channel oscilloscope, part 8
  per-channel oscilloscope, part 7
  per-channel oscilloscope, part 6
  per-channel oscilloscope, part 5
  but PCE supports samples!
  per-channel oscilloscope, part 4
  YM2612: fix Furnace DAC mode glitching slides
  per-channel oscilloscope, part 3
  GUI: add missing actions to settings
  per-channel oscilloscope, part 2
  Revert PC speaker presets
  Have host sound chip appear before expansions
This commit is contained in:
cam900 2022-05-01 19:59:03 +09:00
commit 329048bf6c
102 changed files with 847 additions and 90 deletions

View File

@ -307,7 +307,7 @@ BYTE CSAADevice::_ReadData(void)
} }
#endif #endif
void CSAADevice::_TickAndOutputStereo(unsigned int& left_mixed, unsigned int& right_mixed) void CSAADevice::_TickAndOutputStereo(unsigned int& left_mixed, unsigned int& right_mixed, DivDispatchOscBuffer** oscBuf)
{ {
unsigned int temp_left, temp_right; unsigned int temp_left, temp_right;
unsigned int accum_left = 0, accum_right = 0; unsigned int accum_left = 0, accum_right = 0;
@ -316,21 +316,27 @@ void CSAADevice::_TickAndOutputStereo(unsigned int& left_mixed, unsigned int& ri
m_Noise0.Tick(); m_Noise0.Tick();
m_Noise1.Tick(); m_Noise1.Tick();
m_Amp0.TickAndOutputStereo(temp_left, temp_right); m_Amp0.TickAndOutputStereo(temp_left, temp_right);
oscBuf[0]->data[oscBuf[0]->needle++]=(temp_left+temp_right)<<4;
accum_left += temp_left; accum_left += temp_left;
accum_right += temp_right; accum_right += temp_right;
m_Amp1.TickAndOutputStereo(temp_left, temp_right); m_Amp1.TickAndOutputStereo(temp_left, temp_right);
oscBuf[1]->data[oscBuf[1]->needle++]=(temp_left+temp_right)<<4;
accum_left += temp_left; accum_left += temp_left;
accum_right += temp_right; accum_right += temp_right;
m_Amp2.TickAndOutputStereo(temp_left, temp_right); m_Amp2.TickAndOutputStereo(temp_left, temp_right);
oscBuf[2]->data[oscBuf[2]->needle++]=(temp_left+temp_right)<<4;
accum_left += temp_left; accum_left += temp_left;
accum_right += temp_right; accum_right += temp_right;
m_Amp3.TickAndOutputStereo(temp_left, temp_right); m_Amp3.TickAndOutputStereo(temp_left, temp_right);
oscBuf[3]->data[oscBuf[3]->needle++]=(temp_left+temp_right)<<4;
accum_left += temp_left; accum_left += temp_left;
accum_right += temp_right; accum_right += temp_right;
m_Amp4.TickAndOutputStereo(temp_left, temp_right); m_Amp4.TickAndOutputStereo(temp_left, temp_right);
oscBuf[4]->data[oscBuf[4]->needle++]=(temp_left+temp_right)<<4;
accum_left += temp_left; accum_left += temp_left;
accum_right += temp_right; accum_right += temp_right;
m_Amp5.TickAndOutputStereo(temp_left, temp_right); m_Amp5.TickAndOutputStereo(temp_left, temp_right);
oscBuf[5]->data[oscBuf[5]->needle++]=(temp_left+temp_right)<<4;
accum_left += temp_left; accum_left += temp_left;
accum_right += temp_right; accum_right += temp_right;
} }

View File

@ -53,7 +53,7 @@ public:
void _SetClockRate(unsigned int nClockRate); void _SetClockRate(unsigned int nClockRate);
void _SetSampleRate(unsigned int nSampleRate); void _SetSampleRate(unsigned int nSampleRate);
void _SetOversample(unsigned int nOversample); void _SetOversample(unsigned int nOversample);
void _TickAndOutputStereo(unsigned int& left_mixed, unsigned int& right_mixed); void _TickAndOutputStereo(unsigned int& left_mixed, unsigned int& right_mixed, DivDispatchOscBuffer** oscBuf);
void _TickAndOutputSeparate(unsigned int& left_mixed, unsigned int& right_mixed, void _TickAndOutputSeparate(unsigned int& left_mixed, unsigned int& right_mixed,
unsigned int& left0, unsigned int& right0, unsigned int& left0, unsigned int& right0,
unsigned int& left1, unsigned int& right1, unsigned int& left1, unsigned int& right1,

View File

@ -298,7 +298,7 @@ void scale_for_output(unsigned int left_input, unsigned int right_input,
*pBuffer++ = (right_output >> 8) & 0x00ff; *pBuffer++ = (right_output >> 8) & 0x00ff;
} }
void CSAASoundInternal::GenerateMany(BYTE* pBuffer, unsigned long nSamples) void CSAASoundInternal::GenerateMany(BYTE* pBuffer, unsigned long nSamples, DivDispatchOscBuffer** oscBuf)
{ {
unsigned int left_mixed, right_mixed; unsigned int left_mixed, right_mixed;
static double filterout_z1_left_mixed = 0, filterout_z1_right_mixed = 0; static double filterout_z1_left_mixed = 0, filterout_z1_right_mixed = 0;
@ -376,7 +376,7 @@ void CSAASoundInternal::GenerateMany(BYTE* pBuffer, unsigned long nSamples)
#endif #endif
while (nSamples--) while (nSamples--)
{ {
m_chip._TickAndOutputStereo(left_mixed, right_mixed); m_chip._TickAndOutputStereo(left_mixed, right_mixed, oscBuf);
scale_for_output(left_mixed, right_mixed, oversample, m_bHighpass, nBoost, filterout_z1_left_mixed, filterout_z1_right_mixed, pBuffer); scale_for_output(left_mixed, right_mixed, oversample, m_bHighpass, nBoost, filterout_z1_left_mixed, filterout_z1_right_mixed, pBuffer);
} }

View File

@ -68,7 +68,7 @@ public:
unsigned short GetCurrentBytesPerSample(void); unsigned short GetCurrentBytesPerSample(void);
static unsigned short GetBytesPerSample(SAAPARAM uParam); static unsigned short GetBytesPerSample(SAAPARAM uParam);
void GenerateMany(BYTE * pBuffer, unsigned long nSamples); void GenerateMany(BYTE * pBuffer, unsigned long nSamples, DivDispatchOscBuffer** oscBuf);
}; };

View File

@ -81,7 +81,7 @@ unsigned long SAAAPI SAASNDGetSampleRate(SAAPARAM uParam)
void SAAAPI SAASNDGenerateMany(SAASND object, BYTE * pBuffer, unsigned long nSamples) void SAAAPI SAASNDGenerateMany(SAASND object, BYTE * pBuffer, unsigned long nSamples)
{ {
((LPCSAASOUND)(object))->GenerateMany(pBuffer, nSamples); ((LPCSAASOUND)(object))->GenerateMany(pBuffer, nSamples, NULL);
} }
void SAAAPI SAASNDSetSampleRate(SAASND object, unsigned int nSampleRate) void SAAAPI SAASNDSetSampleRate(SAASND object, unsigned int nSampleRate)

View File

@ -61,6 +61,8 @@ typedef unsigned long SAAPARAM;
#ifdef __cplusplus #ifdef __cplusplus
#include "../../src/engine/dispatch.h"
class CSAASound class CSAASound
{ {
public: public:
@ -79,7 +81,7 @@ public:
virtual unsigned short GetCurrentBytesPerSample () = 0; virtual unsigned short GetCurrentBytesPerSample () = 0;
static unsigned short GetBytesPerSample (SAAPARAM uParam); static unsigned short GetBytesPerSample (SAAPARAM uParam);
virtual void GenerateMany (BYTE * pBuffer, unsigned long nSamples) = 0; virtual void GenerateMany (BYTE * pBuffer, unsigned long nSamples, DivDispatchOscBuffer** oscBuf) = 0;
virtual void SetClockRate(unsigned int nClockRate) = 0; virtual void SetClockRate(unsigned int nClockRate) = 0;
virtual void SetSampleRate(unsigned int nSampleRate) = 0; virtual void SetSampleRate(unsigned int nSampleRate) = 0;

View File

@ -12,8 +12,10 @@
defined(__arm__) || \ defined(__arm__) || \
(defined(__mips__) && defined(__MIPSEL__)) (defined(__mips__) && defined(__MIPSEL__))
#else #else
#ifndef __BIG_ENDIAN
#define __BIG_ENDIAN #define __BIG_ENDIAN
#endif #endif
#endif
#ifndef NULL #ifndef NULL

8
extern/opm/opm.c vendored
View File

@ -1256,6 +1256,14 @@ static inline void OPM_Mixer(opm_t *chip)
} }
chip->mix[0] += chip->op_mix * chip->op_mixl; chip->mix[0] += chip->op_mix * chip->op_mixl;
chip->mix[1] += chip->op_mix * chip->op_mixr; chip->mix[1] += chip->op_mix * chip->op_mixr;
if (slot<8) {
chip->op_chmix[slot&7]=0;
}
chip->op_chmix[slot&7]+=chip->op_mix*(chip->op_mixl|chip->op_mixr);
if (slot>=24) {
chip->ch_out[slot&7]=chip->op_chmix[slot&7];
}
} }
static inline void OPM_Noise(opm_t *chip) static inline void OPM_Noise(opm_t *chip)

2
extern/opm/opm.h vendored
View File

@ -141,6 +141,7 @@ typedef struct {
int16_t op_fb[2]; int16_t op_fb[2];
uint8_t op_mixl; uint8_t op_mixl;
uint8_t op_mixr; uint8_t op_mixr;
uint16_t op_chmix[8];
// Mixer // Mixer
@ -161,6 +162,7 @@ typedef struct {
uint8_t smp_so; uint8_t smp_so;
uint8_t smp_sh1; uint8_t smp_sh1;
uint8_t smp_sh2; uint8_t smp_sh2;
uint16_t ch_out[8];
// Noise // Noise
uint32_t noise_lfsr; uint32_t noise_lfsr;

View File

@ -143,23 +143,29 @@ void DivPlatformArcade::acquire_nuked(short* bufL, short* bufR, size_t start, si
static int o[2]; static int o[2];
for (size_t h=start; h<start+len; h++) { for (size_t h=start; h<start+len; h++) {
if (!writes.empty() && !fm.write_busy) { for (int i=0; i<8; i++) {
QueuedWrite& w=writes.front(); if (!writes.empty() && !fm.write_busy) {
if (w.addrOrVal) { QueuedWrite& w=writes.front();
OPM_Write(&fm,1,w.val); if (w.addrOrVal) {
regPool[w.addr&0xff]=w.val; OPM_Write(&fm,1,w.val);
//printf("write: %x = %.2x\n",w.addr,w.val); regPool[w.addr&0xff]=w.val;
writes.pop(); //printf("write: %x = %.2x\n",w.addr,w.val);
} else { writes.pop();
OPM_Write(&fm,0,w.addr); } else {
w.addrOrVal=true; OPM_Write(&fm,0,w.addr);
w.addrOrVal=true;
}
} }
OPM_Clock(&fm,NULL,NULL,NULL,NULL);
OPM_Clock(&fm,NULL,NULL,NULL,NULL);
OPM_Clock(&fm,NULL,NULL,NULL,NULL);
OPM_Clock(&fm,o,NULL,NULL,NULL);
}
for (int i=0; i<8; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=fm.ch_out[i];
} }
OPM_Clock(&fm,NULL,NULL,NULL,NULL);
OPM_Clock(&fm,NULL,NULL,NULL,NULL);
OPM_Clock(&fm,NULL,NULL,NULL,NULL);
OPM_Clock(&fm,o,NULL,NULL,NULL);
if (o[0]<-32768) o[0]=-32768; if (o[0]<-32768) o[0]=-32768;
if (o[0]>32767) o[0]=32767; if (o[0]>32767) o[0]=32767;
@ -175,6 +181,8 @@ void DivPlatformArcade::acquire_nuked(short* bufL, short* bufR, size_t start, si
void DivPlatformArcade::acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len) { void DivPlatformArcade::acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len) {
static int os[2]; static int os[2];
ymfm::ym2151::fm_engine* fme=fm_ymfm->debug_engine();
for (size_t h=start; h<start+len; h++) { for (size_t h=start; h<start+len; h++) {
os[0]=0; os[1]=0; os[0]=0; os[1]=0;
if (!writes.empty()) { if (!writes.empty()) {
@ -190,6 +198,10 @@ void DivPlatformArcade::acquire_ymfm(short* bufL, short* bufR, size_t start, siz
fm_ymfm->generate(&out_ymfm); fm_ymfm->generate(&out_ymfm);
for (int i=0; i<8; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=(fme->debug_channel(i)->debug_output(0)+fme->debug_channel(i)->debug_output(1));
}
os[0]=out_ymfm.data[0]; os[0]=out_ymfm.data[0];
if (os[0]<-32768) os[0]=-32768; if (os[0]<-32768) os[0]=-32768;
if (os[0]>32767) os[0]=32767; if (os[0]>32767) os[0]=32767;
@ -725,6 +737,10 @@ void* DivPlatformArcade::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformArcade::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformArcade::getRegisterPool() { unsigned char* DivPlatformArcade::getRegisterPool() {
return regPool; return regPool;
} }
@ -792,10 +808,9 @@ void DivPlatformArcade::setFlags(unsigned int flags) {
chipClock=COLOR_NTSC; chipClock=COLOR_NTSC;
baseFreqOff=0; baseFreqOff=0;
} }
if (useYMFM) { rate=chipClock/64;
rate=chipClock/64; for (int i=0; i<8; i++) {
} else { oscBuf[i]->rate=rate;
rate=chipClock/8;
} }
} }
@ -813,6 +828,7 @@ int DivPlatformArcade::init(DivEngine* p, int channels, int sugRate, unsigned in
skipRegisterWrites=false; skipRegisterWrites=false;
for (int i=0; i<8; i++) { for (int i=0; i<8; i++) {
isMuted[i]=false; isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
} }
setFlags(flags); setFlags(flags);
if (useYMFM) fm_ymfm=new ymfm::ym2151(iface); if (useYMFM) fm_ymfm=new ymfm::ym2151(iface);
@ -822,6 +838,9 @@ int DivPlatformArcade::init(DivEngine* p, int channels, int sugRate, unsigned in
} }
void DivPlatformArcade::quit() { void DivPlatformArcade::quit() {
for (int i=0; i<8; i++) {
delete oscBuf[i];
}
if (useYMFM) { if (useYMFM) {
delete fm_ymfm; delete fm_ymfm;
} }

View File

@ -70,6 +70,7 @@ class DivPlatformArcade: public DivDispatch {
chVolR(127) {} chVolR(127) {}
}; };
Channel chan[8]; Channel chan[8];
DivDispatchOscBuffer* oscBuf[8];
struct QueuedWrite { struct QueuedWrite {
unsigned short addr; unsigned short addr;
unsigned char val; unsigned char val;
@ -108,6 +109,7 @@ class DivPlatformArcade: 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();

View File

@ -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;
} }

View File

@ -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();

View File

@ -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,10 +57,20 @@ 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;
if (writeOscBuf==0) {
oscBuf[i]->data[oscBuf[i]->needle++]=chanOut<<7;
}
}
} }
if (++writeOscBuf>=64) writeOscBuf=0;
out<<=6; // scale output to 16 bit out<<=6; // scale output to 16 bit
if (out<-32768) out=-32768; if (out<-32768) out=-32768;
@ -267,6 +278,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;
} }
@ -319,6 +334,9 @@ void DivPlatformBubSysWSG::notifyInsDeletion(void* ins) {
void DivPlatformBubSysWSG::setFlags(unsigned int flags) { void DivPlatformBubSysWSG::setFlags(unsigned int flags) {
chipClock=COLOR_NTSC; chipClock=COLOR_NTSC;
rate=chipClock; rate=chipClock;
for (int i=0; i<2; i++) {
oscBuf[i]->rate=rate/64;
}
} }
void DivPlatformBubSysWSG::poke(unsigned int addr, unsigned short val) { void DivPlatformBubSysWSG::poke(unsigned int addr, unsigned short val) {
@ -333,8 +351,10 @@ int DivPlatformBubSysWSG::init(DivEngine* p, int channels, int sugRate, unsigned
parent=p; parent=p;
dumpWrites=false; dumpWrites=false;
skipRegisterWrites=false; skipRegisterWrites=false;
writeOscBuf=0;
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 +363,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;
} }

View File

@ -56,7 +56,9 @@ class DivPlatformBubSysWSG: public DivDispatch {
wave(-1) {} wave(-1) {}
}; };
Channel chan[2]; Channel chan[2];
DivDispatchOscBuffer* oscBuf[2];
bool isMuted[2]; bool isMuted[2];
unsigned char writeOscBuf;
k005289_core* k005289; k005289_core* k005289;
unsigned short regPool[4]; unsigned short regPool[4];
@ -66,6 +68,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();

View File

@ -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]>>5;
oscBuf[1]->data[oscBuf[1]->needle++]=sid.last_chan_out[1]>>5;
oscBuf[2]->data[oscBuf[2]->needle++]=sid.last_chan_out[2]>>5;
}
} }
} }
@ -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() {

View File

@ -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();

View File

@ -85,6 +85,10 @@ void DivPlatformFDS::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->data[oscBuf->needle++]=sample<<1;
}
} }
} }
@ -396,6 +400,10 @@ void* DivPlatformFDS::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformFDS::getOscBuffer(int ch) {
return oscBuf;
}
unsigned char* DivPlatformFDS::getRegisterPool() { unsigned char* DivPlatformFDS::getRegisterPool() {
return regPool; return regPool;
} }
@ -436,6 +444,7 @@ void DivPlatformFDS::setFlags(unsigned int flags) {
rate=COLOR_NTSC/2.0; rate=COLOR_NTSC/2.0;
} }
chipClock=rate; chipClock=rate;
oscBuf->rate=rate/32;
} }
void DivPlatformFDS::notifyInsDeletion(void* ins) { void DivPlatformFDS::notifyInsDeletion(void* ins) {
@ -457,7 +466,9 @@ int DivPlatformFDS::init(DivEngine* p, int channels, int sugRate, unsigned int f
apuType=flags; apuType=flags;
dumpWrites=false; dumpWrites=false;
skipRegisterWrites=false; skipRegisterWrites=false;
writeOscBuf=0;
fds=new struct _fds; fds=new struct _fds;
oscBuf=new DivDispatchOscBuffer;
for (int i=0; i<1; i++) { for (int i=0; i<1; i++) {
isMuted[i]=false; isMuted[i]=false;
} }
@ -468,6 +479,7 @@ int DivPlatformFDS::init(DivEngine* p, int channels, int sugRate, unsigned int f
} }
void DivPlatformFDS::quit() { void DivPlatformFDS::quit() {
delete oscBuf;
delete fds; delete fds;
} }

View File

@ -64,9 +64,11 @@ class DivPlatformFDS: public DivDispatch {
} }
}; };
Channel chan[1]; Channel chan[1];
DivDispatchOscBuffer* oscBuf;
bool isMuted[1]; bool isMuted[1];
DivWaveSynth ws; DivWaveSynth ws;
unsigned char apuType; unsigned char apuType;
unsigned char writeOscBuf;
struct _fds* fds; struct _fds* fds;
unsigned char regPool[128]; unsigned char regPool[128];
@ -78,6 +80,7 @@ class DivPlatformFDS: 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();

View File

@ -87,6 +87,10 @@ void DivPlatformGB::acquire(short* bufL, short* bufR, size_t start, size_t len)
GB_advance_cycles(gb,16); GB_advance_cycles(gb,16);
bufL[i]=gb->apu_output.final_sample.left; bufL[i]=gb->apu_output.final_sample.left;
bufR[i]=gb->apu_output.final_sample.right; bufR[i]=gb->apu_output.final_sample.right;
for (int i=0; i<4; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=(gb->apu_output.current_sample[i].left+gb->apu_output.current_sample[i].right)<<6;
}
} }
} }
@ -429,6 +433,10 @@ void* DivPlatformGB::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformGB::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformGB::getRegisterPool() { unsigned char* DivPlatformGB::getRegisterPool() {
return regPool; return regPool;
} }
@ -495,20 +503,25 @@ void DivPlatformGB::poke(std::vector<DivRegWrite>& wlist) {
} }
int DivPlatformGB::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { int DivPlatformGB::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
chipClock=4194304;
rate=chipClock/16;
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
isMuted[i]=false; isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
oscBuf[i]->rate=rate;
} }
parent=p; parent=p;
dumpWrites=false; dumpWrites=false;
skipRegisterWrites=false; skipRegisterWrites=false;
chipClock=4194304;
rate=chipClock/16;
gb=new GB_gameboy_t; gb=new GB_gameboy_t;
reset(); reset();
return 4; return 4;
} }
void DivPlatformGB::quit() { void DivPlatformGB::quit() {
for (int i=0; i<4; i++) {
delete oscBuf[i];
}
delete gb; delete gb;
} }

View File

@ -57,6 +57,7 @@ class DivPlatformGB: public DivDispatch {
wave(-1) {} wave(-1) {}
}; };
Channel chan[4]; Channel chan[4];
DivDispatchOscBuffer* oscBuf[4];
bool isMuted[4]; bool isMuted[4];
unsigned char lastPan; unsigned char lastPan;
DivWaveSynth ws; DivWaveSynth ws;
@ -71,6 +72,7 @@ class DivPlatformGB: 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();

View File

@ -145,7 +145,8 @@ void DivPlatformGenesis::acquire_nuked(short* bufL, short* bufR, size_t start, s
OPN2_Clock(&fm,o); os[0]+=o[0]; os[1]+=o[1]; OPN2_Clock(&fm,o); os[0]+=o[0]; os[1]+=o[1];
//OPN2_Write(&fm,0,0); //OPN2_Write(&fm,0,0);
} oscBuf[i]->data[oscBuf[i]->needle++]=fm.ch_out[i]<<7;
}
os[0]=(os[0]<<5); os[0]=(os[0]<<5);
if (os[0]<-32768) os[0]=-32768; if (os[0]<-32768) os[0]=-32768;
@ -163,6 +164,8 @@ void DivPlatformGenesis::acquire_nuked(short* bufL, short* bufR, size_t start, s
void DivPlatformGenesis::acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len) { void DivPlatformGenesis::acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len) {
static int os[2]; static int os[2];
ymfm::ym2612::fm_engine* fme=fm_ymfm->debug_engine();
for (size_t h=start; h<start+len; h++) { for (size_t h=start; h<start+len; h++) {
if (!dacReady) { if (!dacReady) {
dacDelay+=32000; dacDelay+=32000;
@ -218,6 +221,10 @@ void DivPlatformGenesis::acquire_ymfm(short* bufL, short* bufR, size_t start, si
os[0]=out_ymfm.data[0]; os[0]=out_ymfm.data[0];
os[1]=out_ymfm.data[1]; os[1]=out_ymfm.data[1];
//OPN2_Write(&fm,0,0); //OPN2_Write(&fm,0,0);
for (int i=0; i<6; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=(fme->debug_channel(i)->debug_output(0)+fme->debug_channel(i)->debug_output(1))<<6;
}
if (os[0]<-32768) os[0]=-32768; if (os[0]<-32768) os[0]=-32768;
if (os[0]>32767) os[0]=32767; if (os[0]>32767) os[0]=32767;
@ -649,7 +656,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_NOTE_PORTA: { case DIV_CMD_NOTE_PORTA: {
if (c.chan==5 && chan[c.chan].furnaceDac) { if (c.chan==5 && chan[c.chan].furnaceDac && dacMode) {
int destFreq=parent->calcBaseFreq(1,1,c.value2,false); int destFreq=parent->calcBaseFreq(1,1,c.value2,false);
bool return2=false; bool return2=false;
if (destFreq>chan[c.chan].baseFreq) { if (destFreq>chan[c.chan].baseFreq) {
@ -726,7 +733,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
} }
break; break;
case DIV_CMD_LEGATO: { case DIV_CMD_LEGATO: {
if (c.chan==5 && chan[c.chan].furnaceDac) { if (c.chan==5 && chan[c.chan].furnaceDac && dacMode) {
chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false); chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false);
} else { } else {
chan[c.chan].baseFreq=NOTE_FNUM_BLOCK(c.value,11); chan[c.chan].baseFreq=NOTE_FNUM_BLOCK(c.value,11);
@ -846,6 +853,10 @@ void* DivPlatformGenesis::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformGenesis::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformGenesis::getRegisterPool() { unsigned char* DivPlatformGenesis::getRegisterPool() {
return regPool; return regPool;
} }
@ -958,6 +969,9 @@ void DivPlatformGenesis::setFlags(unsigned int flags) {
} else { } else {
rate=chipClock/36; rate=chipClock/36;
} }
for (int i=0; i<10; i++) {
oscBuf[i]->rate=rate;
}
} }
int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
@ -967,6 +981,7 @@ int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate, unsigned i
skipRegisterWrites=false; skipRegisterWrites=false;
for (int i=0; i<10; i++) { for (int i=0; i<10; i++) {
isMuted[i]=false; isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
} }
fm_ymfm=NULL; fm_ymfm=NULL;
setFlags(flags); setFlags(flags);
@ -976,6 +991,9 @@ int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate, unsigned i
} }
void DivPlatformGenesis::quit() { void DivPlatformGenesis::quit() {
for (int i=0; i<10; i++) {
delete oscBuf[i];
}
if (fm_ymfm!=NULL) delete fm_ymfm; if (fm_ymfm!=NULL) delete fm_ymfm;
} }

View File

@ -68,6 +68,7 @@ class DivPlatformGenesis: public DivDispatch {
pan(3) {} pan(3) {}
}; };
Channel chan[10]; Channel chan[10];
DivDispatchOscBuffer* oscBuf[10];
bool isMuted[10]; bool isMuted[10];
struct QueuedWrite { struct QueuedWrite {
unsigned short addr; unsigned short addr;
@ -110,6 +111,7 @@ class DivPlatformGenesis: 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();

View File

@ -391,6 +391,12 @@ void* DivPlatformGenesisExt::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformGenesisExt::getOscBuffer(int ch) {
if (ch>=6) return oscBuf[ch-3];
if (ch<3) return oscBuf[ch];
return NULL;
}
void DivPlatformGenesisExt::reset() { void DivPlatformGenesisExt::reset() {
DivPlatformGenesis::reset(); DivPlatformGenesis::reset();

View File

@ -54,6 +54,7 @@ class DivPlatformGenesisExt: public DivPlatformGenesis {
public: public:
int dispatch(DivCommand c); int dispatch(DivCommand c);
void* getChanState(int chan); void* getChanState(int chan);
DivDispatchOscBuffer* getOscBuffer(int chan);
void reset(); void reset();
void forceIns(); void forceIns();
void tick(bool sysTick=true); void tick(bool sysTick=true);

View File

@ -142,7 +142,7 @@ 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 ); mikey->sampleAudio( bufL + start, bufR + start, len, oscBuf );
} }
void DivPlatformLynx::tick(bool sysTick) { void DivPlatformLynx::tick(bool sysTick) {
@ -342,6 +342,10 @@ void* DivPlatformLynx::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformLynx::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformLynx::getRegisterPool() unsigned char* DivPlatformLynx::getRegisterPool()
{ {
return const_cast<unsigned char*>( mikey->getRegisterPool() ); return const_cast<unsigned char*>( mikey->getRegisterPool() );
@ -398,16 +402,24 @@ int DivPlatformLynx::init(DivEngine* p, int channels, int sugRate, unsigned int
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
isMuted[i]=false; isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
} }
chipClock = 16000000; chipClock = 16000000;
rate = chipClock/128; rate = chipClock/128;
for (int i=0; i<4; i++) {
oscBuf[i]->rate=rate;
}
reset(); reset();
return 4; return 4;
} }
void DivPlatformLynx::quit() { void DivPlatformLynx::quit() {
for (int i=0; i<4; i++) {
delete oscBuf[i];
}
mikey.reset(); mikey.reset();
} }

View File

@ -74,6 +74,7 @@ class DivPlatformLynx: public DivDispatch {
outVol(127) {} outVol(127) {}
}; };
Channel chan[4]; Channel chan[4];
DivDispatchOscBuffer* oscBuf[4];
bool isMuted[4]; bool isMuted[4];
std::unique_ptr<Lynx::Mikey> mikey; std::unique_ptr<Lynx::Mikey> mikey;
friend void putDispatchChan(void*,int,int); friend void putDispatchChan(void*,int,int);
@ -81,6 +82,7 @@ class DivPlatformLynx: 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();

View File

@ -59,7 +59,7 @@ void DivPlatformMMC5::acquire(short* bufL, short* bufR, size_t start, size_t len
if (dacPeriod>=rate) { if (dacPeriod>=rate) {
DivSample* s=parent->getSample(dacSample); DivSample* s=parent->getSample(dacSample);
if (s->samples>0) { if (s->samples>0) {
if (!isMuted[4]) { if (!isMuted[2]) {
rWrite(0x5011,((unsigned char)s->data8[dacPos]+0x80)); rWrite(0x5011,((unsigned char)s->data8[dacPos]+0x80));
} }
dacPos++; dacPos++;
@ -93,6 +93,13 @@ void DivPlatformMMC5::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++]=isMuted[0]?0:((mmc5->S3.output*10)<<7);
oscBuf[1]->data[oscBuf[1]->needle++]=isMuted[1]?0:((mmc5->S4.output*10)<<7);
oscBuf[2]->data[oscBuf[2]->needle++]=isMuted[2]?0:((mmc5->pcm.output*2)<<6);
}
} }
} }
@ -165,18 +172,18 @@ void DivPlatformMMC5::tick(bool sysTick) {
} }
// PCM // PCM
if (chan[4].freqChanged) { if (chan[2].freqChanged) {
chan[4].freq=parent->calcFreq(chan[4].baseFreq,chan[4].pitch,false); chan[2].freq=parent->calcFreq(chan[2].baseFreq,chan[2].pitch,false);
if (chan[4].furnaceDac) { if (chan[2].furnaceDac) {
double off=1.0; double off=1.0;
if (dacSample>=0 && dacSample<parent->song.sampleLen) { if (dacSample>=0 && dacSample<parent->song.sampleLen) {
DivSample* s=parent->getSample(dacSample); DivSample* s=parent->getSample(dacSample);
off=(double)s->centerRate/8363.0; off=(double)s->centerRate/8363.0;
} }
dacRate=MIN(chan[4].freq*off,32000); dacRate=MIN(chan[2].freq*off,32000);
if (dumpWrites) addWrite(0xffff0001,dacRate); if (dumpWrites) addWrite(0xffff0001,dacRate);
} }
chan[4].freqChanged=false; chan[2].freqChanged=false;
} }
} }
@ -343,6 +350,10 @@ void* DivPlatformMMC5::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformMMC5::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformMMC5::getRegisterPool() { unsigned char* DivPlatformMMC5::getRegisterPool() {
return regPool; return regPool;
} }
@ -390,6 +401,9 @@ void DivPlatformMMC5::setFlags(unsigned int flags) {
rate=COLOR_NTSC/2.0; rate=COLOR_NTSC/2.0;
} }
chipClock=rate; chipClock=rate;
for (int i=0; i<3; i++) {
oscBuf[i]->rate=rate/32;
}
} }
void DivPlatformMMC5::notifyInsDeletion(void* ins) { void DivPlatformMMC5::notifyInsDeletion(void* ins) {
@ -411,9 +425,11 @@ int DivPlatformMMC5::init(DivEngine* p, int channels, int sugRate, unsigned int
apuType=flags; apuType=flags;
dumpWrites=false; dumpWrites=false;
skipRegisterWrites=false; skipRegisterWrites=false;
writeOscBuf=0;
mmc5=new struct _mmc5; mmc5=new struct _mmc5;
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
isMuted[i]=false; isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
//mmc5->muted[i]=false; // TODO //mmc5->muted[i]=false; // TODO
} }
setFlags(flags); setFlags(flags);
@ -424,6 +440,9 @@ int DivPlatformMMC5::init(DivEngine* p, int channels, int sugRate, unsigned int
} }
void DivPlatformMMC5::quit() { void DivPlatformMMC5::quit() {
for (int i=0; i<3; i++) {
delete oscBuf[i];
}
delete mmc5; delete mmc5;
} }

View File

@ -57,12 +57,14 @@ class DivPlatformMMC5: public DivDispatch {
wave(-1) {} wave(-1) {}
}; };
Channel chan[5]; Channel chan[5];
DivDispatchOscBuffer* oscBuf[3];
bool isMuted[5]; bool isMuted[5];
int dacPeriod, dacRate; int dacPeriod, dacRate;
unsigned int dacPos; unsigned int dacPos;
int dacSample; int dacSample;
unsigned char sampleBank; unsigned char sampleBank;
unsigned char apuType; unsigned char apuType;
unsigned char writeOscBuf;
struct _mmc5* mmc5; struct _mmc5* mmc5;
unsigned char regPool[128]; unsigned char regPool[128];
@ -72,6 +74,7 @@ class DivPlatformMMC5: 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();

View File

@ -161,6 +161,10 @@ void DivPlatformN163::acquire(short* bufL, short* bufR, size_t start, size_t len
if (out<-32768) out=-32768; if (out<-32768) out=-32768;
bufL[i]=bufR[i]=out; bufL[i]=bufR[i]=out;
if (n163.voice_cycle()==0x78) for (int i=0; i<8; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=n163.chan_out(i)<<7;
}
// command queue // command queue
while (!writes.empty()) { while (!writes.empty()) {
QueuedWrite w=writes.front(); QueuedWrite w=writes.front();
@ -619,6 +623,10 @@ void* DivPlatformN163::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformN163::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformN163::getRegisterPool() { unsigned char* DivPlatformN163::getRegisterPool() {
for (int i=0; i<128; i++) { for (int i=0; i<128; i++) {
regPool[i]=n163.reg(i); regPool[i]=n163.reg(i);
@ -678,6 +686,9 @@ void DivPlatformN163::setFlags(unsigned int flags) {
rate/=15; rate/=15;
n163.set_multiplex(multiplex); n163.set_multiplex(multiplex);
rWrite(0x7f,initChanMax<<4); rWrite(0x7f,initChanMax<<4);
for (int i=0; i<8; i++) {
oscBuf[i]->rate=rate/(initChanMax+1);
}
} }
int DivPlatformN163::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { int DivPlatformN163::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
@ -686,6 +697,7 @@ int DivPlatformN163::init(DivEngine* p, int channels, int sugRate, unsigned int
skipRegisterWrites=false; skipRegisterWrites=false;
for (int i=0; i<8; i++) { for (int i=0; i<8; i++) {
isMuted[i]=false; isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
} }
setFlags(flags); setFlags(flags);
@ -695,6 +707,9 @@ int DivPlatformN163::init(DivEngine* p, int channels, int sugRate, unsigned int
} }
void DivPlatformN163::quit() { void DivPlatformN163::quit() {
for (int i=0; i<8; i++) {
delete oscBuf[i];
}
} }
DivPlatformN163::~DivPlatformN163() { DivPlatformN163::~DivPlatformN163() {

View File

@ -70,6 +70,7 @@ class DivPlatformN163: public DivDispatch {
resVol(15) {} resVol(15) {}
}; };
Channel chan[8]; Channel chan[8];
DivDispatchOscBuffer* oscBuf[8];
bool isMuted[8]; bool isMuted[8];
struct QueuedWrite { struct QueuedWrite {
unsigned char addr; unsigned char addr;
@ -94,6 +95,7 @@ class DivPlatformN163: 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();

View File

@ -116,6 +116,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<<11;
oscBuf[1]->data[oscBuf[1]->needle++]=nes->S2.output<<11;
oscBuf[2]->data[oscBuf[2]->needle++]=nes->TR.output<<11;
oscBuf[3]->data[oscBuf[3]->needle++]=nes->NS.output<<11;
oscBuf[4]->data[oscBuf[4]->needle++]=nes->DMC.output<<8;
}
} }
} }
@ -475,6 +483,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;
} }
@ -534,6 +546,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) {
@ -556,9 +571,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);
@ -568,6 +585,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;
} }

View File

@ -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();

View File

@ -52,6 +52,10 @@ const unsigned short chanMapOPL2Drums[20]={
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 7, N, N, N, N, N, N, N, N, N 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 7, N, N, N, N, N, N, N, N, N
}; };
const unsigned char outChanMapOPL2[18]={
0, 1, 2, 3, 4, 5, 6, 7, 8, N, N, N, N, N, N, N, N, N
};
const unsigned char* slotsOPL2[4]={ const unsigned char* slotsOPL2[4]={
slotsOPL2i[0], slotsOPL2i[0],
slotsOPL2i[1], slotsOPL2i[1],
@ -88,6 +92,10 @@ const unsigned short chanMapOPL3Drums[20]={
0, 3, 1, 4, 2, 5, 0x100, 0x103, 0x101, 0x104, 0x102, 0x105, 0x106, 0x107, 0x108, 6, 7, 8, 8, 7 0, 3, 1, 4, 2, 5, 0x100, 0x103, 0x101, 0x104, 0x102, 0x105, 0x106, 0x107, 0x108, 6, 7, 8, 8, 7
}; };
const unsigned char outChanMapOPL3[18]={
0, 3, 1, 4, 2, 5, 9, 12, 10, 13, 11, 14, 15, 16, 17, 6, 7, 8
};
const unsigned char* slotsOPL3[4]={ const unsigned char* slotsOPL3[4]={
slotsOPL3i[0], slotsOPL3i[0],
slotsOPL3i[1], slotsOPL3i[1],
@ -208,6 +216,20 @@ void DivPlatformOPL::acquire_nuked(short* bufL, short* bufR, size_t start, size_
} }
OPL3_Generate(&fm,o); os[0]+=o[0]; os[1]+=o[1]; OPL3_Generate(&fm,o); os[0]+=o[0]; os[1]+=o[1];
for (int i=0; i<chans; i++) {
unsigned char ch=outChanMap[i];
if (ch==255) continue;
oscBuf[i]->data[oscBuf[i]->needle]=0;
if (fm.channel[i].out[0]!=NULL) {
oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[0];
}
if (fm.channel[i].out[1]!=NULL) {
oscBuf[i]->data[oscBuf[i]->needle]+=*fm.channel[ch].out[1];
}
oscBuf[i]->data[oscBuf[i]->needle]<<=1;
oscBuf[i]->needle++;
}
if (os[0]<-32768) os[0]=-32768; if (os[0]<-32768) os[0]=-32768;
if (os[0]>32767) os[0]=32767; if (os[0]>32767) os[0]=32767;
@ -917,6 +939,10 @@ void* DivPlatformOPL::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformOPL::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformOPL::getRegisterPool() { unsigned char* DivPlatformOPL::getRegisterPool() {
return regPool; return regPool;
} }
@ -1034,6 +1060,7 @@ void DivPlatformOPL::setOPLType(int type, bool drums) {
slotsDrums=slotsOPL2Drums; slotsDrums=slotsOPL2Drums;
slots=drums?slotsDrums:slotsNonDrums; slots=drums?slotsDrums:slotsNonDrums;
chanMap=drums?chanMapOPL2Drums:chanMapOPL2; chanMap=drums?chanMapOPL2Drums:chanMapOPL2;
outChanMap=outChanMapOPL2;
chipFreqBase=9440540*0.25; chipFreqBase=9440540*0.25;
chans=9; chans=9;
melodicChans=drums?6:9; melodicChans=drums?6:9;
@ -1044,6 +1071,7 @@ void DivPlatformOPL::setOPLType(int type, bool drums) {
slotsDrums=slotsOPL3Drums; slotsDrums=slotsOPL3Drums;
slots=drums?slotsDrums:slotsNonDrums; slots=drums?slotsDrums:slotsNonDrums;
chanMap=drums?chanMapOPL3Drums:chanMapOPL3; chanMap=drums?chanMapOPL3Drums:chanMapOPL3;
outChanMap=outChanMapOPL3;
chipFreqBase=9440540; chipFreqBase=9440540;
chans=18; chans=18;
melodicChans=drums?15:18; melodicChans=drums?15:18;
@ -1096,6 +1124,10 @@ void DivPlatformOPL::setFlags(unsigned int flags) {
rate=48000; rate=48000;
chipClock=rate*288; chipClock=rate*288;
} }
for (int i=0; i<18; i++) {
oscBuf[i]->rate=rate;
}
} }
int DivPlatformOPL::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { int DivPlatformOPL::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
@ -1105,6 +1137,9 @@ int DivPlatformOPL::init(DivEngine* p, int channels, int sugRate, unsigned int f
for (int i=0; i<20; i++) { for (int i=0; i<20; i++) {
isMuted[i]=false; isMuted[i]=false;
} }
for (int i=0; i<18; i++) {
oscBuf[i]=new DivDispatchOscBuffer;
}
setFlags(flags); setFlags(flags);
reset(); reset();
@ -1112,6 +1147,9 @@ int DivPlatformOPL::init(DivEngine* p, int channels, int sugRate, unsigned int f
} }
void DivPlatformOPL::quit() { void DivPlatformOPL::quit() {
for (int i=0; i<18; i++) {
delete oscBuf[i];
}
} }
DivPlatformOPL::~DivPlatformOPL() { DivPlatformOPL::~DivPlatformOPL() {

View File

@ -62,6 +62,7 @@ class DivPlatformOPL: public DivDispatch {
} }
}; };
Channel chan[20]; Channel chan[20];
DivDispatchOscBuffer* oscBuf[18];
bool isMuted[20]; bool isMuted[20];
struct QueuedWrite { struct QueuedWrite {
unsigned short addr; unsigned short addr;
@ -75,6 +76,7 @@ class DivPlatformOPL: public DivDispatch {
const unsigned char** slotsDrums; const unsigned char** slotsDrums;
const unsigned char** slots; const unsigned char** slots;
const unsigned short* chanMap; const unsigned short* chanMap;
const unsigned char* outChanMap;
double chipFreqBase; double chipFreqBase;
int delay, oplType, chans, melodicChans, totalChans; int delay, oplType, chans, melodicChans, totalChans;
unsigned char lastBusy; unsigned char lastBusy;
@ -104,6 +106,7 @@ class DivPlatformOPL: 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();

View File

@ -735,6 +735,7 @@ void* DivPlatformOPLL::getChanState(int ch) {
} }
DivDispatchOscBuffer* DivPlatformOPLL::getOscBuffer(int ch) { DivDispatchOscBuffer* DivPlatformOPLL::getOscBuffer(int ch) {
if (ch>=9) return NULL;
return oscBuf[ch]; return oscBuf[ch];
} }

View File

@ -116,6 +116,10 @@ void DivPlatformPCE::acquire(short* bufL, short* bufR, size_t start, size_t len)
pce->Update(24); pce->Update(24);
pce->ResetTS(0); pce->ResetTS(0);
for (int i=0; i<6; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=(pce->channel[i].blip_prev_samp[0]+pce->channel[i].blip_prev_samp[1])<<1;
}
tempL[0]=(tempL[0]>>1)+(tempL[0]>>2); tempL[0]=(tempL[0]>>1)+(tempL[0]>>2);
tempR[0]=(tempR[0]>>1)+(tempR[0]>>2); tempR[0]=(tempR[0]>>1)+(tempR[0]>>2);
@ -469,6 +473,10 @@ void* DivPlatformPCE::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformPCE::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformPCE::getRegisterPool() { unsigned char* DivPlatformPCE::getRegisterPool() {
return regPool; return regPool;
} }
@ -541,6 +549,9 @@ void DivPlatformPCE::setFlags(unsigned int flags) {
chipClock=COLOR_NTSC; chipClock=COLOR_NTSC;
} }
rate=chipClock/12; rate=chipClock/12;
for (int i=0; i<6; i++) {
oscBuf[i]->rate=rate;
}
} }
void DivPlatformPCE::poke(unsigned int addr, unsigned short val) { void DivPlatformPCE::poke(unsigned int addr, unsigned short val) {
@ -557,6 +568,7 @@ int DivPlatformPCE::init(DivEngine* p, int channels, int sugRate, unsigned int f
skipRegisterWrites=false; skipRegisterWrites=false;
for (int i=0; i<6; i++) { for (int i=0; i<6; i++) {
isMuted[i]=false; isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
} }
setFlags(flags); setFlags(flags);
pce=new PCE_PSG(tempL,tempR,PCE_PSG::REVISION_HUC6280A); pce=new PCE_PSG(tempL,tempR,PCE_PSG::REVISION_HUC6280A);
@ -565,6 +577,9 @@ int DivPlatformPCE::init(DivEngine* p, int channels, int sugRate, unsigned int f
} }
void DivPlatformPCE::quit() { void DivPlatformPCE::quit() {
for (int i=0; i<6; i++) {
delete oscBuf[i];
}
delete pce; delete pce;
} }

View File

@ -67,6 +67,7 @@ class DivPlatformPCE: public DivDispatch {
wave(-1) {} wave(-1) {}
}; };
Channel chan[6]; Channel chan[6];
DivDispatchOscBuffer* oscBuf[6];
bool isMuted[6]; bool isMuted[6];
struct QueuedWrite { struct QueuedWrite {
unsigned char addr; unsigned char addr;
@ -88,6 +89,7 @@ class DivPlatformPCE: 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();

View File

@ -50,6 +50,7 @@ const float cut=0.05;
const float reso=0.06; const float reso=0.06;
void DivPlatformPCSpeaker::acquire_unfilt(short* bufL, short* bufR, size_t start, size_t len) { void DivPlatformPCSpeaker::acquire_unfilt(short* bufL, short* bufR, size_t start, size_t len) {
int out=0;
for (size_t i=start; i<start+len; i++) { for (size_t i=start; i<start+len; i++) {
if (on) { if (on) {
pos-=PCSPKR_DIVIDER; pos-=PCSPKR_DIVIDER;
@ -61,9 +62,12 @@ void DivPlatformPCSpeaker::acquire_unfilt(short* bufL, short* bufR, size_t start
pos+=freq; pos+=freq;
} }
} }
bufL[i]=(pos>(freq>>1) && !isMuted[0])?32767:0; out=(pos>(freq>>1) && !isMuted[0])?32767:0;
bufL[i]=out;
oscBuf->data[oscBuf->needle++]=out;
} else { } else {
bufL[i]=0; bufL[i]=0;
oscBuf->data[oscBuf->needle++]=0;
} }
} }
} }
@ -87,8 +91,10 @@ void DivPlatformPCSpeaker::acquire_cone(short* bufL, short* bufR, size_t start,
if (out>1.0) out=1.0; if (out>1.0) out=1.0;
if (out<-1.0) out=-1.0; if (out<-1.0) out=-1.0;
bufL[i]=out*32767; bufL[i]=out*32767;
oscBuf->data[oscBuf->needle++]=out*32767;
} else { } else {
bufL[i]=0; bufL[i]=0;
oscBuf->data[oscBuf->needle++]=0;
} }
} }
} }
@ -112,8 +118,10 @@ void DivPlatformPCSpeaker::acquire_piezo(short* bufL, short* bufR, size_t start,
if (out>1.0) out=1.0; if (out>1.0) out=1.0;
if (out<-1.0) out=-1.0; if (out<-1.0) out=-1.0;
bufL[i]=out*32767; bufL[i]=out*32767;
oscBuf->data[oscBuf->needle++]=out*32767;
} else { } else {
bufL[i]=0; bufL[i]=0;
oscBuf->data[oscBuf->needle++]=0;
} }
} }
} }
@ -140,12 +148,28 @@ void DivPlatformPCSpeaker::beepFreq(int freq) {
} }
void DivPlatformPCSpeaker::acquire_real(short* bufL, short* bufR, size_t start, size_t len) { void DivPlatformPCSpeaker::acquire_real(short* bufL, short* bufR, size_t start, size_t len) {
int out=0;
if (lastOn!=on || lastFreq!=freq) { if (lastOn!=on || lastFreq!=freq) {
lastOn=on; lastOn=on;
lastFreq=freq; lastFreq=freq;
beepFreq((on && !isMuted[0])?freq:0); beepFreq((on && !isMuted[0])?freq:0);
} }
for (size_t i=start; i<start+len; i++) { for (size_t i=start; i<start+len; i++) {
if (on) {
pos-=PCSPKR_DIVIDER;
if (pos>freq) pos=freq;
while (pos<0) {
if (freq<1) {
pos=1;
} else {
pos+=freq;
}
}
out=(pos>(freq>>1) && !isMuted[0])?32767:0;
oscBuf->data[oscBuf->needle++]=out;
} else {
oscBuf->data[oscBuf->needle++]=0;
}
bufL[i]=0; bufL[i]=0;
} }
} }
@ -321,6 +345,10 @@ void* DivPlatformPCSpeaker::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformPCSpeaker::getOscBuffer(int ch) {
return oscBuf;
}
unsigned char* DivPlatformPCSpeaker::getRegisterPool() { unsigned char* DivPlatformPCSpeaker::getRegisterPool() {
if (on) { if (on) {
regPool[0]=freq; regPool[0]=freq;
@ -379,6 +407,7 @@ void DivPlatformPCSpeaker::setFlags(unsigned int flags) {
chipClock=COLOR_NTSC/3.0; chipClock=COLOR_NTSC/3.0;
rate=chipClock/PCSPKR_DIVIDER; rate=chipClock/PCSPKR_DIVIDER;
speakerType=flags&3; speakerType=flags&3;
oscBuf->rate=rate;
} }
void DivPlatformPCSpeaker::notifyInsDeletion(void* ins) { void DivPlatformPCSpeaker::notifyInsDeletion(void* ins) {
@ -407,6 +436,7 @@ int DivPlatformPCSpeaker::init(DivEngine* p, int channels, int sugRate, unsigned
for (int i=0; i<1; i++) { for (int i=0; i<1; i++) {
isMuted[i]=false; isMuted[i]=false;
} }
oscBuf=new DivDispatchOscBuffer;
setFlags(flags); setFlags(flags);
reset(); reset();
@ -420,6 +450,7 @@ void DivPlatformPCSpeaker::quit() {
#ifdef __linux__ #ifdef __linux__
if (beepFD>=0) close(beepFD); if (beepFD>=0) close(beepFD);
#endif #endif
delete oscBuf;
} }
DivPlatformPCSpeaker::~DivPlatformPCSpeaker() { DivPlatformPCSpeaker::~DivPlatformPCSpeaker() {

View File

@ -56,6 +56,7 @@ class DivPlatformPCSpeaker: public DivDispatch {
wave(-1) {} wave(-1) {}
}; };
Channel chan[1]; Channel chan[1];
DivDispatchOscBuffer* oscBuf;
bool isMuted[1]; bool isMuted[1];
bool on, flip, lastOn; bool on, flip, lastOn;
int pos, speakerType, beepFD; int pos, speakerType, beepFD;
@ -78,6 +79,7 @@ class DivPlatformPCSpeaker: 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();

View File

@ -64,12 +64,14 @@ void DivPlatformPET::acquire(short* bufL, short* bufR, size_t start, size_t len)
} }
bufL[h]=chan.out; bufL[h]=chan.out;
bufR[h]=chan.out; bufR[h]=chan.out;
oscBuf->data[oscBuf->needle++]=chan.out;
} }
} else { } else {
chan.out=0; chan.out=0;
for (size_t h=start; h<start+len; h++) { for (size_t h=start; h<start+len; h++) {
bufL[h]=0; bufL[h]=0;
bufR[h]=0; bufR[h]=0;
oscBuf->data[oscBuf->needle++]=0;
} }
} }
} }
@ -244,6 +246,10 @@ void* DivPlatformPET::getChanState(int ch) {
return &chan; return &chan;
} }
DivDispatchOscBuffer* DivPlatformPET::getOscBuffer(int ch) {
return oscBuf;
}
unsigned char* DivPlatformPET::getRegisterPool() { unsigned char* DivPlatformPET::getRegisterPool() {
return regPool; return regPool;
} }
@ -281,9 +287,15 @@ int DivPlatformPET::init(DivEngine* p, int channels, int sugRate, unsigned int f
chipClock=1000000; chipClock=1000000;
rate=chipClock/SAMP_DIVIDER; // = 250000kHz rate=chipClock/SAMP_DIVIDER; // = 250000kHz
isMuted=false; isMuted=false;
oscBuf=new DivDispatchOscBuffer;
oscBuf->rate=rate;
reset(); reset();
return 1; return 1;
} }
void DivPlatformPET::quit() {
delete oscBuf;
}
DivPlatformPET::~DivPlatformPET() { DivPlatformPET::~DivPlatformPET() {
} }

View File

@ -57,6 +57,7 @@ class DivPlatformPET: public DivDispatch {
out(0) {} out(0) {}
}; };
Channel chan; Channel chan;
DivDispatchOscBuffer* oscBuf;
bool isMuted; bool isMuted;
unsigned char regPool[16]; unsigned char regPool[16];
@ -65,6 +66,7 @@ class DivPlatformPET: 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();
@ -78,6 +80,7 @@ class DivPlatformPET: public DivDispatch {
const char** getRegisterSheet(); const char** getRegisterSheet();
const char* getEffectName(unsigned char effect); const char* getEffectName(unsigned char effect);
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
void quit();
~DivPlatformPET(); ~DivPlatformPET();
private: private:
void writeOutVol(); void writeOutVol();

View File

@ -274,6 +274,13 @@ void DivPlatformQSound::acquire(short* bufL, short* bufR, size_t start, size_t l
qsound_update(&chip); qsound_update(&chip);
bufL[h]=chip.out[0]; bufL[h]=chip.out[0];
bufR[h]=chip.out[1]; bufR[h]=chip.out[1];
for (int i=0; i<19; i++) {
int data=chip.voice_output[i]<<2;
if (data<-32768) data=-32768;
if (data>32767) data=32767;
oscBuf[i]->data[oscBuf[i]->needle++]=data;
}
} }
} }
@ -546,6 +553,10 @@ void* DivPlatformQSound::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformQSound::getOscBuffer(int ch) {
return oscBuf[ch];
}
void DivPlatformQSound::reset() { void DivPlatformQSound::reset() {
for (int i=0; i<16; i++) { for (int i=0; i<16; i++) {
chan[i]=DivPlatformQSound::Channel(); chan[i]=DivPlatformQSound::Channel();
@ -632,9 +643,10 @@ int DivPlatformQSound::init(DivEngine* p, int channels, int sugRate, unsigned in
dumpWrites=false; dumpWrites=false;
skipRegisterWrites=false; skipRegisterWrites=false;
//for (int i=0; i<16; i++) { for (int i=0; i<19; i++) {
// isMuted[i]=false; oscBuf[i]=new DivDispatchOscBuffer;
//} //isMuted[i]=false;
}
setFlags(flags); setFlags(flags);
chipClock=60000000; chipClock=60000000;
@ -642,8 +654,15 @@ int DivPlatformQSound::init(DivEngine* p, int channels, int sugRate, unsigned in
chip.rom_data = (unsigned char*)&chip.rom_mask; chip.rom_data = (unsigned char*)&chip.rom_mask;
chip.rom_mask = 0; chip.rom_mask = 0;
reset(); reset();
for (int i=0; i<19; i++) {
oscBuf[i]->rate=rate;
}
return 19; return 19;
} }
void DivPlatformQSound::quit() { void DivPlatformQSound::quit() {
for (int i=0; i<19; i++) {
delete oscBuf[i];
}
} }

View File

@ -63,6 +63,7 @@ class DivPlatformQSound: public DivDispatch {
outVol(255) {} outVol(255) {}
}; };
Channel chan[19]; Channel chan[19];
DivDispatchOscBuffer* oscBuf[19];
int echoDelay; int echoDelay;
int echoFeedback; int echoFeedback;
@ -75,6 +76,7 @@ class DivPlatformQSound: 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();

View File

@ -86,7 +86,7 @@ void DivPlatformSAA1099::acquire_mame(short* bufL, short* bufR, size_t start, si
regPool[w.addr&0x1f]=w.val; regPool[w.addr&0x1f]=w.val;
writes.pop(); writes.pop();
} }
saa.sound_stream_update(saaBuf,len); saa.sound_stream_update(saaBuf,len,oscBuf);
for (size_t i=0; i<len; i++) { for (size_t i=0; i<len; i++) {
bufL[i+start]=saaBuf[0][i]; bufL[i+start]=saaBuf[0][i];
bufR[i+start]=saaBuf[1][i]; bufR[i+start]=saaBuf[1][i];
@ -107,7 +107,7 @@ void DivPlatformSAA1099::acquire_saaSound(short* bufL, short* bufR, size_t start
regPool[w.addr&0x1f]=w.val; regPool[w.addr&0x1f]=w.val;
writes.pop(); writes.pop();
} }
saa_saaSound->GenerateMany((unsigned char*)saaBuf[0],len); saa_saaSound->GenerateMany((unsigned char*)saaBuf[0],len,oscBuf);
for (size_t i=0; i<len; i++) { for (size_t i=0; i<len; i++) {
bufL[i+start]=saaBuf[0][i<<1]; bufL[i+start]=saaBuf[0][i<<1];
bufR[i+start]=saaBuf[0][1+(i<<1)]; bufR[i+start]=saaBuf[0][1+(i<<1)];
@ -398,6 +398,10 @@ void* DivPlatformSAA1099::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformSAA1099::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformSAA1099::getRegisterPool() { unsigned char* DivPlatformSAA1099::getRegisterPool() {
return regPool; return regPool;
} }
@ -485,6 +489,10 @@ void DivPlatformSAA1099::setFlags(unsigned int flags) {
} }
rate=chipClock/32; rate=chipClock/32;
for (int i=0; i<6; i++) {
oscBuf[i]->rate=rate;
}
switch (core) { switch (core) {
case DIV_SAA_CORE_MAME: case DIV_SAA_CORE_MAME:
break; break;
@ -516,6 +524,7 @@ int DivPlatformSAA1099::init(DivEngine* p, int channels, int sugRate, unsigned i
saa_saaSound=NULL; saa_saaSound=NULL;
for (int i=0; i<6; i++) { for (int i=0; i<6; i++) {
isMuted[i]=false; isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
} }
if (core==DIV_SAA_CORE_SAASOUND) { if (core==DIV_SAA_CORE_SAASOUND) {
saa_saaSound=CreateCSAASound(); saa_saaSound=CreateCSAASound();
@ -530,6 +539,9 @@ int DivPlatformSAA1099::init(DivEngine* p, int channels, int sugRate, unsigned i
} }
void DivPlatformSAA1099::quit() { void DivPlatformSAA1099::quit() {
for (int i=0; i<6; i++) {
delete oscBuf[i];
}
if (saa_saaSound!=NULL) { if (saa_saaSound!=NULL) {
DestroyCSAASound(saa_saaSound); DestroyCSAASound(saa_saaSound);
saa_saaSound=NULL; saa_saaSound=NULL;

View File

@ -49,6 +49,7 @@ class DivPlatformSAA1099: public DivDispatch {
Channel(): freqH(0), freqL(0), freq(0), baseFreq(0), pitch(0), pitch2(0), note(0), ins(-1), psgMode(1), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), portaPause(false), inPorta(false), vol(0), outVol(15), pan(255) {} Channel(): freqH(0), freqL(0), freq(0), baseFreq(0), pitch(0), pitch2(0), note(0), ins(-1), psgMode(1), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), portaPause(false), inPorta(false), vol(0), outVol(15), pan(255) {}
}; };
Channel chan[6]; Channel chan[6];
DivDispatchOscBuffer* oscBuf[6];
bool isMuted[6]; bool isMuted[6];
struct QueuedWrite { struct QueuedWrite {
unsigned short addr; unsigned short addr;
@ -90,6 +91,7 @@ class DivPlatformSAA1099: 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();

View File

@ -42,7 +42,16 @@ const char* DivPlatformSMS::getEffectName(unsigned char effect) {
} }
void DivPlatformSMS::acquire(short* bufL, short* bufR, size_t start, size_t len) { void DivPlatformSMS::acquire(short* bufL, short* bufR, size_t start, size_t len) {
sn->sound_stream_update(bufL+start,len); for (size_t h=start; h<start+len; h++) {
sn->sound_stream_update(bufL+h,1);
for (int i=0; i<4; i++) {
if (isMuted[i]) {
oscBuf[i]->data[oscBuf[i]->needle++]=0;
} else {
oscBuf[i]->data[oscBuf[i]->needle++]=sn->get_channel_output(i);
}
}
}
} }
int DivPlatformSMS::acquireOne() { int DivPlatformSMS::acquireOne() {
@ -287,6 +296,10 @@ void* DivPlatformSMS::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformSMS::getOscBuffer(int ch) {
return oscBuf[ch];
}
void DivPlatformSMS::reset() { void DivPlatformSMS::reset() {
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
chan[i]=DivPlatformSMS::Channel(); chan[i]=DivPlatformSMS::Channel();
@ -359,6 +372,9 @@ void DivPlatformSMS::setFlags(unsigned int flags) {
break; break;
} }
rate=chipClock/16; rate=chipClock/16;
for (int i=0; i<4; i++) {
oscBuf[i]->rate=rate;
}
} }
int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
@ -369,6 +385,7 @@ int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate, unsigned int f
oldValue=0xff; oldValue=0xff;
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
isMuted[i]=false; isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
} }
sn=NULL; sn=NULL;
setFlags(flags); setFlags(flags);
@ -377,6 +394,9 @@ int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate, unsigned int f
} }
void DivPlatformSMS::quit() { void DivPlatformSMS::quit() {
for (int i=0; i<4; i++) {
delete oscBuf[i];
}
if (sn!=NULL) delete sn; if (sn!=NULL) delete sn;
} }

View File

@ -52,6 +52,7 @@ class DivPlatformSMS: public DivDispatch {
outVol(15) {} outVol(15) {}
}; };
Channel chan[4]; Channel chan[4];
DivDispatchOscBuffer* oscBuf[4];
bool isMuted[4]; bool isMuted[4];
unsigned char oldValue; unsigned char oldValue;
unsigned char snNoiseMode; unsigned char snNoiseMode;
@ -65,6 +66,7 @@ class DivPlatformSMS: 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);
void reset(); void reset();
void forceIns(); void forceIns();
void tick(bool sysTick=true); void tick(bool sysTick=true);

View File

@ -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());

View File

@ -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);

View File

@ -458,23 +458,31 @@ public:
return mAudioChannels[timer].fireAction( tick ); return mAudioChannels[timer].fireAction( tick );
} }
AudioSample sampleAudio() const AudioSample sampleAudio( DivDispatchOscBuffer** oscb ) const
{ {
int left{}; int left{};
int right{}; int right{};
for ( size_t i = 0; i < 4; ++i ) for ( size_t i = 0; i < 4; ++i )
{ {
int oscbWrite = 0;
if ( ( mStereo & ( (uint8_t)0x01 << i ) ) == 0 ) if ( ( mStereo & ( (uint8_t)0x01 << i ) ) == 0 )
{ {
const int attenuation = ( mPan & ( (uint8_t)0x01 << i ) ) != 0 ? mAttenuationLeft[i] : 0x3c; const int attenuation = ( mPan & ( (uint8_t)0x01 << i ) ) != 0 ? mAttenuationLeft[i] : 0x3c;
left += mAudioChannels[i].getOutput() * attenuation; left += mAudioChannels[i].getOutput() * attenuation;
oscbWrite += mAudioChannels[i].getOutput() * attenuation;
} }
if ( ( mStereo & ( (uint8_t)0x10 << i ) ) == 0 ) if ( ( mStereo & ( (uint8_t)0x10 << i ) ) == 0 )
{ {
const int attenuation = ( mPan & ( (uint8_t)0x01 << i ) ) != 0 ? mAttenuationRight[i] : 0x3c; const int attenuation = ( mPan & ( (uint8_t)0x01 << i ) ) != 0 ? mAttenuationRight[i] : 0x3c;
right += mAudioChannels[i].getOutput() * attenuation; right += mAudioChannels[i].getOutput() * attenuation;
oscbWrite += mAudioChannels[i].getOutput() * attenuation;
}
if (oscb!=NULL) {
oscb[i]->data[oscb[i]->needle++]=oscbWrite;
} }
} }
@ -534,7 +542,7 @@ void Mikey::enqueueSampling()
mQueue->push( ( mNextTick & ~15 ) | 4 ); mQueue->push( ( mNextTick & ~15 ) | 4 );
} }
void Mikey::sampleAudio( int16_t* bufL, int16_t* bufR, size_t size ) void Mikey::sampleAudio( int16_t* bufL, int16_t* bufR, size_t size, DivDispatchOscBuffer** oscb )
{ {
size_t i = 0; size_t i = 0;
while ( i < size ) while ( i < size )
@ -549,7 +557,7 @@ void Mikey::sampleAudio( int16_t* bufL, int16_t* bufR, size_t size )
} }
else else
{ {
auto sample = mMikey->sampleAudio(); auto sample = mMikey->sampleAudio( oscb );
bufL[i] = sample.left; bufL[i] = sample.left;
bufR[i] = sample.right; bufR[i] = sample.right;
i += 1; i += 1;

View File

@ -3,6 +3,9 @@
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
// can you forgive me
#include "../../../dispatch.h"
namespace Lynx namespace Lynx
{ {
@ -18,7 +21,7 @@ public:
~Mikey(); ~Mikey();
void write( uint8_t address, uint8_t value ); void write( uint8_t address, uint8_t value );
void sampleAudio( int16_t* bufL, int16_t* bufR, size_t size ); void sampleAudio( int16_t* bufL, int16_t* bufR, size_t size, DivDispatchOscBuffer** oscb = NULL );
uint8_t const* getRegisterPool(); uint8_t const* getRegisterPool();

View File

@ -98,6 +98,8 @@ void n163_core::tick()
m_ram[m_voice_cycle + 3] = bitfield(accum, 8, 8); m_ram[m_voice_cycle + 3] = bitfield(accum, 8, 8);
m_ram[m_voice_cycle + 5] = bitfield(accum, 16, 8); m_ram[m_voice_cycle + 5] = bitfield(accum, 16, 8);
const u8 prev_voice_cycle = m_voice_cycle;
// update voice cycle // update voice cycle
bool flush = m_multiplex ? true : false; bool flush = m_multiplex ? true : false;
m_voice_cycle -= 0x8; m_voice_cycle -= 0x8;
@ -109,7 +111,9 @@ void n163_core::tick()
} }
// output 4 bit waveform and volume, multiplexed // output 4 bit waveform and volume, multiplexed
m_acc += wave * volume; const u8 chan_index = ((0x78-prev_voice_cycle)>>3)&7;
m_ch_out[chan_index]=wave * volume;
m_acc += m_ch_out[chan_index];
if (flush) if (flush)
{ {
m_out = m_acc / (m_multiplex ? 1 : (bitfield(m_ram[0x7f], 4, 3) + 1)); m_out = m_acc / (m_multiplex ? 1 : (bitfield(m_ram[0x7f], 4, 3) + 1));
@ -127,6 +131,7 @@ void n163_core::reset()
m_addr_latch.reset(); m_addr_latch.reset();
m_out = 0; m_out = 0;
m_acc = 0; m_acc = 0;
std::fill(std::begin(m_ch_out), std::end(m_ch_out), 0);
} }
// accessor // accessor

View File

@ -46,6 +46,12 @@ public:
// sound output pin // sound output pin
s16 out() { return m_out; } s16 out() { return m_out; }
// get channel output
s16 chan_out(u8 ch) { return m_ch_out[ch]; }
// get voice cycle
u8 voice_cycle() { return m_voice_cycle; }
// register pool // register pool
u8 reg(u8 addr) { return m_ram[addr & 0x7f]; } u8 reg(u8 addr) { return m_ram[addr & 0x7f]; }
void set_multiplex(bool multiplex = true) { m_multiplex = multiplex; } void set_multiplex(bool multiplex = true) { m_multiplex = multiplex; }
@ -74,6 +80,7 @@ private:
u8 m_voice_cycle = 0x78; // Voice cycle for processing u8 m_voice_cycle = 0x78; // Voice cycle for processing
addr_latch_t m_addr_latch; // address latch addr_latch_t m_addr_latch; // address latch
s16 m_out = 0; // output s16 m_out = 0; // output
s16 m_ch_out[8] = {0}; // per channel output
// demultiplex related // demultiplex related
bool m_multiplex = true; // multiplex flag, but less noisy = inaccurate! bool m_multiplex = true; // multiplex flag, but less noisy = inaccurate!
s16 m_acc = 0; // accumulated output s16 m_acc = 0; // accumulated output

View File

@ -96,10 +96,11 @@ inline void PCE_PSG::UpdateOutputSub(const int32_t timestamp, psg_channel *ch, c
HRBufs[1][l + 4] += delta[1] * c[4]; HRBufs[1][l + 4] += delta[1] * c[4];
HRBufs[1][l + 5] += delta[1] * c[5]; HRBufs[1][l + 5] += delta[1] * c[5];
HRBufs[1][l + 6] += delta[1] * c[6]; HRBufs[1][l + 6] += delta[1] * c[6];
*/
ch->blip_prev_samp[0] = samp0; ch->blip_prev_samp[0] = samp0;
ch->blip_prev_samp[1] = samp1; ch->blip_prev_samp[1] = samp1;
*/
} }
void PCE_PSG::UpdateOutput_Norm(const int32_t timestamp, psg_channel *ch) void PCE_PSG::UpdateOutput_Norm(const int32_t timestamp, psg_channel *ch)

View File

@ -147,6 +147,8 @@ class PCE_PSG
void PeekWave(const unsigned int ch, uint32_t Address, uint32_t Length, uint8_t *Buffer); void PeekWave(const unsigned int ch, uint32_t Address, uint32_t Length, uint8_t *Buffer);
void PokeWave(const unsigned int ch, uint32_t Address, uint32_t Length, const uint8_t *Buffer); void PokeWave(const unsigned int ch, uint32_t Address, uint32_t Length, const uint8_t *Buffer);
psg_channel channel[6];
private: private:
@ -178,8 +180,6 @@ class PCE_PSG
int32_t vol_update_vllatch; int32_t vol_update_vllatch;
bool vol_pending; bool vol_pending;
psg_channel channel[6];
int32_t lastts; int32_t lastts;
int revision; int revision;

View File

@ -164,7 +164,7 @@ void saa1099_device::device_start()
// sound_stream_update - handle a stream update // sound_stream_update - handle a stream update
//------------------------------------------------- //-------------------------------------------------
void saa1099_device::sound_stream_update(short** outputs, int len) void saa1099_device::sound_stream_update(short** outputs, int len, DivDispatchOscBuffer** oscBuf)
{ {
int j, ch; int j, ch;
/* if the channels are disabled we're done */ /* if the channels are disabled we're done */
@ -225,9 +225,14 @@ void saa1099_device::sound_stream_update(short** outputs, int len)
} }
if (level) if (level)
{ {
output_l += m_channels[ch].amplitude[ LEFT] * m_channels[ch].envelope[ LEFT] / 16; int this_output_l = m_channels[ch].amplitude[ LEFT] * m_channels[ch].envelope[ LEFT] / 16;
output_r += m_channels[ch].amplitude[RIGHT] * m_channels[ch].envelope[RIGHT] / 16; int this_output_r = m_channels[ch].amplitude[RIGHT] * m_channels[ch].envelope[RIGHT] / 16;
} output_l+=this_output_l;
output_r+=this_output_r;
oscBuf[ch]->data[oscBuf[ch]->needle++]=(this_output_l+this_output_r)<<1;
} else if (oscBuf!=NULL) {
oscBuf[ch]->data[oscBuf[ch]->needle++]=0;
}
} }
for (ch = 0; ch < 2; ch++) for (ch = 0; ch < 2; ch++)

View File

@ -7,6 +7,8 @@
#ifndef MAME_SOUND_SAA1099_H #ifndef MAME_SOUND_SAA1099_H
#define MAME_SOUND_SAA1099_H #define MAME_SOUND_SAA1099_H
#include "../../dispatch.h"
//************************************************************************** //**************************************************************************
// TYPE DEFINITIONS // TYPE DEFINITIONS
//************************************************************************** //**************************************************************************
@ -28,7 +30,7 @@ public:
void device_clock_changed(); void device_clock_changed();
// sound stream update overrides // sound stream update overrides
void sound_stream_update(short** outputs, int len); void sound_stream_update(short** outputs, int len, DivDispatchOscBuffer** oscBuf=NULL);
private: private:
struct saa1099_channel struct saa1099_channel

View File

@ -16,6 +16,9 @@ public:
void write(u8 data); void write(u8 data);
void device_start(); void device_start();
void sound_stream_update(short* outputs, int outLen); void sound_stream_update(short* outputs, int outLen);
inline int32_t get_channel_output(int ch) {
return ((m_output[ch]!=0)?m_volume[ch]:0);
}
//DECLARE_READ_LINE_MEMBER( ready_r ) { return m_ready_state ? 1 : 0; } //DECLARE_READ_LINE_MEMBER( ready_r ) { return m_ready_state ? 1 : 0; }
sn76496_base_device( sn76496_base_device(

View File

@ -88,6 +88,12 @@ class SoundUnit {
bool muted[8]; bool muted[8];
void Write(unsigned char addr, unsigned char data); void Write(unsigned char addr, unsigned char data);
void NextSample(short* l, short* r); void NextSample(short* l, short* r);
inline int GetSample(int ch) {
int ret=(nsL[ch]+nsR[ch])>>1;
if (ret<-32768) ret=-32768;
if (ret>32767) ret=32767;
return ret;
}
void Init(); void Init();
void Reset(); void Reset();
SoundUnit(); SoundUnit();

View File

@ -41,6 +41,8 @@ public:
void SoundUpdate(uint32_t); void SoundUpdate(uint32_t);
void RAMWrite(uint32_t, uint8_t); void RAMWrite(uint32_t, uint8_t);
int32_t sample_cache[4][2];
private: private:
// Blip_Synth<blip_good_quality, 4096> WaveSynth; // Blip_Synth<blip_good_quality, 4096> WaveSynth;
@ -61,8 +63,6 @@ private:
uint8_t sweep_counter; uint8_t sweep_counter;
uint8_t SampleRAMPos; uint8_t SampleRAMPos;
int32_t sample_cache[4][2];
int32_t last_v_val; int32_t last_v_val;
uint8_t HyperVoice; uint8_t HyperVoice;

View File

@ -157,7 +157,7 @@ void TIASound::volume(unsigned int percent)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASound::process(short* buffer, unsigned int samples) void TIASound::process(short* buffer, unsigned int samples, DivDispatchOscBuffer** oscBuf)
{ {
// Make temporary local copy // Make temporary local copy
unsigned char audc0 = myAUDC[0], audc1 = myAUDC[1]; unsigned char audc0 = myAUDC[0], audc1 = myAUDC[1];
@ -339,6 +339,11 @@ void TIASound::process(short* buffer, unsigned int samples)
samples--; samples--;
break; break;
} }
if (oscBuf!=NULL) {
oscBuf[0]->data[oscBuf[0]->needle++]=v0;
oscBuf[1]->data[oscBuf[1]->needle++]=v1;
}
} }
// Save for next round // Save for next round

View File

@ -21,6 +21,7 @@
#define TIASOUND_HXX #define TIASOUND_HXX
#include <string> #include <string>
#include "../../../dispatch.h"
/** /**
This class implements a fairly accurate emulation of the TIA sound This class implements a fairly accurate emulation of the TIA sound
@ -87,7 +88,7 @@ class TIASound
@param buffer The location to store generated samples @param buffer The location to store generated samples
@param samples The number of samples to generate @param samples The number of samples to generate
*/ */
void process(short* buffer, unsigned int samples); void process(short* buffer, unsigned int samples, DivDispatchOscBuffer** oscBuf=NULL);
/** /**
Set the volume of the samples created (0-100) Set the volume of the samples created (0-100)

View File

@ -86,6 +86,12 @@ render(struct VERA_PSG* psg, int16_t *left, int16_t *right)
if (ch->right) { if (ch->right) {
r += val; r += val;
} }
if (ch->left || ch->right) {
ch->lastOut=val;
} else {
ch->lastOut=0;
}
} }
*left = l; *left = l;

View File

@ -15,6 +15,7 @@ struct VERAChannel {
uint8_t waveform; uint8_t waveform;
unsigned phase; unsigned phase;
int lastOut;
uint8_t noiseval; uint8_t noiseval;
}; };

View File

@ -88,13 +88,23 @@ void vrcvi_core::tick()
if (!m_control.m_halt) // Halt flag if (!m_control.m_halt) // Halt flag
{ {
// tick per each clock // tick per each clock
int elemIndex=0;
for (auto & elem : m_pulse) for (auto & elem : m_pulse)
{ {
if (elem.tick()) if (elem.tick()) {
m_out += elem.m_control.m_volume; // add 4 bit pulse output m_out += elem.m_control.m_volume; // add 4 bit pulse output
m_ch_out[elemIndex]=elem.m_control.m_volume;
} else {
m_ch_out[elemIndex]=0;
}
elemIndex++;
} }
if (m_sawtooth.tick()) if (m_sawtooth.tick()) {
m_out += bitfield(m_sawtooth.m_accum, 3, 5); // add 5 bit sawtooth output m_out += bitfield(m_sawtooth.m_accum, 3, 5); // add 5 bit sawtooth output
m_ch_out[2]=bitfield(m_sawtooth.m_accum, 3, 5);
} else {
m_ch_out[2]=0;
}
} }
if (m_timer.tick()) if (m_timer.tick())
m_timer.counter_tick(); m_timer.counter_tick();
@ -109,6 +119,7 @@ void vrcvi_core::reset()
m_timer.reset(); m_timer.reset();
m_control.reset(); m_control.reset();
m_out = 0; m_out = 0;
std::fill(std::begin(m_ch_out),std::end(m_ch_out),0);
} }
bool vrcvi_core::alu_t::tick() bool vrcvi_core::alu_t::tick()

View File

@ -62,6 +62,8 @@ public:
// 6 bit output // 6 bit output
s8 out() { return m_out; } s8 out() { return m_out; }
// channel output
s16 chan_out(u8 ch) { return m_ch_out[ch]; }
private: private:
// Common ALU for sound channels // Common ALU for sound channels
struct alu_t struct alu_t
@ -233,6 +235,7 @@ private:
vrcvi_intf &m_intf; vrcvi_intf &m_intf;
s8 m_out = 0; // 6 bit output s8 m_out = 0; // 6 bit output
s8 m_ch_out[3] = {0}; // per-channel output
}; };
#endif #endif

View File

@ -63,6 +63,7 @@ public:
// getters // getters
s32 output(u8 channel) { return m_out[channel & 1]; } s32 output(u8 channel) { return m_out[channel & 1]; }
s32 chan_out(u8 channel) { return (m_voice[channel].data * (m_voice[channel].vol_out[0]+m_voice[channel].vol_out[1]))<<2; }
// internal state // internal state
void reset(); void reset();

View File

@ -245,6 +245,8 @@ void adpcm_a_channel::output(ymfm_output<NumOutputs> &output) const
output.data[1] += value; output.data[1] += value;
} }
template void adpcm_a_channel::output<1>(ymfm_output<1> &output) const;
template void adpcm_a_channel::output<2>(ymfm_output<2> &output) const;
//********************************************************* //*********************************************************

View File

@ -203,6 +203,9 @@ public:
// return a reference to our registers // return a reference to our registers
adpcm_a_registers &regs() { return m_regs; } adpcm_a_registers &regs() { return m_regs; }
// debug functions
adpcm_a_channel* debug_channel(uint32_t index) const { return m_channel[index].get(); }
private: private:
// internal state // internal state
ymfm_interface &m_intf; // reference to the interface ymfm_interface &m_intf; // reference to the interface

View File

@ -301,6 +301,7 @@ public:
// simple getters for debugging // simple getters for debugging
fm_operator<RegisterType> *debug_operator(uint32_t index) const { return m_op[index]; } fm_operator<RegisterType> *debug_operator(uint32_t index) const { return m_op[index]; }
int32_t debug_output(uint32_t index) const { return m_output[index]; }
private: private:
// helper to add values to the outputs based on channel enables // helper to add values to the outputs based on channel enables
@ -313,14 +314,22 @@ private:
constexpr int out2_index = 2 % RegisterType::OUTPUTS; constexpr int out2_index = 2 % RegisterType::OUTPUTS;
constexpr int out3_index = 3 % RegisterType::OUTPUTS; constexpr int out3_index = 3 % RegisterType::OUTPUTS;
if (RegisterType::OUTPUTS == 1 || m_regs.ch_output_0(choffs)) if (RegisterType::OUTPUTS == 1 || m_regs.ch_output_0(choffs)) {
m_output[out0_index]=value;
output.data[out0_index] += value; output.data[out0_index] += value;
if (RegisterType::OUTPUTS >= 2 && m_regs.ch_output_1(choffs)) }
if (RegisterType::OUTPUTS >= 2 && m_regs.ch_output_1(choffs)) {
m_output[out1_index]=value;
output.data[out1_index] += value; output.data[out1_index] += value;
if (RegisterType::OUTPUTS >= 3 && m_regs.ch_output_2(choffs)) }
if (RegisterType::OUTPUTS >= 3 && m_regs.ch_output_2(choffs)) {
m_output[out2_index]=value;
output.data[out2_index] += value; output.data[out2_index] += value;
if (RegisterType::OUTPUTS >= 4 && m_regs.ch_output_3(choffs)) }
if (RegisterType::OUTPUTS >= 4 && m_regs.ch_output_3(choffs)) {
m_output[out3_index]=value;
output.data[out3_index] += value; output.data[out3_index] += value;
}
} }
// internal state // internal state
@ -330,6 +339,7 @@ private:
fm_operator<RegisterType> *m_op[4]; // up to 4 operators fm_operator<RegisterType> *m_op[4]; // up to 4 operators
RegisterType &m_regs; // direct reference to registers RegisterType &m_regs; // direct reference to registers
fm_engine_base<RegisterType> &m_owner; // reference to the owning engine fm_engine_base<RegisterType> &m_owner; // reference to the owning engine
mutable int32_t m_output[4];
}; };

View File

@ -808,7 +808,8 @@ fm_channel<RegisterType>::fm_channel(fm_engine_base<RegisterType> &owner, uint32
m_feedback_in(0), m_feedback_in(0),
m_op{ nullptr, nullptr, nullptr, nullptr }, m_op{ nullptr, nullptr, nullptr, nullptr },
m_regs(owner.regs()), m_regs(owner.regs()),
m_owner(owner) m_owner(owner),
m_output{ 0, 0, 0, 0 }
{ {
} }
@ -823,6 +824,11 @@ void fm_channel<RegisterType>::reset()
// reset our data // reset our data
m_feedback[0] = m_feedback[1] = 0; m_feedback[0] = m_feedback[1] = 0;
m_feedback_in = 0; m_feedback_in = 0;
m_output[0] = 0;
m_output[1] = 0;
m_output[2] = 0;
m_output[3] = 0;
} }

View File

@ -281,6 +281,9 @@ public:
// generate one sample of sound // generate one sample of sound
void generate(output_data *output, uint32_t numsamples = 1); void generate(output_data *output, uint32_t numsamples = 1);
// get the engine
fm_engine* debug_engine() { return &m_fm; }
protected: protected:
// variants // variants
enum opm_variant enum opm_variant

View File

@ -697,6 +697,12 @@ public:
// generate one sample of sound // generate one sample of sound
void generate(output_data *output, uint32_t numsamples = 1); void generate(output_data *output, uint32_t numsamples = 1);
// get the engine
fm_engine* debug_fm_engine() { return &m_fm; }
ssg_engine* debug_ssg_engine() { return &m_ssg; }
adpcm_a_engine* debug_adpcm_a_engine() { return &m_adpcm_a; }
adpcm_b_engine* debug_adpcm_b_engine() { return &m_adpcm_b; }
protected: protected:
// internal helpers // internal helpers
void update_prescale(); void update_prescale();
@ -761,6 +767,9 @@ public:
// generate one sample of sound // generate one sample of sound
void generate(output_data *output, uint32_t numsamples = 1); void generate(output_data *output, uint32_t numsamples = 1);
// get the engine
fm_engine* debug_engine() { return &m_fm; }
protected: protected:
// simulate the DAC discontinuity // simulate the DAC discontinuity
constexpr int32_t dac_discontinuity(int32_t value) const { return (value < 0) ? (value - 2) : (value + 3); } constexpr int32_t dac_discontinuity(int32_t value) const { return (value < 0) ? (value - 2) : (value + 3); }

View File

@ -232,6 +232,8 @@ void ssg_engine::output(output_data &output)
// convert to amplitude // convert to amplitude
output.data[chan] = s_amplitudes[volume]; output.data[chan] = s_amplitudes[volume];
} }
m_last_out=output;
} }

View File

@ -187,6 +187,9 @@ public:
// indicate the prescale has changed // indicate the prescale has changed
void prescale_changed() { if (m_override != nullptr) m_override->ssg_prescale_changed(); } void prescale_changed() { if (m_override != nullptr) m_override->ssg_prescale_changed(); }
// get the last output
void get_last_out(output_data& out) { out=m_last_out; }
private: private:
// internal state // internal state
ymfm_interface &m_intf; // reference to the interface ymfm_interface &m_intf; // reference to the interface
@ -198,6 +201,7 @@ private:
uint32_t m_noise_state; // current noise state uint32_t m_noise_state; // current noise state
ssg_registers m_regs; // registers ssg_registers m_regs; // registers
ssg_override *m_override; // override interface ssg_override *m_override; // override interface
output_data m_last_out;
}; };
} }

View File

@ -99,6 +99,9 @@ void DivPlatformSoundUnit::acquire(short* bufL, short* bufR, size_t start, size_
writes.pop(); writes.pop();
} }
su->NextSample(&bufL[h],&bufR[h]); su->NextSample(&bufL[h],&bufR[h]);
for (int i=0; i<8; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=su->GetSample(i);
}
} }
} }
@ -313,6 +316,10 @@ void* DivPlatformSoundUnit::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformSoundUnit::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformSoundUnit::getRegisterPool() { unsigned char* DivPlatformSoundUnit::getRegisterPool() {
return (unsigned char*)su->chan; return (unsigned char*)su->chan;
} }
@ -365,6 +372,9 @@ void DivPlatformSoundUnit::setFlags(unsigned int flags) {
chipClock=1236000; chipClock=1236000;
} }
rate=chipClock/4; rate=chipClock/4;
for (int i=0; i<8; i++) {
oscBuf[i]->rate=rate;
}
} }
void DivPlatformSoundUnit::poke(unsigned int addr, unsigned short val) { void DivPlatformSoundUnit::poke(unsigned int addr, unsigned short val) {
@ -381,6 +391,7 @@ int DivPlatformSoundUnit::init(DivEngine* p, int channels, int sugRate, unsigned
skipRegisterWrites=false; skipRegisterWrites=false;
for (int i=0; i<8; i++) { for (int i=0; i<8; i++) {
isMuted[i]=false; isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
} }
setFlags(flags); setFlags(flags);
su=new SoundUnit(); su=new SoundUnit();
@ -390,6 +401,9 @@ int DivPlatformSoundUnit::init(DivEngine* p, int channels, int sugRate, unsigned
} }
void DivPlatformSoundUnit::quit() { void DivPlatformSoundUnit::quit() {
for (int i=0; i<8; i++) {
delete oscBuf[i];
}
delete su; delete su;
} }

View File

@ -71,6 +71,7 @@ class DivPlatformSoundUnit: public DivDispatch {
wave(0) {} wave(0) {}
}; };
Channel chan[8]; Channel chan[8];
DivDispatchOscBuffer* oscBuf[8];
bool isMuted[8]; bool isMuted[8];
struct QueuedWrite { struct QueuedWrite {
unsigned char addr; unsigned char addr;
@ -94,6 +95,7 @@ class DivPlatformSoundUnit: 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();

View File

@ -107,6 +107,9 @@ void DivPlatformSwan::acquire(short* bufL, short* bufR, size_t start, size_t len
ws->SoundFlush(samp, 1); ws->SoundFlush(samp, 1);
bufL[h]=samp[0]; bufL[h]=samp[0];
bufR[h]=samp[1]; bufR[h]=samp[1];
for (int i=0; i<4; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=(ws->sample_cache[i][0]+ws->sample_cache[i][1])<<6;
}
} }
} }
@ -457,6 +460,10 @@ void* DivPlatformSwan::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformSwan::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformSwan::getRegisterPool() { unsigned char* DivPlatformSwan::getRegisterPool() {
// get Random from emulator // get Random from emulator
regPool[0x12]=ws->SoundRead(0x92); regPool[0x12]=ws->SoundRead(0x92);
@ -532,6 +539,8 @@ int DivPlatformSwan::init(DivEngine* p, int channels, int sugRate, unsigned int
rate=chipClock/16; // = 192000kHz, should be enough rate=chipClock/16; // = 192000kHz, should be enough
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
isMuted[i]=false; isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
oscBuf[i]->rate=rate;
} }
ws=new WSwan(); ws=new WSwan();
reset(); reset();
@ -539,6 +548,9 @@ int DivPlatformSwan::init(DivEngine* p, int channels, int sugRate, unsigned int
} }
void DivPlatformSwan::quit() { void DivPlatformSwan::quit() {
for (int i=0; i<4; i++) {
delete oscBuf[i];
}
delete ws; delete ws;
} }

View File

@ -57,6 +57,7 @@ class DivPlatformSwan: public DivDispatch {
wave(-1) {} wave(-1) {}
}; };
Channel chan[4]; Channel chan[4];
DivDispatchOscBuffer* oscBuf[4];
bool isMuted[4]; bool isMuted[4];
bool pcm, sweep, furnaceDac; bool pcm, sweep, furnaceDac;
unsigned char sampleBank, noise; unsigned char sampleBank, noise;
@ -78,6 +79,7 @@ class DivPlatformSwan: 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();

View File

@ -48,7 +48,7 @@ const char** DivPlatformTIA::getRegisterSheet() {
} }
void DivPlatformTIA::acquire(short* bufL, short* bufR, size_t start, size_t len) { void DivPlatformTIA::acquire(short* bufL, short* bufR, size_t start, size_t len) {
tia.process(bufL+start,len); tia.process(bufL+start,len,oscBuf);
} }
unsigned char DivPlatformTIA::dealWithFreq(unsigned char shape, int base, int pitch) { unsigned char DivPlatformTIA::dealWithFreq(unsigned char shape, int base, int pitch) {
@ -290,6 +290,10 @@ void* DivPlatformTIA::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformTIA::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformTIA::getRegisterPool() { unsigned char* DivPlatformTIA::getRegisterPool() {
return regPool; return regPool;
} }
@ -337,6 +341,9 @@ void DivPlatformTIA::setFlags(unsigned int flags) {
rate=31468; rate=31468;
} }
chipClock=rate; chipClock=rate;
for (int i=0; i<2; i++) {
oscBuf[i]->rate=rate;
}
} }
int DivPlatformTIA::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { int DivPlatformTIA::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
@ -345,6 +352,7 @@ int DivPlatformTIA::init(DivEngine* p, int channels, int sugRate, unsigned int f
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;
} }
tia.channels(1,false); tia.channels(1,false);
setFlags(flags); setFlags(flags);

View File

@ -40,6 +40,7 @@ class DivPlatformTIA: public DivDispatch {
Channel(): freq(0), baseFreq(0), pitch(0), pitch2(0), note(0), ins(-1), shape(4), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), portaPause(false), inPorta(false), vol(0), outVol(15) {} Channel(): freq(0), baseFreq(0), pitch(0), pitch2(0), note(0), ins(-1), shape(4), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), portaPause(false), inPorta(false), vol(0), outVol(15) {}
}; };
Channel chan[2]; Channel chan[2];
DivDispatchOscBuffer* oscBuf[2];
bool isMuted[2]; bool isMuted[2];
TIASound tia; TIASound tia;
unsigned char regPool[16]; unsigned char regPool[16];
@ -51,6 +52,7 @@ class DivPlatformTIA: 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();

View File

@ -111,12 +111,20 @@ void DivPlatformVERA::acquire(short* bufL, short* bufR, size_t start, size_t len
} }
int curLen=MIN(len,128); int curLen=MIN(len,128);
memset(buf,0,sizeof(buf)); memset(buf,0,sizeof(buf));
psg_render(psg,buf[0],buf[1],curLen);
pcm_render(pcm,buf[2],buf[3],curLen); pcm_render(pcm,buf[2],buf[3],curLen);
for (int i=0; i<curLen; i++) { for (int i=0; i<curLen; i++) {
psg_render(psg,&buf[0][i],&buf[1][i],1);
bufL[pos]=(short)(((int)buf[0][i]+buf[2][i])/2); bufL[pos]=(short)(((int)buf[0][i]+buf[2][i])/2);
bufR[pos]=(short)(((int)buf[1][i]+buf[3][i])/2); bufR[pos]=(short)(((int)buf[1][i]+buf[3][i])/2);
pos++; pos++;
for (int i=0; i<16; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=psg->channels[i].lastOut<<4;
}
int pcmOut=buf[2][i]+buf[3][i];
if (pcmOut<-32768) pcmOut=-32768;
if (pcmOut>32767) pcmOut=32767;
oscBuf[16]->data[oscBuf[16]->needle++]=pcmOut;
} }
len-=curLen; len-=curLen;
} }
@ -373,6 +381,10 @@ void* DivPlatformVERA::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformVERA::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformVERA::getRegisterPool() { unsigned char* DivPlatformVERA::getRegisterPool() {
return regPool; return regPool;
} }
@ -426,6 +438,7 @@ void DivPlatformVERA::poke(std::vector<DivRegWrite>& wlist) {
int DivPlatformVERA::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { int DivPlatformVERA::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
for (int i=0; i<17; i++) { for (int i=0; i<17; i++) {
isMuted[i]=false; isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
} }
parent=p; parent=p;
psg=new struct VERA_PSG; psg=new struct VERA_PSG;
@ -434,11 +447,17 @@ int DivPlatformVERA::init(DivEngine* p, int channels, int sugRate, unsigned int
skipRegisterWrites=false; skipRegisterWrites=false;
chipClock=25000000; chipClock=25000000;
rate=chipClock/512; rate=chipClock/512;
for (int i=0; i<17; i++) {
oscBuf[i]->rate=rate;
}
reset(); reset();
return 17; return 17;
} }
void DivPlatformVERA::quit() { void DivPlatformVERA::quit() {
for (int i=0; i<17; i++) {
delete oscBuf[i];
}
delete psg; delete psg;
delete pcm; delete pcm;
} }

View File

@ -53,6 +53,7 @@ class DivPlatformVERA: public DivDispatch {
Channel(): freq(0), baseFreq(0), pitch(0), pitch2(0), note(0), ins(-1), pan(0), active(false), freqChanged(false), inPorta(false), vol(0), outVol(0), accum(0), noiseval(0) {} Channel(): freq(0), baseFreq(0), pitch(0), pitch2(0), note(0), ins(-1), pan(0), active(false), freqChanged(false), inPorta(false), vol(0), outVol(0), accum(0), noiseval(0) {}
}; };
Channel chan[17]; Channel chan[17];
DivDispatchOscBuffer* oscBuf[17];
bool isMuted[17]; bool isMuted[17];
unsigned char regPool[67]; unsigned char regPool[67];
struct VERA_PSG* psg; struct VERA_PSG* psg;
@ -65,6 +66,7 @@ class DivPlatformVERA: 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();

View File

@ -77,6 +77,9 @@ void DivPlatformVIC20::acquire(short* bufL, short* bufR, size_t start, size_t le
vic_sound_machine_calculate_samples(vic,&samp,1,1,0,SAMP_DIVIDER); vic_sound_machine_calculate_samples(vic,&samp,1,1,0,SAMP_DIVIDER);
bufL[h]=samp; bufL[h]=samp;
bufR[h]=samp; bufR[h]=samp;
for (int i=0; i<4; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=vic->ch[i].out?(vic->volume<<11):0;
}
} }
} }
@ -275,6 +278,10 @@ void* DivPlatformVIC20::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformVIC20::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformVIC20::getRegisterPool() { unsigned char* DivPlatformVIC20::getRegisterPool() {
return regPool; return regPool;
} }
@ -314,6 +321,9 @@ void DivPlatformVIC20::setFlags(unsigned int flags) {
chipClock=COLOR_NTSC*2.0/7.0; chipClock=COLOR_NTSC*2.0/7.0;
} }
rate=chipClock/4; rate=chipClock/4;
for (int i=0; i<4; i++) {
oscBuf[i]->rate=rate;
}
} }
void DivPlatformVIC20::poke(unsigned int addr, unsigned short val) { void DivPlatformVIC20::poke(unsigned int addr, unsigned short val) {
@ -330,6 +340,7 @@ int DivPlatformVIC20::init(DivEngine* p, int channels, int sugRate, unsigned int
skipRegisterWrites=false; skipRegisterWrites=false;
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
isMuted[i]=false; isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
} }
setFlags(flags); setFlags(flags);
vic=new sound_vic20_t(); vic=new sound_vic20_t();
@ -338,6 +349,9 @@ int DivPlatformVIC20::init(DivEngine* p, int channels, int sugRate, unsigned int
} }
void DivPlatformVIC20::quit() { void DivPlatformVIC20::quit() {
for (int i=0; i<4; i++) {
delete oscBuf[i];
}
delete vic; delete vic;
} }

View File

@ -56,6 +56,7 @@ class DivPlatformVIC20: public DivDispatch {
waveWriteCycle(-1) {} waveWriteCycle(-1) {}
}; };
Channel chan[4]; Channel chan[4];
DivDispatchOscBuffer* oscBuf[4];
bool isMuted[4]; bool isMuted[4];
bool hasWaveWrite; bool hasWaveWrite;
@ -67,6 +68,7 @@ class DivPlatformVIC20: 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();

View File

@ -97,6 +97,14 @@ void DivPlatformVRC6::acquire(short* bufL, short* bufR, size_t start, size_t len
if (sample<-32768) sample=-32768; if (sample<-32768) sample=-32768;
bufL[i]=bufR[i]=sample; bufL[i]=bufR[i]=sample;
// Oscilloscope buffer part
if (++writeOscBuf>=32) {
writeOscBuf=0;
for (int i=0; i<3; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=vrc6.chan_out(i)<<10;
}
}
// Command part // Command part
while (!writes.empty()) { while (!writes.empty()) {
QueuedWrite w=writes.front(); QueuedWrite w=writes.front();
@ -427,6 +435,10 @@ void* DivPlatformVRC6::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformVRC6::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformVRC6::getRegisterPool() { unsigned char* DivPlatformVRC6::getRegisterPool() {
return regPool; return regPool;
} }
@ -471,6 +483,9 @@ void DivPlatformVRC6::setFlags(unsigned int flags) {
rate=COLOR_NTSC/2.0; rate=COLOR_NTSC/2.0;
} }
chipClock=rate; chipClock=rate;
for (int i=0; i<3; i++) {
oscBuf[i]->rate=rate/32;
}
} }
void DivPlatformVRC6::notifyInsDeletion(void* ins) { void DivPlatformVRC6::notifyInsDeletion(void* ins) {
@ -491,8 +506,10 @@ int DivPlatformVRC6::init(DivEngine* p, int channels, int sugRate, unsigned int
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);
reset(); reset();
@ -500,6 +517,9 @@ int DivPlatformVRC6::init(DivEngine* p, int channels, int sugRate, unsigned int
} }
void DivPlatformVRC6::quit() { void DivPlatformVRC6::quit() {
for (int i=0; i<3; i++) {
delete oscBuf[i];
}
} }
DivPlatformVRC6::~DivPlatformVRC6() { DivPlatformVRC6::~DivPlatformVRC6() {

View File

@ -65,6 +65,7 @@ class DivPlatformVRC6: public DivDispatch {
outVol(15) {} outVol(15) {}
}; };
Channel chan[3]; Channel chan[3];
DivDispatchOscBuffer* oscBuf[3];
bool isMuted[3]; bool isMuted[3];
struct QueuedWrite { struct QueuedWrite {
unsigned short addr; unsigned short addr;
@ -73,6 +74,7 @@ class DivPlatformVRC6: public DivDispatch {
}; };
std::queue<QueuedWrite> writes; std::queue<QueuedWrite> writes;
unsigned char sampleBank; unsigned char sampleBank;
unsigned char writeOscBuf;
vrcvi_intf intf; vrcvi_intf intf;
vrcvi_core vrc6; vrcvi_core vrc6;
unsigned char regPool[13]; unsigned char regPool[13];
@ -83,6 +85,7 @@ class DivPlatformVRC6: 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();

View File

@ -252,6 +252,10 @@ void DivPlatformX1_010::acquire(short* bufL, short* bufR, size_t start, size_t l
//printf("tempL: %d tempR: %d\n",tempL,tempR); //printf("tempL: %d tempR: %d\n",tempL,tempR);
bufL[h]=stereo?tempL:((tempL+tempR)>>1); bufL[h]=stereo?tempL:((tempL+tempR)>>1);
bufR[h]=stereo?tempR:bufL[h]; bufR[h]=stereo?tempR:bufL[h];
for (int i=0; i<16; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=x1_010->chan_out(i);
}
} }
} }
@ -822,6 +826,10 @@ void* DivPlatformX1_010::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformX1_010::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformX1_010::getRegisterPool() { unsigned char* DivPlatformX1_010::getRegisterPool() {
for (int i=0; i<0x2000; i++) { for (int i=0; i<0x2000; i++) {
regPool[i]=x1_010->ram_r(i); regPool[i]=x1_010->ram_r(i);
@ -888,6 +896,9 @@ void DivPlatformX1_010::setFlags(unsigned int flags) {
} }
rate=chipClock/512; rate=chipClock/512;
stereo=flags&16; stereo=flags&16;
for (int i=0; i<16; i++) {
oscBuf[i]->rate=rate;
}
} }
void DivPlatformX1_010::poke(unsigned int addr, unsigned short val) { void DivPlatformX1_010::poke(unsigned int addr, unsigned short val) {
@ -905,6 +916,7 @@ int DivPlatformX1_010::init(DivEngine* p, int channels, int sugRate, unsigned in
stereo=false; stereo=false;
for (int i=0; i<16; i++) { for (int i=0; i<16; i++) {
isMuted[i]=false; isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
} }
setFlags(flags); setFlags(flags);
intf.parent=parent; intf.parent=parent;
@ -915,6 +927,9 @@ int DivPlatformX1_010::init(DivEngine* p, int channels, int sugRate, unsigned in
} }
void DivPlatformX1_010::quit() { void DivPlatformX1_010::quit() {
for (int i=0; i<16; i++) {
delete oscBuf[i];
}
delete x1_010; delete x1_010;
} }

View File

@ -112,6 +112,7 @@ class DivPlatformX1_010: public DivDispatch {
waveBank(0) {} waveBank(0) {}
}; };
Channel chan[16]; Channel chan[16];
DivDispatchOscBuffer* oscBuf[16];
bool isMuted[16]; bool isMuted[16];
bool stereo=false; bool stereo=false;
unsigned char sampleBank; unsigned char sampleBank;
@ -126,6 +127,7 @@ class DivPlatformX1_010: 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();

View File

@ -18,6 +18,7 @@
*/ */
#include "ym2610.h" #include "ym2610.h"
#include "sound/ymfm/ymfm.h"
#include "../engine.h" #include "../engine.h"
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
@ -30,6 +31,10 @@ static unsigned char konOffs[4]={
1, 2, 5, 6 1, 2, 5, 6
}; };
static unsigned char bchOffs[4]={
1, 2, 4, 5
};
#define CHIP_DIVIDER 32 #define CHIP_DIVIDER 32
const char* regCheatSheetYM2610[]={ const char* regCheatSheetYM2610[]={
@ -337,6 +342,14 @@ double DivPlatformYM2610::NOTE_ADPCMB(int note) {
void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t len) { void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t len) {
static int os[2]; static int os[2];
ymfm::ym2612::fm_engine* fme=fm->debug_fm_engine();
ymfm::ssg_engine* ssge=fm->debug_ssg_engine();
ymfm::adpcm_a_engine* aae=fm->debug_adpcm_a_engine();
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
ymfm::ssg_engine::output_data ssgOut;
ymfm::ymfm_output<2> adpcmOut;
for (size_t h=start; h<start+len; h++) { for (size_t h=start; h<start+len; h++) {
os[0]=0; os[1]=0; os[0]=0; os[1]=0;
if (!writes.empty()) { if (!writes.empty()) {
@ -362,6 +375,26 @@ void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t l
bufL[h]=os[0]; bufL[h]=os[0];
bufR[h]=os[1]; bufR[h]=os[1];
for (int i=0; i<4; i++) {
int ch=bchOffs[i];
oscBuf[i]->data[oscBuf[i]->needle++]=(fme->debug_channel(ch)->debug_output(0)+fme->debug_channel(ch)->debug_output(1));
}
ssge->get_last_out(ssgOut);
for (int i=4; i<7; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=ssgOut.data[i-4];
}
for (int i=7; i<13; i++) {
adpcmOut.clear();
aae->debug_channel(i-7)->output<2>(adpcmOut);
oscBuf[i]->data[oscBuf[i]->needle++]=adpcmOut.data[0]+adpcmOut.data[1];
}
adpcmOut.clear();
abe->output(adpcmOut,1);
oscBuf[13]->data[oscBuf[13]->needle++]=adpcmOut.data[0]+adpcmOut.data[1];
} }
} }
@ -1058,6 +1091,10 @@ void* DivPlatformYM2610::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformYM2610::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformYM2610::getRegisterPool() { unsigned char* DivPlatformYM2610::getRegisterPool() {
return regPool; return regPool;
} }
@ -1153,9 +1190,13 @@ int DivPlatformYM2610::init(DivEngine* p, int channels, int sugRate, unsigned in
skipRegisterWrites=false; skipRegisterWrites=false;
for (int i=0; i<14; i++) { for (int i=0; i<14; i++) {
isMuted[i]=false; isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
} }
chipClock=8000000; chipClock=8000000;
rate=chipClock/16; rate=chipClock/16;
for (int i=0; i<14; i++) {
oscBuf[i]->rate=rate;
}
iface.parent=parent; iface.parent=parent;
iface.sampleBank=0; iface.sampleBank=0;
fm=new ymfm::ym2610(iface); fm=new ymfm::ym2610(iface);
@ -1168,6 +1209,9 @@ int DivPlatformYM2610::init(DivEngine* p, int channels, int sugRate, unsigned in
} }
void DivPlatformYM2610::quit() { void DivPlatformYM2610::quit() {
for (int i=0; i<14; i++) {
delete oscBuf[i];
}
ay->quit(); ay->quit();
delete ay; delete ay;
delete fm; delete fm;

View File

@ -82,6 +82,7 @@ class DivPlatformYM2610: public DivDispatch {
pan(3) {} pan(3) {}
}; };
Channel chan[14]; Channel chan[14];
DivDispatchOscBuffer* oscBuf[14];
bool isMuted[14]; bool isMuted[14];
struct QueuedWrite { struct QueuedWrite {
unsigned short addr; unsigned short addr;
@ -117,6 +118,7 @@ class DivPlatformYM2610: 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();

View File

@ -18,6 +18,7 @@
*/ */
#include "ym2610b.h" #include "ym2610b.h"
#include "sound/ymfm/ymfm.h"
#include "../engine.h" #include "../engine.h"
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
@ -401,6 +402,14 @@ double DivPlatformYM2610B::NOTE_ADPCMB(int note) {
void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t len) { void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t len) {
static int os[2]; static int os[2];
ymfm::ym2612::fm_engine* fme=fm->debug_fm_engine();
ymfm::ssg_engine* ssge=fm->debug_ssg_engine();
ymfm::adpcm_a_engine* aae=fm->debug_adpcm_a_engine();
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
ymfm::ssg_engine::output_data ssgOut;
ymfm::ymfm_output<2> adpcmOut;
for (size_t h=start; h<start+len; h++) { for (size_t h=start; h<start+len; h++) {
os[0]=0; os[1]=0; os[0]=0; os[1]=0;
if (!writes.empty()) { if (!writes.empty()) {
@ -426,6 +435,25 @@ void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t
bufL[h]=os[0]; bufL[h]=os[0];
bufR[h]=os[1]; bufR[h]=os[1];
for (int i=0; i<6; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=(fme->debug_channel(i)->debug_output(0)+fme->debug_channel(i)->debug_output(1));
}
ssge->get_last_out(ssgOut);
for (int i=6; i<9; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=ssgOut.data[i-6];
}
for (int i=9; i<15; i++) {
adpcmOut.clear();
aae->debug_channel(i-9)->output<2>(adpcmOut);
oscBuf[i]->data[oscBuf[i]->needle++]=adpcmOut.data[0]+adpcmOut.data[1];
}
adpcmOut.clear();
abe->output(adpcmOut,1);
oscBuf[15]->data[oscBuf[15]->needle++]=adpcmOut.data[0]+adpcmOut.data[1];
} }
} }
@ -1121,6 +1149,10 @@ void* DivPlatformYM2610B::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformYM2610B::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformYM2610B::getRegisterPool() { unsigned char* DivPlatformYM2610B::getRegisterPool() {
return regPool; return regPool;
} }
@ -1216,9 +1248,13 @@ int DivPlatformYM2610B::init(DivEngine* p, int channels, int sugRate, unsigned i
skipRegisterWrites=false; skipRegisterWrites=false;
for (int i=0; i<16; i++) { for (int i=0; i<16; i++) {
isMuted[i]=false; isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
} }
chipClock=8000000; chipClock=8000000;
rate=chipClock/16; rate=chipClock/16;
for (int i=0; i<16; i++) {
oscBuf[i]->rate=rate;
}
iface.parent=parent; iface.parent=parent;
iface.sampleBank=0; iface.sampleBank=0;
fm=new ymfm::ym2610b(iface); fm=new ymfm::ym2610b(iface);
@ -1231,6 +1267,9 @@ int DivPlatformYM2610B::init(DivEngine* p, int channels, int sugRate, unsigned i
} }
void DivPlatformYM2610B::quit() { void DivPlatformYM2610B::quit() {
for (int i=0; i<16; i++) {
delete oscBuf[i];
}
ay->quit(); ay->quit();
delete ay; delete ay;
delete fm; delete fm;

View File

@ -74,6 +74,7 @@ class DivPlatformYM2610B: public DivDispatch {
pan(3) {} pan(3) {}
}; };
Channel chan[16]; Channel chan[16];
DivDispatchOscBuffer* oscBuf[16];
bool isMuted[16]; bool isMuted[16];
struct QueuedWrite { struct QueuedWrite {
unsigned short addr; unsigned short addr;
@ -108,6 +109,7 @@ class DivPlatformYM2610B: 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();

View File

@ -336,13 +336,18 @@ void DivPlatformYM2610BExt::forceIns() {
} }
} }
void* DivPlatformYM2610BExt::getChanState(int ch) { void* DivPlatformYM2610BExt::getChanState(int ch) {
if (ch>=6) return &chan[ch-3]; if (ch>=6) return &chan[ch-3];
if (ch>=2) return &opChan[ch-2]; if (ch>=2) return &opChan[ch-2];
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformYM2610BExt::getOscBuffer(int ch) {
if (ch>=6) return oscBuf[ch-3];
if (ch<3) return oscBuf[ch];
return NULL;
}
void DivPlatformYM2610BExt::reset() { void DivPlatformYM2610BExt::reset() {
DivPlatformYM2610B::reset(); DivPlatformYM2610B::reset();

View File

@ -38,6 +38,7 @@ class DivPlatformYM2610BExt: public DivPlatformYM2610B {
public: public:
int dispatch(DivCommand c); int dispatch(DivCommand c);
void* getChanState(int chan); void* getChanState(int chan);
DivDispatchOscBuffer* getOscBuffer(int chan);
void reset(); void reset();
void forceIns(); void forceIns();
void tick(bool sysTick=true); void tick(bool sysTick=true);

View File

@ -343,6 +343,12 @@ void* DivPlatformYM2610Ext::getChanState(int ch) {
return &chan[ch]; return &chan[ch];
} }
DivDispatchOscBuffer* DivPlatformYM2610Ext::getOscBuffer(int ch) {
if (ch>=5) return oscBuf[ch-3];
if (ch<2) return oscBuf[ch];
return NULL;
}
void DivPlatformYM2610Ext::reset() { void DivPlatformYM2610Ext::reset() {
DivPlatformYM2610::reset(); DivPlatformYM2610::reset();

View File

@ -38,6 +38,7 @@ class DivPlatformYM2610Ext: public DivPlatformYM2610 {
public: public:
int dispatch(DivCommand c); int dispatch(DivCommand c);
void* getChanState(int chan); void* getChanState(int chan);
DivDispatchOscBuffer* getOscBuffer(int chan);
void reset(); void reset();
void forceIns(); void forceIns();
void tick(bool sysTick=true); void tick(bool sysTick=true);

View File

@ -375,7 +375,8 @@ 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_PCE, DIV_INS_PCE, DIV_INS_PCE, DIV_INS_PCE, DIV_INS_PCE, DIV_INS_PCE} {DIV_INS_PCE, DIV_INS_PCE, DIV_INS_PCE, DIV_INS_PCE, DIV_INS_PCE, DIV_INS_PCE},
{DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA}
); );
sysDefs[DIV_SYSTEM_NES]=new DivSysDef( sysDefs[DIV_SYSTEM_NES]=new DivSysDef(

View File

@ -38,8 +38,8 @@ void FurnaceGUI::drawChanOsc() {
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding,ImVec2(0.0f,0.0f)); ImGui::PushStyleVar(ImGuiStyleVar_CellPadding,ImVec2(0.0f,0.0f));
float availY=ImGui::GetContentRegionAvail().y; float availY=ImGui::GetContentRegionAvail().y;
if (ImGui::BeginTable("ChanOsc",chanOscCols,ImGuiTableFlags_Borders)) { if (ImGui::BeginTable("ChanOsc",chanOscCols,ImGuiTableFlags_Borders)) {
std::vector<DivDispatchOscBuffer*> oscBufs;
int chans=e->getTotalChannelCount(); int chans=e->getTotalChannelCount();
int rows=(chans+(chanOscCols-1))/chanOscCols;
ImDrawList* dl=ImGui::GetWindowDrawList(); ImDrawList* dl=ImGui::GetWindowDrawList();
ImGuiWindow* window=ImGui::GetCurrentWindow(); ImGuiWindow* window=ImGui::GetCurrentWindow();
ImVec2 waveform[512]; ImVec2 waveform[512];
@ -48,12 +48,18 @@ void FurnaceGUI::drawChanOsc() {
ImU32 color=ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_WAVE]); ImU32 color=ImGui::GetColorU32(uiColors[GUI_COLOR_OSC_WAVE]);
for (int i=0; i<chans; i++) { for (int i=0; i<chans; i++) {
DivDispatchOscBuffer* buf=e->getOscBuffer(i);
if (buf!=NULL) oscBufs.push_back(buf);
}
int rows=(oscBufs.size()+(chanOscCols-1))/chanOscCols;
for (size_t i=0; i<oscBufs.size(); i++) {
if (i%chanOscCols==0) ImGui::TableNextRow(); if (i%chanOscCols==0) ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
DivDispatchOscBuffer* buf=e->getOscBuffer(i); DivDispatchOscBuffer* buf=oscBufs[i];
if (buf==NULL) { if (buf==NULL) {
ImGui::Text("Not Available"); ImGui::Text("Error!");
} else { } else {
ImVec2 size=ImGui::GetContentRegionAvail(); ImVec2 size=ImGui::GetContentRegionAvail();
size.y=availY/rows; size.y=availY/rows;

Some files were not shown because too many files have changed in this diff Show More