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

* 'master' of https://github.com/tildearrow/furnace:
  YM2610: optimize oscilloscope fetch CPU usage
  GUI: add audio load meter to statistics
  GUI: put "OK" and "Cancel" buttons in the bottom
  better FM chip names
  sysDef refactor, part 3 - PLEASE READ
  NO
  Reduce unnecessary line
  Debug improvements
  AY8930: Fix VGM output.

# Conflicts:
#	.gitignore
#	src/engine/playback.cpp
#	src/gui/debugWindow.cpp
This commit is contained in:
cam900 2022-05-04 03:32:26 +09:00
commit 4021abe495
18 changed files with 2519 additions and 1925 deletions

View file

@ -26,8 +26,6 @@
- unified data view - unified data view
- volume commands should work on Game Boy - volume commands should work on Game Boy
- macro editor menu - macro editor menu
- refactor sysDef.cpp
- effect/postEffect refactor
- add another FM editor layout - add another FM editor layout
- try to find out why does VSlider not accept keyboard input - try to find out why does VSlider not accept keyboard input
- finish lock layout - finish lock layout
@ -36,7 +34,5 @@
- store edit/followOrders/followPattern state in config - store edit/followOrders/followPattern state in config
- add ability to select a column by double clicking - add ability to select a column by double clicking
- add ability to move selection by dragging - add ability to move selection by dragging
- settings: OK/Cancel buttons should be always visible
- Apply button in settings - Apply button in settings
- better FM chip names (number and codename)
- find and replace - find and replace

View file

@ -71,9 +71,9 @@ afterwards everyone moved to Windows and software mixed PCM streaming...
- `56xx`: set DR of all operators. - `56xx`: set DR of all operators.
- `57xx`: set DR of operator 1. - `57xx`: set DR of operator 1.
- `58xx`: set DR of operator 2. - `58xx`: set DR of operator 2.
- `58xx`: set DR of operator 3. - `59xx`: set DR of operator 3.
- only in 4-op mode (OPL3). - only in 4-op mode (OPL3).
- `58xx`: set DR of operator 4. - `5Axx`: set DR of operator 4.
- only in 4-op mode (OPL3). - only in 4-op mode (OPL3).
- `5Bxy`: set KSR of operator. - `5Bxy`: set KSR of operator.
- `x` is the operator (1-4; last 2 operators only in 4-op mode). a value of 0 means "all operators". - `x` is the operator (1-4; last 2 operators only in 4-op mode). a value of 0 means "all operators".

View file

@ -233,15 +233,19 @@ struct DivRegWrite {
}; };
struct DivDispatchOscBuffer { struct DivDispatchOscBuffer {
bool follow;
unsigned int rate; unsigned int rate;
unsigned short needle; unsigned short needle;
unsigned short readNeedle; unsigned short readNeedle;
unsigned short followNeedle;
short data[65536]; short data[65536];
DivDispatchOscBuffer(): DivDispatchOscBuffer():
follow(true),
rate(65536), rate(65536),
needle(0), needle(0),
readNeedle(0) { readNeedle(0),
followNeedle(0) {
memset(data,0,65536*sizeof(short)); memset(data,0,65536*sizeof(short));
} }
}; };

View file

@ -26,6 +26,7 @@
#include "safeWriter.h" #include "safeWriter.h"
#include "../audio/taAudio.h" #include "../audio/taAudio.h"
#include "blip_buf.h" #include "blip_buf.h"
#include <atomic>
#include <functional> #include <functional>
#include <initializer_list> #include <initializer_list>
#include <thread> #include <thread>
@ -208,8 +209,8 @@ struct DivSysDef {
std::initializer_list<int> chTypes, std::initializer_list<int> chTypes,
std::initializer_list<DivInstrumentType> chInsType1, std::initializer_list<DivInstrumentType> chInsType1,
std::initializer_list<DivInstrumentType> chInsType2={}, std::initializer_list<DivInstrumentType> chInsType2={},
EffectProcess fxHandler=NULL, EffectProcess fxHandler=[](int,unsigned char,unsigned char) -> bool {return false;},
EffectProcess postFxHandler=NULL): EffectProcess postFxHandler=[](int,unsigned char,unsigned char) -> bool {return false;}):
name(sysName), name(sysName),
nameJ(sysNameJ), nameJ(sysNameJ),
id(fileID), id(fileID),
@ -418,6 +419,7 @@ class DivEngine {
float oscSize; float oscSize;
int oscReadPos, oscWritePos; int oscReadPos, oscWritePos;
int tickMult; int tickMult;
std::atomic<size_t> processTime;
void runExportThread(); void runExportThread();
void nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size); void nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size);
@ -925,7 +927,8 @@ class DivEngine {
oscSize(1), oscSize(1),
oscReadPos(0), oscReadPos(0),
oscWritePos(0), oscWritePos(0),
tickMult(1) { tickMult(1),
processTime(0) {
memset(isMuted,0,DIV_MAX_CHANS*sizeof(bool)); memset(isMuted,0,DIV_MAX_CHANS*sizeof(bool));
memset(keyHit,0,DIV_MAX_CHANS*sizeof(bool)); memset(keyHit,0,DIV_MAX_CHANS*sizeof(bool));
memset(dispatchChanOfChan,0,DIV_MAX_CHANS*sizeof(int)); memset(dispatchChanOfChan,0,DIV_MAX_CHANS*sizeof(int));

View file

@ -25,7 +25,7 @@
#include <math.h> #include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;} #define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;}
#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} } #define immWrite2(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define CHIP_DIVIDER 8 #define CHIP_DIVIDER 8
@ -61,6 +61,18 @@ const char* regCheatSheetAY8930[]={
NULL NULL
}; };
void DivPlatformAY8930::immWrite(unsigned char a, unsigned char v) {
if ((int)bank!=(a>>4)) {
bank=a>>4;
immWrite2(0x0d, 0xa0|(bank<<4)|ayEnvMode[0]);
}
if (a==0x0d) {
immWrite2(0x0d,0xa0|(bank<<4)|(v&15));
} else {
immWrite2(a&15,v);
}
}
const char** DivPlatformAY8930::getRegisterSheet() { const char** DivPlatformAY8930::getRegisterSheet() {
return regCheatSheetAY8930; return regCheatSheetAY8930;
} }
@ -123,18 +135,13 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l
} }
while (!writes.empty()) { while (!writes.empty()) {
QueuedWrite w=writes.front(); QueuedWrite w=writes.front();
if ((int)bank!=(w.addr>>4)) { ay->address_w(w.addr);
bank=w.addr>>4; ay->data_w(w.val);
ay->address_w(0x0d); if (w.addr!=0x0d && (regPool[0x0d]&0xf0)==0xb0) {
ay->data_w(0xa0|(bank<<4)|ayEnvMode[0]); regPool[(w.addr&0x0f)|0x10]=w.val;
}
ay->address_w(w.addr&15);
if (w.addr==0x0d) {
ay->data_w(0xa0|(bank<<4)|(w.val&15));
} else { } else {
ay->data_w(w.val); regPool[w.addr&0x0f]=w.val;
} }
regPool[w.addr&0x1f]=w.val;
writes.pop(); writes.pop();
} }
ay->sound_stream_update(ayBuf,len); ay->sound_stream_update(ayBuf,len);

