ESFM: optimize osc buf
This commit is contained in:
parent
cf4807b5d0
commit
b3b50bdb66
|
@ -427,18 +427,20 @@ struct DivSamplePos {
|
|||
constexpr size_t OSCBUF_PREC=(sizeof(size_t)>=8)?16:16;
|
||||
constexpr size_t OSCBUF_MASK=(UINTMAX_C(1)<<OSCBUF_PREC)-1;
|
||||
|
||||
#define putSampleIKnowWhatIAmDoing(_ob,_pos,_val) \
|
||||
_ob->data[_pos]=_val;
|
||||
|
||||
// the actual output of all DivDispatchOscBuffer instanced runs at 65536Hz.
|
||||
struct DivDispatchOscBuffer {
|
||||
size_t rate;
|
||||
size_t rateMul;
|
||||
unsigned int needle;
|
||||
unsigned short readNeedle;
|
||||
unsigned short followNeedle;
|
||||
unsigned short lastSample;
|
||||
//unsigned short lastSample;
|
||||
bool follow;
|
||||
short data[65536];
|
||||
|
||||
inline void putSample(size_t pos, short val) {
|
||||
inline void putSample(const size_t pos, const short val) {
|
||||
unsigned short realPos=((needle+pos*rateMul)>>OSCBUF_PREC);
|
||||
if (val==-1) {
|
||||
data[realPos]=0xfffe;
|
||||
|
@ -447,6 +449,16 @@ struct DivDispatchOscBuffer {
|
|||
//lastSample=val;
|
||||
data[realPos]=val;
|
||||
}
|
||||
/*
|
||||
inline void putSampleIKnowWhatIAmDoing(const unsigned short pos, const short val) {
|
||||
//unsigned short realPos=((needle+pos*rateMul)>>OSCBUF_PREC);
|
||||
if (val==-1) {
|
||||
data[pos]=0xfffe;
|
||||
return;
|
||||
}
|
||||
//lastSample=val;
|
||||
data[pos]=val;
|
||||
}*/
|
||||
inline void begin(unsigned short len) {
|
||||
size_t calc=(len*rateMul);
|
||||
unsigned short start=needle>>16;
|
||||
|
@ -473,8 +485,7 @@ struct DivDispatchOscBuffer {
|
|||
memset(data,-1,65536*sizeof(short));
|
||||
needle=0;
|
||||
readNeedle=0;
|
||||
followNeedle=0;
|
||||
lastSample=0;
|
||||
//lastSample=0;
|
||||
}
|
||||
void setRate(unsigned int r) {
|
||||
double rateMulD=65536.0/(double)r;
|
||||
|
@ -487,8 +498,7 @@ struct DivDispatchOscBuffer {
|
|||
rateMul(UINTMAX_C(1)<<OSCBUF_PREC),
|
||||
needle(0),
|
||||
readNeedle(0),
|
||||
followNeedle(0),
|
||||
lastSample(0),
|
||||
//lastSample(0),
|
||||
follow(true) {
|
||||
memset(data,-1,65536*sizeof(short));
|
||||
}
|
||||
|
|
|
@ -66,6 +66,46 @@ void DivPlatformESFM::acquire(short** buf, size_t len) {
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformESFM::acquireDirect(blip_buffer_t** bb, size_t off, size_t len) {
|
||||
thread_local short o[2];
|
||||
unsigned int sharedNeedlePos=oscBuf[0]->needle;
|
||||
for (int i=0; i<18; i++) {
|
||||
oscBuf[i]->begin(len);
|
||||
}
|
||||
size_t pos=off;
|
||||
for (size_t h=0; h<len; h++) {
|
||||
if (!writes.empty()) {
|
||||
QueuedWrite& w=writes.front();
|
||||
ESFM_write_reg_buffered_fast(&chip,w.addr,w.val);
|
||||
if (w.addr<ESFM_REG_POOL_SIZE) {
|
||||
regPool[w.addr]=w.val;
|
||||
}
|
||||
writes.pop();
|
||||
}
|
||||
|
||||
ESFM_generate(&chip,o);
|
||||
const unsigned int shiftedNeedlePos=sharedNeedlePos>>OSCBUF_PREC;
|
||||
for (int c=0; c<18; c++) {
|
||||
putSampleIKnowWhatIAmDoing(oscBuf[c],shiftedNeedlePos,ESFM_get_channel_output_native(&chip,c));
|
||||
}
|
||||
sharedNeedlePos+=oscBuf[0]->rateMul;
|
||||
|
||||
if (o[0]!=oldOut[0]) {
|
||||
blip_add_delta(bb[0],pos,oldOut[0]-o[0]);
|
||||
oldOut[0]=o[0];
|
||||
}
|
||||
if (o[1]!=oldOut[1]) {
|
||||
blip_add_delta(bb[1],pos,oldOut[1]-o[1]);
|
||||
oldOut[1]=o[1];
|
||||
}
|
||||
|
||||
pos++;
|
||||
}
|
||||
for (int i=0; i<18; i++) {
|
||||
oscBuf[i]->end(len);
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformESFM::tick(bool sysTick) {
|
||||
for (int i=0; i<18; i++) {
|
||||
chan[i].std.next();
|
||||
|
@ -1024,6 +1064,9 @@ void DivPlatformESFM::reset() {
|
|||
chan[i].vol=0x3f;
|
||||
chan[i].outVol=0x3f;
|
||||
}
|
||||
|
||||
oldOut[0]=0;
|
||||
oldOut[1]=0;
|
||||
}
|
||||
|
||||
int DivPlatformESFM::getOutputCount() {
|
||||
|
@ -1038,6 +1081,10 @@ bool DivPlatformESFM::keyOffAffectsPorta(int ch) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool DivPlatformESFM::hasAcquireDirect() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DivPlatformESFM::getLegacyAlwaysSetVolume() {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -120,6 +120,7 @@ class DivPlatformESFM: public DivDispatch {
|
|||
};
|
||||
FixedQueue<QueuedWrite,2048> writes;
|
||||
esfm_chip chip;
|
||||
short oldOut[2];
|
||||
bool isFast;
|
||||
|
||||
unsigned char regPool[ESFM_REG_POOL_SIZE];
|
||||
|
@ -180,6 +181,7 @@ class DivPlatformESFM: public DivDispatch {
|
|||
|
||||
public:
|
||||
void acquire(short** buf, size_t len);
|
||||
void acquireDirect(blip_buffer_t** bb, size_t off, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
DivMacroInt* getChanMacroInt(int ch);
|
||||
|
@ -194,6 +196,7 @@ class DivPlatformESFM: public DivDispatch {
|
|||
void muteChannel(int ch, bool mute);
|
||||
bool keyOffAffectsArp(int ch);
|
||||
bool keyOffAffectsPorta(int ch);
|
||||
bool hasAcquireDirect();
|
||||
bool getLegacyAlwaysSetVolume();
|
||||
void toggleRegisterDump(bool enable);
|
||||
void notifyInsChange(int ins);
|
||||
|
|
|
@ -276,10 +276,9 @@ void FurnaceGUI::drawDebug() {
|
|||
ImGui::Checkbox(fmt::sprintf("##%d_OSCFollow_%d",i,c).c_str(),&oscBuf->follow);
|
||||
// address
|
||||
ImGui::TableNextColumn();
|
||||
int needle=oscBuf->follow?oscBuf->needle:oscBuf->followNeedle;
|
||||
int needle=oscBuf->needle;
|
||||
ImGui::BeginDisabled(oscBuf->follow);
|
||||
if (ImGui::InputInt(fmt::sprintf("##%d_OSCFollowNeedle_%d",i,c).c_str(),&needle,1,100)) {
|
||||
oscBuf->followNeedle=MIN(MAX(needle,0),65535);
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
// data
|
||||
|
|
Loading…
Reference in a new issue