improved mutex locking - less xruns when seeking

especially in JACK and macOS
This commit is contained in:
tildearrow 2022-03-23 21:38:28 -05:00
parent 11d9ce3f87
commit 711b60d454
5 changed files with 147 additions and 134 deletions

View file

@ -437,25 +437,25 @@ bool DivEngine::haltAudioFile() {
} }
void DivEngine::notifyInsChange(int ins) { void DivEngine::notifyInsChange(int ins) {
isBusy.lock(); BUSY_BEGIN;
for (int i=0; i<song.systemLen; i++) { for (int i=0; i<song.systemLen; i++) {
disCont[i].dispatch->notifyInsChange(ins); disCont[i].dispatch->notifyInsChange(ins);
} }
isBusy.unlock(); BUSY_END;
} }
void DivEngine::notifyWaveChange(int wave) { void DivEngine::notifyWaveChange(int wave) {
isBusy.lock(); BUSY_BEGIN;
for (int i=0; i<song.systemLen; i++) { for (int i=0; i<song.systemLen; i++) {
disCont[i].dispatch->notifyWaveChange(wave); disCont[i].dispatch->notifyWaveChange(wave);
} }
isBusy.unlock(); BUSY_END;
} }
void DivEngine::renderSamplesP() { void DivEngine::renderSamplesP() {
isBusy.lock(); BUSY_BEGIN;
renderSamples(); renderSamples();
isBusy.unlock(); BUSY_END;
} }
void DivEngine::renderSamples() { void DivEngine::renderSamples() {
@ -583,7 +583,7 @@ void DivEngine::renderSamples() {
void DivEngine::createNew(const int* description) { void DivEngine::createNew(const int* description) {
quitDispatch(); quitDispatch();
isBusy.lock(); BUSY_BEGIN;
saveLock.lock(); saveLock.lock();
song.unload(); song.unload();
song=DivSong(); song=DivSong();
@ -604,27 +604,27 @@ void DivEngine::createNew(const int* description) {
recalcChans(); recalcChans();
renderSamples(); renderSamples();
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
initDispatch(); initDispatch();
isBusy.lock(); BUSY_BEGIN;
reset(); reset();
isBusy.unlock(); BUSY_END;
} }
void DivEngine::changeSystem(int index, DivSystem which) { void DivEngine::changeSystem(int index, DivSystem which) {
quitDispatch(); quitDispatch();
isBusy.lock(); BUSY_BEGIN;
saveLock.lock(); saveLock.lock();
song.system[index]=which; song.system[index]=which;
song.systemFlags[index]=0; song.systemFlags[index]=0;
recalcChans(); recalcChans();
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
initDispatch(); initDispatch();
isBusy.lock(); BUSY_BEGIN;
renderSamples(); renderSamples();
reset(); reset();
isBusy.unlock(); BUSY_END;
} }
bool DivEngine::addSystem(DivSystem which) { bool DivEngine::addSystem(DivSystem which) {
@ -638,7 +638,7 @@ bool DivEngine::addSystem(DivSystem which) {
return false; return false;
} }
quitDispatch(); quitDispatch();
isBusy.lock(); BUSY_BEGIN;
saveLock.lock(); saveLock.lock();
song.system[song.systemLen]=which; song.system[song.systemLen]=which;
song.systemVol[song.systemLen]=64; song.systemVol[song.systemLen]=64;
@ -646,12 +646,12 @@ bool DivEngine::addSystem(DivSystem which) {
song.systemFlags[song.systemLen++]=0; song.systemFlags[song.systemLen++]=0;
recalcChans(); recalcChans();
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
initDispatch(); initDispatch();
isBusy.lock(); BUSY_BEGIN;
renderSamples(); renderSamples();
reset(); reset();
isBusy.unlock(); BUSY_END;
return true; return true;
} }
@ -665,7 +665,7 @@ bool DivEngine::removeSystem(int index) {
return false; return false;
} }
quitDispatch(); quitDispatch();
isBusy.lock(); BUSY_BEGIN;
saveLock.lock(); saveLock.lock();
song.system[index]=DIV_SYSTEM_NULL; song.system[index]=DIV_SYSTEM_NULL;
song.systemLen--; song.systemLen--;
@ -674,27 +674,27 @@ bool DivEngine::removeSystem(int index) {
} }
recalcChans(); recalcChans();
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
initDispatch(); initDispatch();
isBusy.lock(); BUSY_BEGIN;
renderSamples(); renderSamples();
reset(); reset();
isBusy.unlock(); BUSY_END;
return true; return true;
} }
void DivEngine::poke(int sys, unsigned int addr, unsigned short val) { void DivEngine::poke(int sys, unsigned int addr, unsigned short val) {
if (sys<0 || sys>=song.systemLen) return; if (sys<0 || sys>=song.systemLen) return;
isBusy.lock(); BUSY_BEGIN;
disCont[sys].dispatch->poke(addr,val); disCont[sys].dispatch->poke(addr,val);
isBusy.unlock(); BUSY_END;
} }
void DivEngine::poke(int sys, std::vector<DivRegWrite>& wlist) { void DivEngine::poke(int sys, std::vector<DivRegWrite>& wlist) {
if (sys<0 || sys>=song.systemLen) return; if (sys<0 || sys>=song.systemLen) return;
isBusy.lock(); BUSY_BEGIN;
disCont[sys].dispatch->poke(wlist); disCont[sys].dispatch->poke(wlist);
isBusy.unlock(); BUSY_END;
} }
String DivEngine::getLastError() { String DivEngine::getLastError() {
@ -753,13 +753,13 @@ void DivEngine::enableCommandStream(bool enable) {
} }
void DivEngine::getCommandStream(std::vector<DivCommand>& where) { void DivEngine::getCommandStream(std::vector<DivCommand>& where) {
isBusy.lock(); BUSY_BEGIN;
where.clear(); where.clear();
for (DivCommand& i: cmdStream) { for (DivCommand& i: cmdStream) {
where.push_back(i); where.push_back(i);
} }
cmdStream.clear(); cmdStream.clear();
isBusy.unlock(); BUSY_END;
} }
void DivEngine::playSub(bool preserveDrift, int goalRow) { void DivEngine::playSub(bool preserveDrift, int goalRow) {
@ -834,7 +834,7 @@ int DivEngine::calcFreq(int base, int pitch, bool period, int octave) {
} }
void DivEngine::play() { void DivEngine::play() {
isBusy.lock(); BUSY_BEGIN_SOFT;
sPreview.sample=-1; sPreview.sample=-1;
sPreview.wave=-1; sPreview.wave=-1;
sPreview.pos=0; sPreview.pos=0;
@ -847,11 +847,11 @@ void DivEngine::play() {
for (int i=0; i<DIV_MAX_CHANS; i++) { for (int i=0; i<DIV_MAX_CHANS; i++) {
keyHit[i]=false; keyHit[i]=false;
} }
isBusy.unlock(); BUSY_END;
} }
void DivEngine::playToRow(int row) { void DivEngine::playToRow(int row) {
isBusy.lock(); BUSY_BEGIN_SOFT;
sPreview.sample=-1; sPreview.sample=-1;
sPreview.wave=-1; sPreview.wave=-1;
sPreview.pos=0; sPreview.pos=0;
@ -860,25 +860,27 @@ void DivEngine::playToRow(int row) {
for (int i=0; i<DIV_MAX_CHANS; i++) { for (int i=0; i<DIV_MAX_CHANS; i++) {
keyHit[i]=false; keyHit[i]=false;
} }
isBusy.unlock(); BUSY_END;
} }
void DivEngine::stepOne(int row) { void DivEngine::stepOne(int row) {
isBusy.lock();
if (!isPlaying()) { if (!isPlaying()) {
BUSY_BEGIN_SOFT;
freelance=false; freelance=false;
playSub(false,row); playSub(false,row);
for (int i=0; i<DIV_MAX_CHANS; i++) { for (int i=0; i<DIV_MAX_CHANS; i++) {
keyHit[i]=false; keyHit[i]=false;
} }
} else {
BUSY_BEGIN;
} }
stepPlay=2; stepPlay=2;
ticks=1; ticks=1;
isBusy.unlock(); BUSY_END;
} }
void DivEngine::stop() { void DivEngine::stop() {
isBusy.lock(); BUSY_BEGIN;
freelance=false; freelance=false;
playing=false; playing=false;
extValuePresent=false; extValuePresent=false;
@ -890,27 +892,27 @@ void DivEngine::stop() {
for (int i=0; i<song.systemLen; i++) { for (int i=0; i<song.systemLen; i++) {
disCont[i].dispatch->notifyPlaybackStop(); disCont[i].dispatch->notifyPlaybackStop();
} }
isBusy.unlock(); BUSY_END;
} }
void DivEngine::halt() { void DivEngine::halt() {
isBusy.lock(); BUSY_BEGIN;
halted=true; halted=true;
isBusy.unlock(); BUSY_END;
} }
void DivEngine::resume() { void DivEngine::resume() {
isBusy.lock(); BUSY_BEGIN;
halted=false; halted=false;
haltOn=DIV_HALT_NONE; haltOn=DIV_HALT_NONE;
isBusy.unlock(); BUSY_END;
} }
void DivEngine::haltWhen(DivHaltPositions when) { void DivEngine::haltWhen(DivHaltPositions when) {
isBusy.lock(); BUSY_BEGIN;
halted=false; halted=false;
haltOn=when; haltOn=when;
isBusy.unlock(); BUSY_END;
} }
bool DivEngine::isHalted() { bool DivEngine::isHalted() {
@ -966,9 +968,9 @@ void DivEngine::reset() {
} }
void DivEngine::syncReset() { void DivEngine::syncReset() {
isBusy.lock(); BUSY_BEGIN;
reset(); reset();
isBusy.unlock(); BUSY_END;
} }
const int sampleRates[6]={ const int sampleRates[6]={
@ -1024,11 +1026,11 @@ int DivEngine::getEffectiveSampleRate(int rate) {
} }
void DivEngine::previewSample(int sample, int note) { void DivEngine::previewSample(int sample, int note) {
isBusy.lock(); BUSY_BEGIN;
if (sample<0 || sample>=(int)song.sample.size()) { if (sample<0 || sample>=(int)song.sample.size()) {
sPreview.sample=-1; sPreview.sample=-1;
sPreview.pos=0; sPreview.pos=0;
isBusy.unlock(); BUSY_END;
return; return;
} }
blip_clear(samp_bb); blip_clear(samp_bb);
@ -1043,26 +1045,26 @@ void DivEngine::previewSample(int sample, int note) {
sPreview.pos=0; sPreview.pos=0;
sPreview.sample=sample; sPreview.sample=sample;
sPreview.wave=-1; sPreview.wave=-1;
isBusy.unlock(); BUSY_END;
} }
void DivEngine::stopSamplePreview() { void DivEngine::stopSamplePreview() {
isBusy.lock(); BUSY_BEGIN;
sPreview.sample=-1; sPreview.sample=-1;
sPreview.pos=0; sPreview.pos=0;
isBusy.unlock(); BUSY_END;
} }
void DivEngine::previewWave(int wave, int note) { void DivEngine::previewWave(int wave, int note) {
isBusy.lock(); BUSY_BEGIN;
if (wave<0 || wave>=(int)song.wave.size()) { if (wave<0 || wave>=(int)song.wave.size()) {
sPreview.wave=-1; sPreview.wave=-1;
sPreview.pos=0; sPreview.pos=0;
isBusy.unlock(); BUSY_END;
return; return;
} }
if (song.wave[wave]->len<=0) { if (song.wave[wave]->len<=0) {
isBusy.unlock(); BUSY_END;
return; return;
} }
blip_clear(samp_bb); blip_clear(samp_bb);
@ -1073,14 +1075,14 @@ void DivEngine::previewWave(int wave, int note) {
sPreview.pos=0; sPreview.pos=0;
sPreview.sample=-1; sPreview.sample=-1;
sPreview.wave=wave; sPreview.wave=wave;
isBusy.unlock(); BUSY_END;
} }
void DivEngine::stopWavePreview() { void DivEngine::stopWavePreview() {
isBusy.lock(); BUSY_BEGIN;
sPreview.wave=-1; sPreview.wave=-1;
sPreview.pos=0; sPreview.pos=0;
isBusy.unlock(); BUSY_END;
} }
String DivEngine::getConfigPath() { String DivEngine::getConfigPath() {
@ -1135,9 +1137,9 @@ bool DivEngine::getRepeatPattern() {
} }
void DivEngine::setRepeatPattern(bool value) { void DivEngine::setRepeatPattern(bool value) {
isBusy.lock(); BUSY_BEGIN;
repeatPattern=value; repeatPattern=value;
isBusy.unlock(); BUSY_END;
} }
bool DivEngine::hasExtValue() { bool DivEngine::hasExtValue() {
@ -1177,7 +1179,7 @@ void DivEngine::toggleSolo(int chan) {
} }
} }
} }
isBusy.lock(); BUSY_BEGIN;
if (!solo) { if (!solo) {
for (int i=0; i<chans; i++) { for (int i=0; i<chans; i++) {
isMuted[i]=(i!=chan); isMuted[i]=(i!=chan);
@ -1193,31 +1195,31 @@ void DivEngine::toggleSolo(int chan) {
} }
} }
} }
isBusy.unlock(); BUSY_END;
} }
void DivEngine::muteChannel(int chan, bool mute) { void DivEngine::muteChannel(int chan, bool mute) {
isBusy.lock(); BUSY_BEGIN;
isMuted[chan]=mute; isMuted[chan]=mute;
if (disCont[dispatchOfChan[chan]].dispatch!=NULL) { if (disCont[dispatchOfChan[chan]].dispatch!=NULL) {
disCont[dispatchOfChan[chan]].dispatch->muteChannel(dispatchChanOfChan[chan],isMuted[chan]); disCont[dispatchOfChan[chan]].dispatch->muteChannel(dispatchChanOfChan[chan],isMuted[chan]);
} }
isBusy.unlock(); BUSY_END;
} }
void DivEngine::unmuteAll() { void DivEngine::unmuteAll() {
isBusy.lock(); BUSY_BEGIN;
for (int i=0; i<chans; i++) { for (int i=0; i<chans; i++) {
isMuted[i]=false; isMuted[i]=false;
if (disCont[dispatchOfChan[i]].dispatch!=NULL) { if (disCont[dispatchOfChan[i]].dispatch!=NULL) {
disCont[dispatchOfChan[i]].dispatch->muteChannel(dispatchChanOfChan[i],isMuted[i]); disCont[dispatchOfChan[i]].dispatch->muteChannel(dispatchChanOfChan[i],isMuted[i]);
} }
} }
isBusy.unlock(); BUSY_END;
} }
int DivEngine::addInstrument(int refChan) { int DivEngine::addInstrument(int refChan) {
isBusy.lock(); BUSY_BEGIN;
DivInstrument* ins=new DivInstrument; DivInstrument* ins=new DivInstrument;
int insCount=(int)song.ins.size(); int insCount=(int)song.ins.size();
ins->name=fmt::sprintf("Instrument %d",insCount); ins->name=fmt::sprintf("Instrument %d",insCount);
@ -1226,7 +1228,7 @@ int DivEngine::addInstrument(int refChan) {
song.ins.push_back(ins); song.ins.push_back(ins);
song.insLen=insCount+1; song.insLen=insCount+1;
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
return insCount; return insCount;
} }
@ -1949,18 +1951,18 @@ bool DivEngine::addInstrumentFromFile(const char* path) {
} }
} }
isBusy.lock(); BUSY_BEGIN;
saveLock.lock(); saveLock.lock();
int insCount=(int)song.ins.size(); int insCount=(int)song.ins.size();
song.ins.push_back(ins); song.ins.push_back(ins);
song.insLen=insCount+1; song.insLen=insCount+1;
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
return true; return true;
} }
void DivEngine::delInstrument(int index) { void DivEngine::delInstrument(int index) {
isBusy.lock(); BUSY_BEGIN;
saveLock.lock(); saveLock.lock();
if (index>=0 && index<(int)song.ins.size()) { if (index>=0 && index<(int)song.ins.size()) {
for (int i=0; i<song.systemLen; i++) { for (int i=0; i<song.systemLen; i++) {
@ -1981,18 +1983,18 @@ void DivEngine::delInstrument(int index) {
} }
} }
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
} }
int DivEngine::addWave() { int DivEngine::addWave() {
isBusy.lock(); BUSY_BEGIN;
saveLock.lock(); saveLock.lock();
DivWavetable* wave=new DivWavetable; DivWavetable* wave=new DivWavetable;
int waveCount=(int)song.wave.size(); int waveCount=(int)song.wave.size();
song.wave.push_back(wave); song.wave.push_back(wave);
song.waveLen=waveCount+1; song.waveLen=waveCount+1;
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
return waveCount; return waveCount;
} }
@ -2106,18 +2108,18 @@ bool DivEngine::addWaveFromFile(const char* path) {
return false; return false;
} }
isBusy.lock(); BUSY_BEGIN;
saveLock.lock(); saveLock.lock();
int waveCount=(int)song.wave.size(); int waveCount=(int)song.wave.size();
song.wave.push_back(wave); song.wave.push_back(wave);
song.waveLen=waveCount+1; song.waveLen=waveCount+1;
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
return true; return true;
} }
void DivEngine::delWave(int index) { void DivEngine::delWave(int index) {
isBusy.lock(); BUSY_BEGIN;
saveLock.lock(); saveLock.lock();
if (index>=0 && index<(int)song.wave.size()) { if (index>=0 && index<(int)song.wave.size()) {
delete song.wave[index]; delete song.wave[index];
@ -2125,11 +2127,11 @@ void DivEngine::delWave(int index) {
song.waveLen=song.wave.size(); song.waveLen=song.wave.size();
} }
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
} }
int DivEngine::addSample() { int DivEngine::addSample() {
isBusy.lock(); BUSY_BEGIN;
saveLock.lock(); saveLock.lock();
DivSample* sample=new DivSample; DivSample* sample=new DivSample;
int sampleCount=(int)song.sample.size(); int sampleCount=(int)song.sample.size();
@ -2138,16 +2140,16 @@ int DivEngine::addSample() {
song.sampleLen=sampleCount+1; song.sampleLen=sampleCount+1;
saveLock.unlock(); saveLock.unlock();
renderSamples(); renderSamples();
isBusy.unlock(); BUSY_END;
return sampleCount; return sampleCount;
} }
int DivEngine::addSampleFromFile(const char* path) { int DivEngine::addSampleFromFile(const char* path) {
isBusy.lock(); BUSY_BEGIN;
SF_INFO si; SF_INFO si;
SNDFILE* f=sf_open(path,SFM_READ,&si); SNDFILE* f=sf_open(path,SFM_READ,&si);
if (f==NULL) { if (f==NULL) {
isBusy.unlock(); BUSY_END;
int err=sf_error(NULL); int err=sf_error(NULL);
if (err==SF_ERR_SYSTEM) { if (err==SF_ERR_SYSTEM) {
lastError=fmt::sprintf("could not open file! (%s %s)",sf_error_number(err),strerror(errno)); lastError=fmt::sprintf("could not open file! (%s %s)",sf_error_number(err),strerror(errno));
@ -2159,7 +2161,7 @@ int DivEngine::addSampleFromFile(const char* path) {
if (si.frames>16777215) { if (si.frames>16777215) {
lastError="this sample is too big! max sample size is 16777215."; lastError="this sample is too big! max sample size is 16777215.";
sf_close(f); sf_close(f);
isBusy.unlock(); BUSY_END;
return -1; return -1;
} }
short* buf=new short[si.channels*si.frames]; short* buf=new short[si.channels*si.frames];
@ -2226,12 +2228,12 @@ int DivEngine::addSampleFromFile(const char* path) {
song.sampleLen=sampleCount+1; song.sampleLen=sampleCount+1;
saveLock.unlock(); saveLock.unlock();
renderSamples(); renderSamples();
isBusy.unlock(); BUSY_END;
return sampleCount; return sampleCount;
} }
void DivEngine::delSample(int index) { void DivEngine::delSample(int index) {
isBusy.lock(); BUSY_BEGIN;
saveLock.lock(); saveLock.lock();
if (index>=0 && index<(int)song.sample.size()) { if (index>=0 && index<(int)song.sample.size()) {
delete song.sample[index]; delete song.sample[index];
@ -2240,13 +2242,13 @@ void DivEngine::delSample(int index) {
renderSamples(); renderSamples();
} }
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
} }
void DivEngine::addOrder(bool duplicate, bool where) { void DivEngine::addOrder(bool duplicate, bool where) {
unsigned char order[DIV_MAX_CHANS]; unsigned char order[DIV_MAX_CHANS];
if (song.ordersLen>=0x7e) return; if (song.ordersLen>=0x7e) return;
isBusy.lock(); BUSY_BEGIN_SOFT;
if (duplicate) { if (duplicate) {
for (int i=0; i<DIV_MAX_CHANS; i++) { for (int i=0; i<DIV_MAX_CHANS; i++) {
order[i]=song.orders.ord[i][curOrder]; order[i]=song.orders.ord[i][curOrder];
@ -2289,14 +2291,14 @@ void DivEngine::addOrder(bool duplicate, bool where) {
playSub(false); playSub(false);
} }
} }
isBusy.unlock(); BUSY_END;
} }
void DivEngine::deepCloneOrder(bool where) { void DivEngine::deepCloneOrder(bool where) {
unsigned char order[DIV_MAX_CHANS]; unsigned char order[DIV_MAX_CHANS];
if (song.ordersLen>=0x7e) return; if (song.ordersLen>=0x7e) return;
warnings=""; warnings="";
isBusy.lock(); BUSY_BEGIN_SOFT;
for (int i=0; i<chans; i++) { for (int i=0; i<chans; i++) {
bool didNotFind=true; bool didNotFind=true;
logD("channel %d\n",i); logD("channel %d\n",i);
@ -2341,12 +2343,12 @@ void DivEngine::deepCloneOrder(bool where) {
playSub(false); playSub(false);
} }
} }
isBusy.unlock(); BUSY_END;
} }
void DivEngine::deleteOrder() { void DivEngine::deleteOrder() {
if (song.ordersLen<=1) return; if (song.ordersLen<=1) return;
isBusy.lock(); BUSY_BEGIN_SOFT;
saveLock.lock(); saveLock.lock();
for (int i=0; i<DIV_MAX_CHANS; i++) { for (int i=0; i<DIV_MAX_CHANS; i++) {
for (int j=curOrder; j<song.ordersLen; j++) { for (int j=curOrder; j<song.ordersLen; j++) {
@ -2359,13 +2361,13 @@ void DivEngine::deleteOrder() {
if (playing && !freelance) { if (playing && !freelance) {
playSub(false); playSub(false);
} }
isBusy.unlock(); BUSY_END;
} }
void DivEngine::moveOrderUp() { void DivEngine::moveOrderUp() {
isBusy.lock(); BUSY_BEGIN_SOFT;
if (curOrder<1) { if (curOrder<1) {
isBusy.unlock(); BUSY_END;
return; return;
} }
saveLock.lock(); saveLock.lock();
@ -2379,13 +2381,13 @@ void DivEngine::moveOrderUp() {
if (playing && !freelance) { if (playing && !freelance) {
playSub(false); playSub(false);
} }
isBusy.unlock(); BUSY_END;
} }
void DivEngine::moveOrderDown() { void DivEngine::moveOrderDown() {
isBusy.lock(); BUSY_BEGIN_SOFT;
if (curOrder>=song.ordersLen-1) { if (curOrder>=song.ordersLen-1) {
isBusy.unlock(); BUSY_END;
return; return;
} }
saveLock.lock(); saveLock.lock();
@ -2399,7 +2401,7 @@ void DivEngine::moveOrderDown() {
if (playing && !freelance) { if (playing && !freelance) {
playSub(false); playSub(false);
} }
isBusy.unlock(); BUSY_END;
} }
void DivEngine::exchangeIns(int one, int two) { void DivEngine::exchangeIns(int one, int two) {
@ -2419,114 +2421,114 @@ void DivEngine::exchangeIns(int one, int two) {
bool DivEngine::moveInsUp(int which) { bool DivEngine::moveInsUp(int which) {
if (which<1 || which>=(int)song.ins.size()) return false; if (which<1 || which>=(int)song.ins.size()) return false;
isBusy.lock(); BUSY_BEGIN;
DivInstrument* prev=song.ins[which]; DivInstrument* prev=song.ins[which];
saveLock.lock(); saveLock.lock();
song.ins[which]=song.ins[which-1]; song.ins[which]=song.ins[which-1];
song.ins[which-1]=prev; song.ins[which-1]=prev;
exchangeIns(which,which-1); exchangeIns(which,which-1);
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
return true; return true;
} }
bool DivEngine::moveWaveUp(int which) { bool DivEngine::moveWaveUp(int which) {
if (which<1 || which>=(int)song.wave.size()) return false; if (which<1 || which>=(int)song.wave.size()) return false;
isBusy.lock(); BUSY_BEGIN;
DivWavetable* prev=song.wave[which]; DivWavetable* prev=song.wave[which];
saveLock.lock(); saveLock.lock();
song.wave[which]=song.wave[which-1]; song.wave[which]=song.wave[which-1];
song.wave[which-1]=prev; song.wave[which-1]=prev;
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
return true; return true;
} }
bool DivEngine::moveSampleUp(int which) { bool DivEngine::moveSampleUp(int which) {
if (which<1 || which>=(int)song.sample.size()) return false; if (which<1 || which>=(int)song.sample.size()) return false;
isBusy.lock(); BUSY_BEGIN;
DivSample* prev=song.sample[which]; DivSample* prev=song.sample[which];
saveLock.lock(); saveLock.lock();
song.sample[which]=song.sample[which-1]; song.sample[which]=song.sample[which-1];
song.sample[which-1]=prev; song.sample[which-1]=prev;
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
return true; return true;
} }
bool DivEngine::moveInsDown(int which) { bool DivEngine::moveInsDown(int which) {
if (which<0 || which>=((int)song.ins.size())-1) return false; if (which<0 || which>=((int)song.ins.size())-1) return false;
isBusy.lock(); BUSY_BEGIN;
DivInstrument* prev=song.ins[which]; DivInstrument* prev=song.ins[which];
saveLock.lock(); saveLock.lock();
song.ins[which]=song.ins[which+1]; song.ins[which]=song.ins[which+1];
song.ins[which+1]=prev; song.ins[which+1]=prev;
exchangeIns(which,which+1); exchangeIns(which,which+1);
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
return true; return true;
} }
bool DivEngine::moveWaveDown(int which) { bool DivEngine::moveWaveDown(int which) {
if (which<0 || which>=((int)song.wave.size())-1) return false; if (which<0 || which>=((int)song.wave.size())-1) return false;
isBusy.lock(); BUSY_BEGIN;
DivWavetable* prev=song.wave[which]; DivWavetable* prev=song.wave[which];
saveLock.lock(); saveLock.lock();
song.wave[which]=song.wave[which+1]; song.wave[which]=song.wave[which+1];
song.wave[which+1]=prev; song.wave[which+1]=prev;
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
return true; return true;
} }
bool DivEngine::moveSampleDown(int which) { bool DivEngine::moveSampleDown(int which) {
if (which<0 || which>=((int)song.sample.size())-1) return false; if (which<0 || which>=((int)song.sample.size())-1) return false;
isBusy.lock(); BUSY_BEGIN;
DivSample* prev=song.sample[which]; DivSample* prev=song.sample[which];
saveLock.lock(); saveLock.lock();
song.sample[which]=song.sample[which+1]; song.sample[which]=song.sample[which+1];
song.sample[which+1]=prev; song.sample[which+1]=prev;
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
return true; return true;
} }
void DivEngine::noteOn(int chan, int ins, int note, int vol) { void DivEngine::noteOn(int chan, int ins, int note, int vol) {
if (chan<0 || chan>=chans) return; if (chan<0 || chan>=chans) return;
isBusy.lock(); BUSY_BEGIN;
pendingNotes.push(DivNoteEvent(chan,ins,note,vol,true)); pendingNotes.push(DivNoteEvent(chan,ins,note,vol,true));
if (!playing) { if (!playing) {
reset(); reset();
freelance=true; freelance=true;
playing=true; playing=true;
} }
isBusy.unlock(); BUSY_END;
} }
void DivEngine::noteOff(int chan) { void DivEngine::noteOff(int chan) {
if (chan<0 || chan>=chans) return; if (chan<0 || chan>=chans) return;
isBusy.lock(); BUSY_BEGIN;
pendingNotes.push(DivNoteEvent(chan,-1,-1,-1,false)); pendingNotes.push(DivNoteEvent(chan,-1,-1,-1,false));
if (!playing) { if (!playing) {
reset(); reset();
freelance=true; freelance=true;
playing=true; playing=true;
} }
isBusy.unlock(); BUSY_END;
} }
void DivEngine::setOrder(unsigned char order) { void DivEngine::setOrder(unsigned char order) {
isBusy.lock(); BUSY_BEGIN_SOFT;
curOrder=order; curOrder=order;
if (order>=song.ordersLen) curOrder=0; if (order>=song.ordersLen) curOrder=0;
if (playing && !freelance) { if (playing && !freelance) {
playSub(false); playSub(false);
} }
isBusy.unlock(); BUSY_END;
} }
void DivEngine::setSysFlags(int system, unsigned int flags, bool restart) { void DivEngine::setSysFlags(int system, unsigned int flags, bool restart) {
isBusy.lock(); BUSY_BEGIN_SOFT;
saveLock.lock(); saveLock.lock();
song.systemFlags[system]=flags; song.systemFlags[system]=flags;
saveLock.unlock(); saveLock.unlock();
@ -2535,11 +2537,11 @@ void DivEngine::setSysFlags(int system, unsigned int flags, bool restart) {
if (restart && isPlaying()) { if (restart && isPlaying()) {
playSub(false); playSub(false);
} }
isBusy.unlock(); BUSY_END;
} }
void DivEngine::setSongRate(float hz, bool pal) { void DivEngine::setSongRate(float hz, bool pal) {
isBusy.lock(); BUSY_BEGIN;
saveLock.lock(); saveLock.lock();
song.pal=!pal; song.pal=!pal;
song.hz=hz; song.hz=hz;
@ -2556,7 +2558,7 @@ void DivEngine::setSongRate(float hz, bool pal) {
} }
} }
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
} }
void DivEngine::setAudio(DivAudioEngines which) { void DivEngine::setAudio(DivAudioEngines which) {
@ -2600,9 +2602,9 @@ bool DivEngine::switchMaster() {
} }
void DivEngine::synchronized(const std::function<void()>& what) { void DivEngine::synchronized(const std::function<void()>& what) {
isBusy.lock(); BUSY_BEGIN;
what(); what();
isBusy.unlock(); BUSY_END;
} }
void DivEngine::lockSave(const std::function<void()>& what) { void DivEngine::lockSave(const std::function<void()>& what) {
@ -2612,11 +2614,11 @@ void DivEngine::lockSave(const std::function<void()>& what) {
} }
void DivEngine::lockEngine(const std::function<void()>& what) { void DivEngine::lockEngine(const std::function<void()>& what) {
isBusy.lock(); BUSY_BEGIN;
saveLock.lock(); saveLock.lock();
what(); what();
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
} }
TAAudioDesc& DivEngine::getAudioDescWant() { TAAudioDesc& DivEngine::getAudioDescWant() {
@ -2639,18 +2641,18 @@ void DivEngine::rescanAudioDevices() {
} }
void DivEngine::initDispatch() { void DivEngine::initDispatch() {
isBusy.lock(); BUSY_BEGIN;
for (int i=0; i<song.systemLen; i++) { for (int i=0; i<song.systemLen; i++) {
disCont[i].init(song.system[i],this,getChannelCount(song.system[i]),got.rate,song.systemFlags[i]); disCont[i].init(song.system[i],this,getChannelCount(song.system[i]),got.rate,song.systemFlags[i]);
disCont[i].setRates(got.rate); disCont[i].setRates(got.rate);
disCont[i].setQuality(lowQuality); disCont[i].setQuality(lowQuality);
} }
recalcChans(); recalcChans();
isBusy.unlock(); BUSY_END;
} }
void DivEngine::quitDispatch() { void DivEngine::quitDispatch() {
isBusy.lock(); BUSY_BEGIN;
for (int i=0; i<song.systemLen; i++) { for (int i=0; i<song.systemLen; i++) {
disCont[i].quit(); disCont[i].quit();
} }
@ -2675,7 +2677,7 @@ void DivEngine::quitDispatch() {
for (int i=0; i<DIV_MAX_CHANS; i++) { for (int i=0; i<DIV_MAX_CHANS; i++) {
isMuted[i]=0; isMuted[i]=0;
} }
isBusy.unlock(); BUSY_END;
} }
#define CHECK_CONFIG_DIR_MAC() \ #define CHECK_CONFIG_DIR_MAC() \

View file

@ -38,6 +38,10 @@
warnings+=(String("\n")+x); \ warnings+=(String("\n")+x); \
} }
#define BUSY_BEGIN softLocked=false; isBusy.lock();
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
#define BUSY_END isBusy.unlock(); softLocked=false;
#define DIV_VERSION "dev70" #define DIV_VERSION "dev70"
#define DIV_ENGINE_VERSION 70 #define DIV_ENGINE_VERSION 70
@ -185,6 +189,7 @@ class DivEngine {
bool halted; bool halted;
bool forceMono; bool forceMono;
bool cmdStreamEnabled; bool cmdStreamEnabled;
bool softLocked;
int ticks, curRow, curOrder, remainingLoops, nextSpeed; int ticks, curRow, curOrder, remainingLoops, nextSpeed;
double divider; double divider;
int cycles; int cycles;

View file

@ -733,14 +733,14 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
} }
if (active) quitDispatch(); if (active) quitDispatch();
isBusy.lock(); BUSY_BEGIN_SOFT;
saveLock.lock(); saveLock.lock();
song.unload(); song.unload();
song=ds; song=ds;
recalcChans(); recalcChans();
renderSamples(); renderSamples();
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
if (active) { if (active) {
initDispatch(); initDispatch();
syncReset(); syncReset();
@ -1236,14 +1236,14 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
} }
if (active) quitDispatch(); if (active) quitDispatch();
isBusy.lock(); BUSY_BEGIN_SOFT;
saveLock.lock(); saveLock.lock();
song.unload(); song.unload();
song=ds; song=ds;
recalcChans(); recalcChans();
renderSamples(); renderSamples();
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
if (active) { if (active) {
initDispatch(); initDispatch();
syncReset(); syncReset();
@ -1602,14 +1602,14 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
ds.insLen=ds.ins.size(); ds.insLen=ds.ins.size();
if (active) quitDispatch(); if (active) quitDispatch();
isBusy.lock(); BUSY_BEGIN_SOFT;
saveLock.lock(); saveLock.lock();
song.unload(); song.unload();
song=ds; song=ds;
recalcChans(); recalcChans();
renderSamples(); renderSamples();
saveLock.unlock(); saveLock.unlock();
isBusy.unlock(); BUSY_END;
if (active) { if (active) {
initDispatch(); initDispatch();
syncReset(); syncReset();

View file

@ -1408,7 +1408,13 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
memset(out[1],0,size*sizeof(float)); memset(out[1],0,size*sizeof(float));
} }
if (softLocked) {
if (!isBusy.try_lock()) {
return;
}
} else {
isBusy.lock(); isBusy.lock();
}
got.bufsize=size; got.bufsize=size;
if (out!=NULL && ((sPreview.sample>=0 && sPreview.sample<(int)song.sample.size()) || (sPreview.wave>=0 && sPreview.wave<(int)song.wave.size()))) { if (out!=NULL && ((sPreview.sample>=0 && sPreview.sample<(int)song.sample.size()) || (sPreview.wave>=0 && sPreview.wave<(int)song.wave.size()))) {

View file

@ -477,7 +477,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop) {
stop(); stop();
repeatPattern=false; repeatPattern=false;
setOrder(0); setOrder(0);
isBusy.lock(); BUSY_BEGIN_SOFT;
double origRate=got.rate; double origRate=got.rate;
got.rate=44100; got.rate=44100;
// determine loop point // determine loop point
@ -1305,6 +1305,6 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop) {
logI("%d register writes total.\n",writeCount); logI("%d register writes total.\n",writeCount);
isBusy.unlock(); BUSY_END;
return w; return w;
} }