View file

@ -73,6 +73,7 @@ class DivPlatformAY8930: public DivDispatch {
size_t ayBufLen; size_t ayBufLen;
void updateOutSel(bool immediate=false); void updateOutSel(bool immediate=false);
void immWrite(unsigned char a, unsigned char v);
friend void putDispatchChan(void*,int,int); friend void putDispatchChan(void*,int,int);

View file

@ -269,7 +269,7 @@ void DivPlatformES5506::tick(bool sysTick) {
signed int k1=chan[i].k1Prev,k2=chan[i].k2Prev; signed int k1=chan[i].k1Prev,k2=chan[i].k2Prev;
// volume/panning macros // volume/panning macros
if (chan[i].std.vol.had) { if (chan[i].std.vol.had) {
const unsigned int nextVol=((chan[i].vol&0xff)*MIN(0xffff,chan[i].std.vol.val))/0xff; const unsigned int nextVol=((chan[i].vol&0xff)*MIN(0xffff,(0xffff*chan[i].std.vol.val)/chan[i].volMacroMax))/0xff;
if (chan[i].outVol!=nextVol) { if (chan[i].outVol!=nextVol) {
chan[i].outVol=nextVol; chan[i].outVol=nextVol;
if (!isMuted[i]) { if (!isMuted[i]) {
@ -278,7 +278,7 @@ void DivPlatformES5506::tick(bool sysTick) {
} }
} }
if (chan[i].std.panL.had) { if (chan[i].std.panL.had) {
const unsigned int nextLVol=(((ins->es5506.lVol*(chan[i].lVol&0xff))/0xff)*MIN(0xffff,chan[i].std.panL.val))/0xffff; const unsigned int nextLVol=(((ins->es5506.lVol*(chan[i].lVol&0xff))/0xff)*MIN(0xffff,(0xffff*chan[i].std.panL.val)/chan[i].panMacroMax))/0xffff;
if (chan[i].outLVol!=nextLVol) { if (chan[i].outLVol!=nextLVol) {
chan[i].outLVol=nextLVol; chan[i].outLVol=nextLVol;
if (!isMuted[i]) { if (!isMuted[i]) {
@ -287,7 +287,7 @@ void DivPlatformES5506::tick(bool sysTick) {
} }
} }
if (chan[i].std.panR.had) { if (chan[i].std.panR.had) {
const unsigned int nextRVol=(((ins->es5506.rVol*(chan[i].rVol&0xff))/0xff)*MIN(0xffff,chan[i].std.panR.val))/0xffff; const unsigned int nextRVol=(((ins->es5506.rVol*(chan[i].rVol&0xff))/0xff)*MIN(0xffff,(0xffff*chan[i].std.panR.val)/chan[i].panMacroMax))/0xffff;
if (chan[i].outRVol!=nextRVol) { if (chan[i].outRVol!=nextRVol) {
chan[i].outRVol=nextRVol; chan[i].outRVol=nextRVol;
if (!isMuted[i]) { if (!isMuted[i]) {
@ -644,11 +644,22 @@ int DivPlatformES5506::dispatch(DivCommand c) {
chan[c.chan].pcm.length=length; chan[c.chan].pcm.length=length;
chan[c.chan].pcm.loopStart=(start+(s->loopStart<<11))&0xfffff800; chan[c.chan].pcm.loopStart=(start+(s->loopStart<<11))&0xfffff800;
chan[c.chan].pcm.loopEnd=(start+((s->loopEnd-1)<<11))&0xffffff80; chan[c.chan].pcm.loopEnd=(start+((s->loopEnd-1)<<11))&0xffffff80;
chan[c.chan].filter=ins->es5506.filter; if (ins->type==DIV_INS_ES5506) { // Native format
chan[c.chan].envelope=ins->es5506.envelope; chan[c.chan].volMacroMax=0xffff;
chan[c.chan].panMacroMax=0xffff;
chan[c.chan].filter=ins->es5506.filter;
chan[c.chan].envelope=ins->es5506.envelope;
} else { // Amiga format
chan[c.chan].volMacroMax=64;
chan[c.chan].panMacroMax=127;
chan[c.chan].filter=DivInstrumentES5506::Filter();
chan[c.chan].envelope=DivInstrumentES5506::Envelope();
}
} else { } else {
chan[c.chan].sample=-1; chan[c.chan].sample=-1;
chan[c.chan].pcm.index=-1; chan[c.chan].pcm.index=-1;
chan[c.chan].volMacroMax=0xffff;
chan[c.chan].panMacroMax=0xffff;
chan[c.chan].filter=DivInstrumentES5506::Filter(); chan[c.chan].filter=DivInstrumentES5506::Filter();
chan[c.chan].envelope=DivInstrumentES5506::Envelope(); chan[c.chan].envelope=DivInstrumentES5506::Envelope();
} }

View file

@ -56,6 +56,7 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
loopMode(DIV_SAMPLE_LOOPMODE_ONESHOT) {} loopMode(DIV_SAMPLE_LOOPMODE_ONESHOT) {}
} pcm; } pcm;
int freq, baseFreq, pitch, pitch2, note, ins, sample, wave; int freq, baseFreq, pitch, pitch2, note, ins, sample, wave;
unsigned int volMacroMax, panMacroMax;
bool active, insChanged, freqChanged, pcmChanged, keyOn, keyOff, inPorta, useWave, isReverseLoop; bool active, insChanged, freqChanged, pcmChanged, keyOn, keyOff, inPorta, useWave, isReverseLoop;
struct VolChanged { // Volume changed flags struct VolChanged { // Volume changed flags
@ -135,6 +136,8 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
ins(-1), ins(-1),
sample(-1), sample(-1),
wave(-1), wave(-1),
volMacroMax(0xffff),
panMacroMax(0xffff),
active(false), active(false),
insChanged(true), insChanged(true),
freqChanged(false), freqChanged(false),

View file

@ -220,7 +220,7 @@ bool adpcm_a_channel::clock()
//------------------------------------------------- //-------------------------------------------------
template<int NumOutputs> template<int NumOutputs>
void adpcm_a_channel::output(ymfm_output<NumOutputs> &output) const void adpcm_a_channel::output(ymfm_output<NumOutputs> &output)
{ {
// volume combines instrument and total levels // volume combines instrument and total levels
int vol = (m_regs.ch_instrument_level(m_choffs) ^ 0x1f) + (m_regs.total_level() ^ 0x3f); int vol = (m_regs.ch_instrument_level(m_choffs) ^ 0x1f) + (m_regs.total_level() ^ 0x3f);
@ -239,14 +239,18 @@ void adpcm_a_channel::output(ymfm_output<NumOutputs> &output) const
int16_t value = ((int16_t(m_accumulator << 4) * mul) >> shift) & ~3; int16_t value = ((int16_t(m_accumulator << 4) * mul) >> shift) & ~3;
// apply to left/right as appropriate // apply to left/right as appropriate
if (NumOutputs == 1 || m_regs.ch_pan_left(m_choffs)) if (NumOutputs == 1 || m_regs.ch_pan_left(m_choffs)) {
output.data[0] += value; output.data[0] += value;
if (NumOutputs > 1 && m_regs.ch_pan_right(m_choffs)) m_lastOut[0] = value;
}
if (NumOutputs > 1 && m_regs.ch_pan_right(m_choffs)) {
output.data[1] += value; output.data[1] += value;
m_lastOut[1] = value;
}
} }
template void adpcm_a_channel::output<1>(ymfm_output<1> &output) const; template void adpcm_a_channel::output<1>(ymfm_output<1> &output);
template void adpcm_a_channel::output<2>(ymfm_output<2> &output) const; template void adpcm_a_channel::output<2>(ymfm_output<2> &output);
//********************************************************* //*********************************************************
@ -528,7 +532,7 @@ void adpcm_b_channel::clock()
//------------------------------------------------- //-------------------------------------------------
template<int NumOutputs> template<int NumOutputs>
void adpcm_b_channel::output(ymfm_output<NumOutputs> &output, uint32_t rshift) const void adpcm_b_channel::output(ymfm_output<NumOutputs> &output, uint32_t rshift)
{ {
// mask out some channels for debug purposes // mask out some channels for debug purposes
if ((debug::GLOBAL_ADPCM_B_CHANNEL_MASK & 1) == 0) if ((debug::GLOBAL_ADPCM_B_CHANNEL_MASK & 1) == 0)
@ -541,10 +545,14 @@ void adpcm_b_channel::output(ymfm_output<NumOutputs> &output, uint32_t rshift) c
result = (result * int32_t(m_regs.level())) >> (8 + rshift); result = (result * int32_t(m_regs.level())) >> (8 + rshift);
// apply to left/right // apply to left/right
if (NumOutputs == 1 || m_regs.pan_left()) if (NumOutputs == 1 || m_regs.pan_left()) {
m_lastOut[0] = result;
output.data[0] += result; output.data[0] += result;
if (NumOutputs > 1 && m_regs.pan_right()) }
if (NumOutputs > 1 && m_regs.pan_right()) {
m_lastOut[1] = result;
output.data[1] += result; output.data[1] += result;
}
} }

View file

@ -146,7 +146,10 @@ public:
// return the computed output value, with panning applied // return the computed output value, with panning applied
template<int NumOutputs> template<int NumOutputs>
void output(ymfm_output<NumOutputs> &output) const; void output(ymfm_output<NumOutputs> &output);
// return the last output
int32_t get_last_out(int ch) { return m_lastOut[ch]; }
private: private:
// internal state // internal state
@ -158,6 +161,7 @@ private:
uint32_t m_curaddress; // current address uint32_t m_curaddress; // current address
int32_t m_accumulator; // accumulator int32_t m_accumulator; // accumulator
int32_t m_step_index; // index in the stepping table int32_t m_step_index; // index in the stepping table
int32_t m_lastOut[2]; // last output
adpcm_a_registers &m_regs; // reference to registers adpcm_a_registers &m_regs; // reference to registers
adpcm_a_engine &m_owner; // reference to our owner adpcm_a_engine &m_owner; // reference to our owner
}; };
@ -326,7 +330,7 @@ public:
// return the computed output value, with panning applied // return the computed output value, with panning applied
template<int NumOutputs> template<int NumOutputs>
void output(ymfm_output<NumOutputs> &output, uint32_t rshift) const; void output(ymfm_output<NumOutputs> &output, uint32_t rshift);
// return the status register // return the status register
uint8_t status() const { return m_status; } uint8_t status() const { return m_status; }
@ -337,6 +341,9 @@ public:
// handle special register writes // handle special register writes
void write(uint32_t regnum, uint8_t value); void write(uint32_t regnum, uint8_t value);
// return the last output
int32_t get_last_out(int ch) { return m_lastOut[ch]; }
private: private:
// helper - return the current address shift // helper - return the current address shift
uint32_t address_shift() const; uint32_t address_shift() const;
@ -361,6 +368,7 @@ private:
int32_t m_accumulator; // accumulator int32_t m_accumulator; // accumulator
int32_t m_prev_accum; // previous accumulator (for linear interp) int32_t m_prev_accum; // previous accumulator (for linear interp)
int32_t m_adpcm_step; // next forecast int32_t m_adpcm_step; // next forecast
int32_t m_lastOut[2]; // last output
adpcm_b_registers &m_regs; // reference to registers adpcm_b_registers &m_regs; // reference to registers
adpcm_b_engine &m_owner; // reference to our owner adpcm_b_engine &m_owner; // reference to our owner
}; };
@ -387,6 +395,9 @@ public:
template<int NumOutputs> template<int NumOutputs>
void output(ymfm_output<NumOutputs> &output, uint32_t rshift); void output(ymfm_output<NumOutputs> &output, uint32_t rshift);
// get last output
int32_t get_last_out(int ch) { return m_channel->get_last_out(ch); }
// read from the ADPCM-B registers // read from the ADPCM-B registers
uint32_t read(uint32_t regnum) { return m_channel->read(regnum); } uint32_t read(uint32_t regnum) { return m_channel->read(regnum); }

View file

@ -428,7 +428,15 @@ void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t l
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine(); ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
ymfm::ssg_engine::output_data ssgOut; ymfm::ssg_engine::output_data ssgOut;
ymfm::ymfm_output<2> adpcmOut;
ymfm::fm_channel<ymfm::opn_registers_base<true>>* fmChan[6];
ymfm::adpcm_a_channel* adpcmAChan[6];
for (int i=0; i<4; i++) {
fmChan[i]=fme->debug_channel(bchOffs[i]);
}
for (int i=0; i<6; i++) {
adpcmAChan[i]=aae->debug_channel(i);
}
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;
@ -457,8 +465,7 @@ void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t l
bufR[h]=os[1]; bufR[h]=os[1];
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
int ch=bchOffs[i]; oscBuf[i]->data[oscBuf[i]->needle++]=(fmChan[i]->debug_output(0)+fmChan[i]->debug_output(1));
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); ssge->get_last_out(ssgOut);
@ -467,14 +474,10 @@ void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t l
} }
for (int i=7; i<13; i++) { for (int i=7; i<13; i++) {
adpcmOut.clear(); oscBuf[i]->data[oscBuf[i]->needle++]=adpcmAChan[i-7]->get_last_out(0)+adpcmAChan[i-7]->get_last_out(1);
aae->debug_channel(i-7)->output<2>(adpcmOut);
oscBuf[i]->data[oscBuf[i]->needle++]=adpcmOut.data[0]+adpcmOut.data[1];
} }
adpcmOut.clear(); oscBuf[13]->data[oscBuf[13]->needle++]=abe->get_last_out(0)+abe->get_last_out(1);
abe->output(adpcmOut,1);
oscBuf[13]->data[oscBuf[13]->needle++]=adpcmOut.data[0]+adpcmOut.data[1];
} }
} }

View file

@ -408,7 +408,13 @@ void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine(); ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
ymfm::ssg_engine::output_data ssgOut; ymfm::ssg_engine::output_data ssgOut;
ymfm::ymfm_output<2> adpcmOut;
ymfm::fm_channel<ymfm::opn_registers_base<true>>* fmChan[6];
ymfm::adpcm_a_channel* adpcmAChan[6];
for (int i=0; i<6; i++) {
fmChan[i]=fme->debug_channel(i);
adpcmAChan[i]=aae->debug_channel(i);
}
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;
@ -436,8 +442,9 @@ 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++) { 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)); oscBuf[i]->data[oscBuf[i]->needle++]=(fmChan[i]->debug_output(0)+fmChan[i]->debug_output(1));
} }
ssge->get_last_out(ssgOut); ssge->get_last_out(ssgOut);
@ -446,14 +453,10 @@ void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t
} }
for (int i=9; i<15; i++) { for (int i=9; i<15; i++) {
adpcmOut.clear(); oscBuf[i]->data[oscBuf[i]->needle++]=adpcmAChan[i-9]->get_last_out(0)+adpcmAChan[i-9]->get_last_out(1);
aae->debug_channel(i-9)->output<2>(adpcmOut);
oscBuf[i]->data[oscBuf[i]->needle++]=adpcmOut.data[0]+adpcmOut.data[1];
} }
adpcmOut.clear(); oscBuf[15]->data[oscBuf[15]->needle++]=abe->get_last_out(0)+abe->get_last_out(1);
abe->output(adpcmOut,1);
oscBuf[15]->data[oscBuf[15]->needle++]=adpcmOut.data[0]+adpcmOut.data[1];
} }
} }

