workPool: don't use std::function

it's kinda slow
This commit is contained in:
tildearrow 2023-09-07 00:16:47 -05:00
parent 084cbcb168
commit 9b276e80f8
7 changed files with 45 additions and 20 deletions

View file

@ -197,6 +197,10 @@ struct DivDispatchContainer {
bool lowQuality, dcOffCompensation; bool lowQuality, dcOffCompensation;
double rateMemory; double rateMemory;
// used in multi-thread
int cycles;
unsigned int size;
void setRates(double gotRate); void setRates(double gotRate);
void setQuality(bool lowQual); void setQuality(bool lowQual);
void grow(size_t size); void grow(size_t size);
@ -215,7 +219,9 @@ struct DivDispatchContainer {
lastAvail(0), lastAvail(0),
lowQuality(false), lowQuality(false),
dcOffCompensation(false), dcOffCompensation(false),
rateMemory(0.0) { rateMemory(0.0),
cycles(0),
size(0) {
memset(bb,0,DIV_MAX_OUTPUTS*sizeof(blip_buffer_t*)); memset(bb,0,DIV_MAX_OUTPUTS*sizeof(blip_buffer_t*));
memset(temp,0,DIV_MAX_OUTPUTS*sizeof(int)); memset(temp,0,DIV_MAX_OUTPUTS*sizeof(int));
memset(prevSample,0,DIV_MAX_OUTPUTS*sizeof(int)); memset(prevSample,0,DIV_MAX_OUTPUTS*sizeof(int));

View file

@ -1760,6 +1760,13 @@ void DivEngine::runMidiTime(int totalCycles) {
} }
} }
void _runDispatch1(void* d) {
}
void _runDispatch2(void* d) {
}
void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size) { void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size) {
lastNBIns=inChans; lastNBIns=inChans;
lastNBOuts=outChans; lastNBOuts=outChans;
@ -2066,9 +2073,11 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
// 5. tick the clock and fill buffers as needed // 5. tick the clock and fill buffers as needed
if (cycles<runLeftG) { if (cycles<runLeftG) {
for (int i=0; i<song.systemLen; i++) { for (int i=0; i<song.systemLen; i++) {
renderPool->push([this,size](void* d) { disCont[i].cycles=cycles;
disCont[i].size=size;
renderPool->push([](void* d) {
DivDispatchContainer* dc=(DivDispatchContainer*)d; DivDispatchContainer* dc=(DivDispatchContainer*)d;
int total=(cycles*dc->runtotal)/(size<<MASTER_CLOCK_PREC); int total=(dc->cycles*dc->runtotal)/(dc->size<<MASTER_CLOCK_PREC);
dc->acquire(dc->runPos,total); dc->acquire(dc->runPos,total);
dc->runLeft-=total; dc->runLeft-=total;
dc->runPos+=total; dc->runPos+=total;

View file

@ -71,7 +71,7 @@ void DivWorkThread::run() {
} }
} }
bool DivWorkThread::assign(const std::function<void(void*)>& what, void* arg) { bool DivWorkThread::assign(void (*what)(void*), void* arg) {
lock.lock(); lock.lock();
if (tasks.size()>=30) { if (tasks.size()>=30) {
lock.unlock(); lock.unlock();
@ -105,7 +105,7 @@ void DivWorkThread::init(DivWorkPool* p) {
thread=new std::thread(_workThread,this); thread=new std::thread(_workThread,this);
} }
void DivWorkPool::push(const std::function<void(void*)>& what, void* arg) { void DivWorkPool::push(void (*what)(void*), void* arg) {
// if no work threads, just execute // if no work threads, just execute
if (!threaded) { if (!threaded) {
what(arg); what(arg);

View file

@ -31,9 +31,9 @@
class DivWorkPool; class DivWorkPool;
struct DivPendingTask { struct DivPendingTask {
std::function<void(void*)> func; void (*func)(void*);
void* funcArg; void* funcArg;
DivPendingTask(std::function<void(void*)> f, void* arg): DivPendingTask(void (*f)(void*), void* arg):
func(f), func(f),
funcArg(arg) {} funcArg(arg) {}
DivPendingTask(): DivPendingTask():
@ -52,7 +52,7 @@ struct DivWorkThread {
bool promiseAlreadySet; bool promiseAlreadySet;
void run(); void run();
bool assign(const std::function<void(void*)>& what, void* arg); bool assign(void (*what)(void*), void* arg);
void wait(); void wait();
bool busy(); bool busy();
void finish(); void finish();
@ -82,7 +82,7 @@ class DivWorkPool {
* push a new job to this work pool. * push a new job to this work pool.
* if all work threads are busy, this will block until one is free. * if all work threads are busy, this will block until one is free.
*/ */
void push(const std::function<void(void*)>& what, void* arg); void push(void (*what)(void*), void* arg);
/** /**
* check whether this work pool is busy. * check whether this work pool is busy.

View file

@ -60,7 +60,7 @@ float FurnaceGUI::computeGradPos(int type, int chan) {
return 1.0f; return 1.0f;
break; break;
case GUI_OSCREF_FREQUENCY: case GUI_OSCREF_FREQUENCY:
return chanOscPitch[chan]; return chanOscChan[chan].pitch;
break; break;
case GUI_OSCREF_VOLUME: case GUI_OSCREF_VOLUME:
return chanOscVol[chan]; return chanOscVol[chan];
@ -416,10 +416,11 @@ void FurnaceGUI::drawChanOsc() {
} }
if (fft_->ready && e->isRunning()) { if (fft_->ready && e->isRunning()) {
chanOscWorkPool->push([this](void* fft_v) { fft_->windowSize=chanOscWindowSize;
fft_->waveCorr=chanOscWaveCorr;
chanOscWorkPool->push([](void* fft_v) {
ChanOscStatus* fft=(ChanOscStatus*)fft_v; ChanOscStatus* fft=(ChanOscStatus*)fft_v;
DivDispatchOscBuffer* buf=fft->relatedBuf; DivDispatchOscBuffer* buf=fft->relatedBuf;
int ch=fft->relatedCh;
// the STRATEGY // the STRATEGY
// 1. FFT of windowed signal // 1. FFT of windowed signal
@ -433,7 +434,7 @@ void FurnaceGUI::drawChanOsc() {
// initialization // initialization
double phase=0.0; double phase=0.0;
int displaySize=(float)(buf->rate)*(chanOscWindowSize/1000.0f); int displaySize=(float)(buf->rate)*(fft->windowSize/1000.0f);
fft->loudEnough=false; fft->loudEnough=false;
fft->needle=buf->needle; fft->needle=buf->needle;
@ -493,7 +494,7 @@ void FurnaceGUI::drawChanOsc() {
// did we find the period size? // did we find the period size?
if (fft->waveLen<(FURNACE_FFT_SIZE-32)) { if (fft->waveLen<(FURNACE_FFT_SIZE-32)) {
// we got pitch // we got pitch
chanOscPitch[ch]=pow(1.0-(fft->waveLen/(double)(FURNACE_FFT_SIZE>>1)),4.0); fft->pitch=pow(1.0-(fft->waveLen/(double)(FURNACE_FFT_SIZE>>1)),4.0);
fft->waveLen*=(double)displaySize*2.0/(double)FURNACE_FFT_SIZE; fft->waveLen*=(double)displaySize*2.0/(double)FURNACE_FFT_SIZE;
@ -511,7 +512,7 @@ void FurnaceGUI::drawChanOsc() {
// calculate and lock into phase // calculate and lock into phase
phase=(0.5+(atan2(dft[1],dft[0])/(2.0*M_PI))); phase=(0.5+(atan2(dft[1],dft[0])/(2.0*M_PI)));
if (chanOscWaveCorr) { if (fft->waveCorr) {
fft->needle-=phase*fft->waveLen; fft->needle-=phase*fft->waveLen;
} }
} }

View file

@ -1097,7 +1097,9 @@ float FurnaceGUI::calcBPM(const DivGroovePattern& speeds, float hz, int vN, int
void FurnaceGUI::play(int row) { void FurnaceGUI::play(int row) {
memset(chanOscVol,0,DIV_MAX_CHANS*sizeof(float)); memset(chanOscVol,0,DIV_MAX_CHANS*sizeof(float));
memset(chanOscPitch,0,DIV_MAX_CHANS*sizeof(float)); for (int i=0; i<DIV_MAX_CHANS; i++) {
chanOscChan[i].pitch=0.0f;
}
memset(chanOscBright,0,DIV_MAX_CHANS*sizeof(float)); memset(chanOscBright,0,DIV_MAX_CHANS*sizeof(float));
e->walkSong(loopOrder,loopRow,loopEnd); e->walkSong(loopOrder,loopRow,loopEnd);
memset(lastIns,-1,sizeof(int)*DIV_MAX_CHANS); memset(lastIns,-1,sizeof(int)*DIV_MAX_CHANS);
@ -3811,7 +3813,9 @@ bool FurnaceGUI::loop() {
if (!e->isRunning()) { if (!e->isRunning()) {
activeNotes.clear(); activeNotes.clear();
memset(chanOscVol,0,DIV_MAX_CHANS*sizeof(float)); memset(chanOscVol,0,DIV_MAX_CHANS*sizeof(float));
memset(chanOscPitch,0,DIV_MAX_CHANS*sizeof(float)); for (int i=0; i<DIV_MAX_CHANS; i++) {
chanOscChan[i].pitch=0.0f;
}
memset(chanOscBright,0,DIV_MAX_CHANS*sizeof(float)); memset(chanOscBright,0,DIV_MAX_CHANS*sizeof(float));
e->synchronized([this]() { e->synchronized([this]() {
@ -7417,7 +7421,9 @@ FurnaceGUI::FurnaceGUI():
memset(chanOscLP0,0,sizeof(float)*DIV_MAX_CHANS); memset(chanOscLP0,0,sizeof(float)*DIV_MAX_CHANS);
memset(chanOscLP1,0,sizeof(float)*DIV_MAX_CHANS); memset(chanOscLP1,0,sizeof(float)*DIV_MAX_CHANS);
memset(chanOscVol,0,sizeof(float)*DIV_MAX_CHANS); memset(chanOscVol,0,sizeof(float)*DIV_MAX_CHANS);
memset(chanOscPitch,0,sizeof(float)*DIV_MAX_CHANS); for (int i=0; i<DIV_MAX_CHANS; i++) {
chanOscChan[i].pitch=0.0f;
}
memset(chanOscBright,0,sizeof(float)*DIV_MAX_CHANS); memset(chanOscBright,0,sizeof(float)*DIV_MAX_CHANS);
memset(lastCorrPos,0,sizeof(short)*DIV_MAX_CHANS); memset(lastCorrPos,0,sizeof(short)*DIV_MAX_CHANS);

View file

@ -2061,7 +2061,6 @@ class FurnaceGUI {
float chanOscLP0[DIV_MAX_CHANS]; float chanOscLP0[DIV_MAX_CHANS];
float chanOscLP1[DIV_MAX_CHANS]; float chanOscLP1[DIV_MAX_CHANS];
float chanOscVol[DIV_MAX_CHANS]; float chanOscVol[DIV_MAX_CHANS];
float chanOscPitch[DIV_MAX_CHANS];
float chanOscBright[DIV_MAX_CHANS]; float chanOscBright[DIV_MAX_CHANS];
unsigned short lastNeedlePos[DIV_MAX_CHANS]; unsigned short lastNeedlePos[DIV_MAX_CHANS];
unsigned short lastCorrPos[DIV_MAX_CHANS]; unsigned short lastCorrPos[DIV_MAX_CHANS];
@ -2074,8 +2073,9 @@ class FurnaceGUI {
double inBufPosFrac; double inBufPosFrac;
double waveLen; double waveLen;
int waveLenBottom, waveLenTop, relatedCh; int waveLenBottom, waveLenTop, relatedCh;
float pitch, windowSize;
unsigned short needle; unsigned short needle;
bool ready, loudEnough; bool ready, loudEnough, waveCorr;
fftw_plan plan; fftw_plan plan;
fftw_plan planI; fftw_plan planI;
ChanOscStatus(): ChanOscStatus():
@ -2089,9 +2089,12 @@ class FurnaceGUI {
waveLenBottom(0), waveLenBottom(0),
waveLenTop(0), waveLenTop(0),
relatedCh(0), relatedCh(0),
pitch(0.0f),
windowSize(1.0f),
needle(0), needle(0),
ready(false), ready(false),
loudEnough(false), loudEnough(false),
waveCorr(false),
plan(NULL), plan(NULL),
planI(NULL) {} planI(NULL) {}
} chanOscChan[DIV_MAX_CHANS]; } chanOscChan[DIV_MAX_CHANS];