View file

@ -17,6 +17,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include <chrono>
#define _USE_MATH_DEFINES #define _USE_MATH_DEFINES
#include "dispatch.h" #include "dispatch.h"
#include "engine.h" #include "engine.h"
@ -262,6 +263,7 @@ int DivEngine::dispatchCmd(DivCommand c) {
} }
bool DivEngine::perSystemEffect(int ch, unsigned char effect, unsigned char effectVal) { bool DivEngine::perSystemEffect(int ch, unsigned char effect, unsigned char effectVal) {
<<<<<<< HEAD
switch (sysOfChan[ch]) { switch (sysOfChan[ch]) {
case DIV_SYSTEM_YM2612: case DIV_SYSTEM_YM2612:
case DIV_SYSTEM_YM2612_EXT: case DIV_SYSTEM_YM2612_EXT:
@ -599,391 +601,15 @@ bool DivEngine::perSystemEffect(int ch, unsigned char effect, unsigned char effe
return false; return false;
} }
return true; return true;
=======
if (sysDefs[sysOfChan[ch]]==NULL) return false;
return sysDefs[sysOfChan[ch]]->effectFunc(ch,effect,effectVal);
>>>>>>> 4c9b172b50a240efc37aec8bdd4a59972fbf10c4
} }
#define IS_YM2610 (sysOfChan[ch]==DIV_SYSTEM_YM2610 || sysOfChan[ch]==DIV_SYSTEM_YM2610_EXT || sysOfChan[ch]==DIV_SYSTEM_YM2610_FULL || sysOfChan[ch]==DIV_SYSTEM_YM2610_FULL_EXT || sysOfChan[ch]==DIV_SYSTEM_YM2610B || sysOfChan[ch]==DIV_SYSTEM_YM2610B_EXT)
#define IS_OPM_LIKE (sysOfChan[ch]==DIV_SYSTEM_YM2151 || sysOfChan[ch]==DIV_SYSTEM_OPZ)
bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char effectVal) { bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char effectVal) {
switch (sysOfChan[ch]) { if (sysDefs[sysOfChan[ch]]==NULL) return false;
case DIV_SYSTEM_YM2612: return sysDefs[sysOfChan[ch]]->postEffectFunc(ch,effect,effectVal);
case DIV_SYSTEM_YM2612_EXT:
case DIV_SYSTEM_YM2151:
case DIV_SYSTEM_YM2610:
case DIV_SYSTEM_YM2610_EXT:
case DIV_SYSTEM_YM2610_FULL:
case DIV_SYSTEM_YM2610_FULL_EXT:
case DIV_SYSTEM_YM2610B:
case DIV_SYSTEM_YM2610B_EXT:
case DIV_SYSTEM_OPZ:
switch (effect) {
case 0x10: // LFO or noise mode
if (IS_OPM_LIKE) {
dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_FREQ,ch,effectVal));
} else {
dispatchCmd(DivCommand(DIV_CMD_FM_LFO,ch,effectVal));
}
break;
case 0x11: // FB
dispatchCmd(DivCommand(DIV_CMD_FM_FB,ch,effectVal&7));
break;
case 0x12: // TL op1
dispatchCmd(DivCommand(DIV_CMD_FM_TL,ch,0,effectVal&0x7f));
break;
case 0x13: // TL op2
dispatchCmd(DivCommand(DIV_CMD_FM_TL,ch,1,effectVal&0x7f));
break;
case 0x14: // TL op3
dispatchCmd(DivCommand(DIV_CMD_FM_TL,ch,2,effectVal&0x7f));
break;
case 0x15: // TL op4
dispatchCmd(DivCommand(DIV_CMD_FM_TL,ch,3,effectVal&0x7f));
break;
case 0x16: // MULT
if ((effectVal>>4)>0 && (effectVal>>4)<5) {
dispatchCmd(DivCommand(DIV_CMD_FM_MULT,ch,(effectVal>>4)-1,effectVal&15));
}
break;
case 0x17: // arcade LFO
if (IS_OPM_LIKE) {
dispatchCmd(DivCommand(DIV_CMD_FM_LFO,ch,effectVal));
}
break;
case 0x18: // EXT or LFO waveform
if (IS_OPM_LIKE) {
dispatchCmd(DivCommand(DIV_CMD_FM_LFO_WAVE,ch,effectVal));
} else {
dispatchCmd(DivCommand(DIV_CMD_FM_EXTCH,ch,effectVal));
}
break;
case 0x19: // AR global
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,-1,effectVal&31));
break;
case 0x1a: // AR op1
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,0,effectVal&31));
break;
case 0x1b: // AR op2
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,1,effectVal&31));
break;
case 0x1c: // AR op3
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,2,effectVal&31));
break;
case 0x1d: // AR op4
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,3,effectVal&31));
break;
case 0x1e: // UNOFFICIAL: Arcade AM depth
dispatchCmd(DivCommand(DIV_CMD_FM_AM_DEPTH,ch,effectVal&127));
break;
case 0x1f: // UNOFFICIAL: Arcade PM depth
dispatchCmd(DivCommand(DIV_CMD_FM_PM_DEPTH,ch,effectVal&127));
break;
case 0x20: // Neo Geo PSG mode
if (IS_YM2610) {
dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_MODE,ch,effectVal));
}
break;
case 0x21: // Neo Geo PSG noise freq
if (IS_YM2610) {
dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_FREQ,ch,effectVal));
}
break;
case 0x22: // UNOFFICIAL: Neo Geo PSG envelope enable
if (IS_YM2610) {
dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_SET,ch,effectVal));
}
break;
case 0x23: // UNOFFICIAL: Neo Geo PSG envelope period low
if (IS_YM2610) {
dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_LOW,ch,effectVal));
}
break;
case 0x24: // UNOFFICIAL: Neo Geo PSG envelope period high
if (IS_YM2610) {
dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_HIGH,ch,effectVal));
}
break;
case 0x25: // UNOFFICIAL: Neo Geo PSG envelope slide up
if (IS_YM2610) {
dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_SLIDE,ch,-effectVal));
}
break;
case 0x26: // UNOFFICIAL: Neo Geo PSG envelope slide down
if (IS_YM2610) {
dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_SLIDE,ch,effectVal));
}
break;
case 0x29: // auto-envelope
if (IS_YM2610) {
dispatchCmd(DivCommand(DIV_CMD_AY_AUTO_ENVELOPE,ch,effectVal));
}
break;
default:
return false;
}
break;
case DIV_SYSTEM_OPLL:
case DIV_SYSTEM_OPLL_DRUMS:
case DIV_SYSTEM_VRC7:
switch (effect) {
case 0x11: // FB
dispatchCmd(DivCommand(DIV_CMD_FM_FB,ch,effectVal&7));
break;
case 0x12: // TL op1
dispatchCmd(DivCommand(DIV_CMD_FM_TL,ch,0,effectVal&0x3f));
break;
case 0x13: // TL op2
dispatchCmd(DivCommand(DIV_CMD_FM_TL,ch,1,effectVal&0x0f));
break;
case 0x16: // MULT
if ((effectVal>>4)>0 && (effectVal>>4)<3) {
dispatchCmd(DivCommand(DIV_CMD_FM_MULT,ch,(effectVal>>4)-1,effectVal&15));
}
break;
case 0x19: // AR global
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,-1,effectVal&31));
break;
case 0x1a: // AR op1
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,0,effectVal&31));
break;
case 0x1b: // AR op2
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,1,effectVal&31));
break;
default:
return false;
}
break;
case DIV_SYSTEM_OPL:
case DIV_SYSTEM_OPL2:
case DIV_SYSTEM_OPL3:
case DIV_SYSTEM_OPL_DRUMS:
case DIV_SYSTEM_OPL2_DRUMS:
case DIV_SYSTEM_OPL3_DRUMS:
switch (effect) {
case 0x10: // DAM
dispatchCmd(DivCommand(DIV_CMD_FM_LFO,ch,effectVal&1));
break;
case 0x11: // FB
dispatchCmd(DivCommand(DIV_CMD_FM_FB,ch,effectVal&7));
break;
case 0x12: // TL op1
dispatchCmd(DivCommand(DIV_CMD_FM_TL,ch,0,effectVal&0x3f));
break;
case 0x13: // TL op2
dispatchCmd(DivCommand(DIV_CMD_FM_TL,ch,1,effectVal&0x3f));
break;
case 0x14: // TL op3
dispatchCmd(DivCommand(DIV_CMD_FM_TL,ch,2,effectVal&0x3f));
break;
case 0x15: // TL op4
dispatchCmd(DivCommand(DIV_CMD_FM_TL,ch,3,effectVal&0x3f));
break;
case 0x16: // MULT
if ((effectVal>>4)>0 && (effectVal>>4)<5) {
dispatchCmd(DivCommand(DIV_CMD_FM_MULT,ch,(effectVal>>4)-1,effectVal&15));
}
break;
case 0x17: // DVB
dispatchCmd(DivCommand(DIV_CMD_FM_LFO,ch,2+(effectVal&1)));
break;
case 0x19: // AR global
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,-1,effectVal&15));
break;
case 0x1a: // AR op1
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,0,effectVal&15));
break;
case 0x1b: // AR op2
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,1,effectVal&15));
break;
case 0x1c: // AR op3
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,2,effectVal&15));
break;
case 0x1d: // AR op4
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,3,effectVal&15));
break;
default:
return false;
}
break;
case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580:
switch (effect) {
case 0x10: // select waveform
dispatchCmd(DivCommand(DIV_CMD_WAVE,ch,effectVal));
break;
case 0x11: // cutoff
dispatchCmd(DivCommand(DIV_CMD_C64_CUTOFF,ch,effectVal));
break;
case 0x12: // duty
dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_MODE,ch,effectVal));
break;
case 0x13: // resonance
dispatchCmd(DivCommand(DIV_CMD_C64_RESONANCE,ch,effectVal));
break;
case 0x14: // filter mode
dispatchCmd(DivCommand(DIV_CMD_C64_FILTER_MODE,ch,effectVal));
break;
case 0x15: // reset time
dispatchCmd(DivCommand(DIV_CMD_C64_RESET_TIME,ch,effectVal));
break;
case 0x1a: // reset mask
dispatchCmd(DivCommand(DIV_CMD_C64_RESET_MASK,ch,effectVal));
break;
case 0x1b: // cutoff reset
dispatchCmd(DivCommand(DIV_CMD_C64_FILTER_RESET,ch,effectVal));
break;
case 0x1c: // duty reset
dispatchCmd(DivCommand(DIV_CMD_C64_DUTY_RESET,ch,effectVal));
break;
case 0x1e: // extended
dispatchCmd(DivCommand(DIV_CMD_C64_EXTENDED,ch,effectVal));
break;
case 0x30: case 0x31: case 0x32: case 0x33:
case 0x34: case 0x35: case 0x36: case 0x37:
case 0x38: case 0x39: case 0x3a: case 0x3b:
case 0x3c: case 0x3d: case 0x3e: case 0x3f: // fine duty
dispatchCmd(DivCommand(DIV_CMD_C64_FINE_DUTY,ch,((effect&0x0f)<<8)|effectVal));
break;
case 0x40: case 0x41: case 0x42: case 0x43:
case 0x44: case 0x45: case 0x46: case 0x47: // fine cutoff
dispatchCmd(DivCommand(DIV_CMD_C64_FINE_CUTOFF,ch,((effect&0x07)<<8)|effectVal));
break;
default:
return false;
}
break;
case DIV_SYSTEM_AY8910:
case DIV_SYSTEM_AY8930:
switch (effect) {
case 0x12: // duty on 8930
dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_MODE,ch,0x10+(effectVal&15)));
break;
case 0x20: // mode
dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_MODE,ch,effectVal&15));
break;
case 0x21: // noise freq
dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_FREQ,ch,effectVal));
break;
case 0x22: // envelope enable
dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_SET,ch,effectVal));
break;
case 0x23: // envelope period low
dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_LOW,ch,effectVal));
break;
case 0x24: // envelope period high
dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_HIGH,ch,effectVal));
break;
case 0x25: // envelope slide up
dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_SLIDE,ch,-effectVal));
break;
case 0x26: // envelope slide down
dispatchCmd(DivCommand(DIV_CMD_AY_ENVELOPE_SLIDE,ch,effectVal));
break;
case 0x27: // noise and mask
dispatchCmd(DivCommand(DIV_CMD_AY_NOISE_MASK_AND,ch,effectVal));
break;
case 0x28: // noise or mask
dispatchCmd(DivCommand(DIV_CMD_AY_NOISE_MASK_OR,ch,effectVal));
break;
case 0x29: // auto-envelope
dispatchCmd(DivCommand(DIV_CMD_AY_AUTO_ENVELOPE,ch,effectVal));
break;
case 0x2d: // TEST
dispatchCmd(DivCommand(DIV_CMD_AY_IO_WRITE,ch,255,effectVal));
break;
case 0x2e: // I/O port A
dispatchCmd(DivCommand(DIV_CMD_AY_IO_WRITE,ch,0,effectVal));
break;
case 0x2f: // I/O port B
dispatchCmd(DivCommand(DIV_CMD_AY_IO_WRITE,ch,1,effectVal));
break;
default:
return false;
}
break;
case DIV_SYSTEM_SAA1099:
switch (effect) {
case 0x10: // select channel mode
dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_MODE,ch,effectVal));
break;
case 0x11: // set noise freq
dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_FREQ,ch,effectVal));
break;
case 0x12: // setup envelope
dispatchCmd(DivCommand(DIV_CMD_SAA_ENVELOPE,ch,effectVal));
break;
default:
return false;
}
break;
case DIV_SYSTEM_TIA:
switch (effect) {
case 0x10: // select waveform
dispatchCmd(DivCommand(DIV_CMD_WAVE,ch,effectVal));
break;
default:
return false;
}
break;
case DIV_SYSTEM_AMIGA:
switch (effect) {
case 0x10: // toggle filter
dispatchCmd(DivCommand(DIV_CMD_AMIGA_FILTER,ch,effectVal));
break;
case 0x11: // toggle AM
dispatchCmd(DivCommand(DIV_CMD_AMIGA_AM,ch,effectVal));
break;
case 0x12: // toggle PM
dispatchCmd(DivCommand(DIV_CMD_AMIGA_PM,ch,effectVal));
break;
default:
return false;
}
break;
case DIV_SYSTEM_SEGAPCM:
case DIV_SYSTEM_SEGAPCM_COMPAT:
switch (effect) {
case 0x20: // PCM frequency
dispatchCmd(DivCommand(DIV_CMD_SAMPLE_FREQ,ch,effectVal));
break;
default:
return false;
}
break;
case DIV_SYSTEM_LYNX:
if (effect>=0x30 && effect<0x40) {
int value = ((int)(effect&0x0f)<<8)|effectVal;
dispatchCmd(DivCommand(DIV_CMD_LYNX_LFSR_LOAD,ch,value));
break;
}
return false;
break;
case DIV_SYSTEM_X1_010:
switch (effect) {
case 0x20: // PCM frequency
dispatchCmd(DivCommand(DIV_CMD_SAMPLE_FREQ,ch,effectVal));
break;
case 0x22: // envelope mode
dispatchCmd(DivCommand(DIV_CMD_X1_010_ENVELOPE_MODE,ch,effectVal));
break;
case 0x23: // envelope period
dispatchCmd(DivCommand(DIV_CMD_X1_010_ENVELOPE_PERIOD,ch,effectVal));
break;
case 0x25: // envelope slide up
dispatchCmd(DivCommand(DIV_CMD_X1_010_ENVELOPE_SLIDE,ch,effectVal));
break;
case 0x26: // envelope slide down
dispatchCmd(DivCommand(DIV_CMD_X1_010_ENVELOPE_SLIDE,ch,-effectVal));
break;
case 0x29: // auto-envelope
dispatchCmd(DivCommand(DIV_CMD_X1_010_AUTO_ENVELOPE,ch,effectVal));
break;
default:
return false;
}
break;
default:
return false;
}
return true;
} }
void DivEngine::processRow(int i, bool afterDelay) { void DivEngine::processRow(int i, bool afterDelay) {
@ -1787,6 +1413,8 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
} }
got.bufsize=size; got.bufsize=size;
std::chrono::steady_clock::time_point ts_processBegin=std::chrono::steady_clock::now();
// process MIDI events (TODO: everything) // process MIDI events (TODO: everything)
if (output) if (output->midiIn) while (!output->midiIn->queue.empty()) { if (output) if (output->midiIn) while (!output->midiIn->queue.empty()) {
TAMidiMessage& msg=output->midiIn->queue.front(); TAMidiMessage& msg=output->midiIn->queue.front();
@ -2150,4 +1778,8 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
} }
} }
isBusy.unlock(); isBusy.unlock();
std::chrono::steady_clock::time_point ts_processEnd=std::chrono::steady_clock::now();
processTime=std::chrono::duration_cast<std::chrono::nanoseconds>(ts_processEnd-ts_processBegin).count();
} }

File diff suppressed because it is too large Load diff

View file

@ -345,6 +345,8 @@ void putDispatchChan(void* data, int chanNum, int type) {
ImGui::Text("- ins: %d",ch->ins); ImGui::Text("- ins: %d",ch->ins);
ImGui::Text("- sample: %d",ch->sample); ImGui::Text("- sample: %d",ch->sample);
ImGui::Text("- wave: %d",ch->wave); ImGui::Text("- wave: %d",ch->wave);
ImGui::Text("- VolMacroMax: %d",ch->volMacroMax);
ImGui::Text("- PanMacroMax: %d",ch->panMacroMax);
ImGui::Text("* PCM:"); ImGui::Text("* PCM:");
ImGui::Text(" - index: %d",ch->pcm.index); ImGui::Text(" - index: %d",ch->pcm.index);
ImGui::Text(" - freqOffs: %.6f",ch->pcm.freqOffs); ImGui::Text(" - freqOffs: %.6f",ch->pcm.freqOffs);

View file

@ -149,42 +149,95 @@ void FurnaceGUI::drawDebug() {
ImGui::Text("%d: <NULL!>",i); ImGui::Text("%d: <NULL!>",i);
continue; continue;
} }
ImGui::Text("%d: %s",i,sample->name.c_str()); if (ImGui::TreeNode(fmt::sprintf("%d: %s",i,sample->name).c_str())) {
ImGui::Indent(); ImGui::Text("rate: %d",sample->rate);
ImGui::Text("rate: %d",sample->rate); ImGui::Text("centerRate: %d",sample->centerRate);
ImGui::Text("centerRate: %d",sample->centerRate); ImGui::Text("loopStart: %d",sample->loopStart);
ImGui::Text("loopStart: %d",sample->loopStart); ImGui::Text("loopOffP: %d",sample->loopOffP);
ImGui::Text("loopOffP: %d",sample->loopOffP); ImGui::Text("depth: %d",sample->depth);
ImGui::Text("depth: %d",sample->depth); ImGui::Text("length8: %d",sample->length8);
ImGui::Text("length8: %d",sample->length8); ImGui::Text("length16: %d",sample->length16);
ImGui::Text("length16: %d",sample->length16); ImGui::Text("length1: %d",sample->length1);
ImGui::Text("length1: %d",sample->length1); ImGui::Text("lengthDPCM: %d",sample->lengthDPCM);
ImGui::Text("lengthDPCM: %d",sample->lengthDPCM); ImGui::Text("lengthQSoundA: %d",sample->lengthQSoundA);
ImGui::Text("lengthQSoundA: %d",sample->lengthQSoundA); ImGui::Text("lengthA: %d",sample->lengthA);
ImGui::Text("lengthA: %d",sample->lengthA); ImGui::Text("lengthB: %d",sample->lengthB);
ImGui::Text("lengthB: %d",sample->lengthB); ImGui::Text("lengthX68: %d",sample->lengthX68);
ImGui::Text("lengthX68: %d",sample->lengthX68); ImGui::Text("lengthBRR: %d",sample->lengthBRR);
ImGui::Text("lengthBRR: %d",sample->lengthBRR); ImGui::Text("lengthVOX: %d",sample->lengthVOX);
ImGui::Text("lengthVOX: %d",sample->lengthVOX);
ImGui::Text("off8: %x",sample->off8); ImGui::Text("off8: %x",sample->off8);
ImGui::Text("off16: %x",sample->off16); ImGui::Text("off16: %x",sample->off16);
ImGui::Text("off1: %x",sample->off1); ImGui::Text("off1: %x",sample->off1);
ImGui::Text("offDPCM: %x",sample->offDPCM); ImGui::Text("offDPCM: %x",sample->offDPCM);
ImGui::Text("offQSoundA: %x",sample->offQSoundA); ImGui::Text("offQSoundA: %x",sample->offQSoundA);
ImGui::Text("offA: %x",sample->offA); ImGui::Text("offA: %x",sample->offA);
ImGui::Text("offB: %x",sample->offB); ImGui::Text("offB: %x",sample->offB);
ImGui::Text("offX68: %x",sample->offX68); ImGui::Text("offX68: %x",sample->offX68);
ImGui::Text("offBRR: %x",sample->offBRR); ImGui::Text("offBRR: %x",sample->offBRR);
ImGui::Text("offVOX: %x",sample->offVOX); ImGui::Text("offVOX: %x",sample->offVOX);
ImGui::Text("offSegaPCM: %x",sample->offSegaPCM); ImGui::Text("offSegaPCM: %x",sample->offSegaPCM);
ImGui::Text("offQSound: %x",sample->offQSound); ImGui::Text("offQSound: %x",sample->offQSound);
ImGui::Text("offX1_010: %x",sample->offX1_010); ImGui::Text("offX1_010: %x",sample->offX1_010);
ImGui::Text("offES5506: %x",sample->offES5506); ImGui::Text("offES5506: %x",sample->offES5506);
ImGui::Text("offSU: %x",sample->offSU); ImGui::Text("offSU: %x",sample->offSU);
ImGui::Text("samples: %d",sample->samples); ImGui::Text("samples: %d",sample->samples);
ImGui::Unindent(); ImGui::TreePop();
}
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Oscilloscope Debug")) {
int c=0;
for (int i=0; i<e->song.systemLen; i++) {
DivSystem system=e->song.system[i];
if (e->getChannelCount(system)>0) {
if (ImGui::TreeNode(fmt::sprintf("%d: %s",i,e->getSystemName(system)).c_str())) {
if (ImGui::BeginTable("OscilloscopeTable",4,ImGuiTableFlags_Borders|ImGuiTableFlags_SizingStretchSame)) {
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text("Channel");
ImGui::TableNextColumn();
ImGui::Text("Follow");
ImGui::TableNextColumn();
ImGui::Text("Address");
ImGui::TableNextColumn();
ImGui::Text("Data");
for (int j=0; j<e->getChannelCount(system); j++, c++) {
ImGui::TableNextRow();
// channel
ImGui::TableNextColumn();
ImGui::Text("%d",j);
// follow
ImGui::TableNextColumn();
ImGui::Checkbox(fmt::sprintf("##%d_OSCFollow_%d",i,c).c_str(),&e->getOscBuffer(c)->follow);
// address
ImGui::TableNextColumn();
int needle=e->getOscBuffer(c)->follow?e->getOscBuffer(c)->needle:e->getOscBuffer(c)->followNeedle;
ImGui::BeginDisabled(e->getOscBuffer(c)->follow);
if (ImGui::InputInt(fmt::sprintf("##%d_OSCFollowNeedle_%d",i,c).c_str(),&needle,1,100)) {
e->getOscBuffer(c)->followNeedle=MIN(MAX(needle,0),65535);
}
ImGui::EndDisabled();
// data
ImGui::TableNextColumn();
ImGui::Text("%d",e->getOscBuffer(c)->data[needle]);
}
ImGui::EndTable();
}
ImGui::TreePop();
}
} else {
ImGui::Text("%d: <NULL!>",i);
continue;
}
} }
ImGui::TreePop(); ImGui::TreePop();
} }

File diff suppressed because it is too large Load diff

View file

@ -19,6 +19,7 @@
#include "gui.h" #include "gui.h"
#include <fmt/printf.h> #include <fmt/printf.h>
#include <imgui.h>
void FurnaceGUI::drawStats() { void FurnaceGUI::drawStats() {
if (nextWindow==GUI_WINDOW_STATS) { if (nextWindow==GUI_WINDOW_STATS) {
@ -28,6 +29,13 @@ void FurnaceGUI::drawStats() {
} }
if (!statsOpen) return; if (!statsOpen) return;
if (ImGui::Begin("Statistics",&statsOpen)) { if (ImGui::Begin("Statistics",&statsOpen)) {
size_t lastProcTime=e->processTime;
double maxGot=1000000000.0*(double)e->getAudioDescGot().bufsize/(double)e->getAudioDescGot().rate;
String procStr=fmt::sprintf("%.1f%%",100.0*((double)lastProcTime/(double)maxGot));
ImGui::Text("Audio load");
ImGui::SameLine();
ImGui::ProgressBar((double)lastProcTime/maxGot,ImVec2(-FLT_MIN,0),procStr.c_str());
ImGui::Separator();
for (int i=0; i<e->song.systemLen; i++) { for (int i=0; i<e->song.systemLen; i++) {
DivDispatch* dispatch=e->getDispatch(i); DivDispatch* dispatch=e->getDispatch(i);
for (int j=0; dispatch!=NULL && dispatch->getSampleMemCapacity(j)>0; j++) { for (int j=0; dispatch!=NULL && dispatch->getSampleMemCapacity(j)>0; j++) {