mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-27 23:13:01 +00:00
Merge branch 'master' of https://github.com/tildearrow/furnace into n163
This commit is contained in:
commit
39654bfa86
12 changed files with 215 additions and 152 deletions
|
@ -437,25 +437,25 @@ bool DivEngine::haltAudioFile() {
|
|||
}
|
||||
|
||||
void DivEngine::notifyInsChange(int ins) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
for (int i=0; i<song.systemLen; i++) {
|
||||
disCont[i].dispatch->notifyInsChange(ins);
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::notifyWaveChange(int wave) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
for (int i=0; i<song.systemLen; i++) {
|
||||
disCont[i].dispatch->notifyWaveChange(wave);
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::renderSamplesP() {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
renderSamples();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::renderSamples() {
|
||||
|
@ -583,7 +583,7 @@ void DivEngine::renderSamples() {
|
|||
|
||||
void DivEngine::createNew(const int* description) {
|
||||
quitDispatch();
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
song.unload();
|
||||
song=DivSong();
|
||||
|
@ -604,27 +604,27 @@ void DivEngine::createNew(const int* description) {
|
|||
recalcChans();
|
||||
renderSamples();
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
initDispatch();
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
reset();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::changeSystem(int index, DivSystem which) {
|
||||
quitDispatch();
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
song.system[index]=which;
|
||||
song.systemFlags[index]=0;
|
||||
recalcChans();
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
initDispatch();
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
renderSamples();
|
||||
reset();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
bool DivEngine::addSystem(DivSystem which) {
|
||||
|
@ -638,7 +638,7 @@ bool DivEngine::addSystem(DivSystem which) {
|
|||
return false;
|
||||
}
|
||||
quitDispatch();
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
song.system[song.systemLen]=which;
|
||||
song.systemVol[song.systemLen]=64;
|
||||
|
@ -646,12 +646,12 @@ bool DivEngine::addSystem(DivSystem which) {
|
|||
song.systemFlags[song.systemLen++]=0;
|
||||
recalcChans();
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
initDispatch();
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
renderSamples();
|
||||
reset();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -665,7 +665,7 @@ bool DivEngine::removeSystem(int index) {
|
|||
return false;
|
||||
}
|
||||
quitDispatch();
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
song.system[index]=DIV_SYSTEM_NULL;
|
||||
song.systemLen--;
|
||||
|
@ -674,27 +674,27 @@ bool DivEngine::removeSystem(int index) {
|
|||
}
|
||||
recalcChans();
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
initDispatch();
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
renderSamples();
|
||||
reset();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DivEngine::poke(int sys, unsigned int addr, unsigned short val) {
|
||||
if (sys<0 || sys>=song.systemLen) return;
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
disCont[sys].dispatch->poke(addr,val);
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::poke(int sys, std::vector<DivRegWrite>& wlist) {
|
||||
if (sys<0 || sys>=song.systemLen) return;
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
disCont[sys].dispatch->poke(wlist);
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
String DivEngine::getLastError() {
|
||||
|
@ -753,13 +753,13 @@ void DivEngine::enableCommandStream(bool enable) {
|
|||
}
|
||||
|
||||
void DivEngine::getCommandStream(std::vector<DivCommand>& where) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
where.clear();
|
||||
for (DivCommand& i: cmdStream) {
|
||||
where.push_back(i);
|
||||
}
|
||||
cmdStream.clear();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
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() {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN_SOFT;
|
||||
sPreview.sample=-1;
|
||||
sPreview.wave=-1;
|
||||
sPreview.pos=0;
|
||||
|
@ -847,11 +847,11 @@ void DivEngine::play() {
|
|||
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||
keyHit[i]=false;
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::playToRow(int row) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN_SOFT;
|
||||
sPreview.sample=-1;
|
||||
sPreview.wave=-1;
|
||||
sPreview.pos=0;
|
||||
|
@ -860,25 +860,27 @@ void DivEngine::playToRow(int row) {
|
|||
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||
keyHit[i]=false;
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::stepOne(int row) {
|
||||
isBusy.lock();
|
||||
if (!isPlaying()) {
|
||||
BUSY_BEGIN_SOFT;
|
||||
freelance=false;
|
||||
playSub(false,row);
|
||||
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||
keyHit[i]=false;
|
||||
}
|
||||
} else {
|
||||
BUSY_BEGIN;
|
||||
}
|
||||
stepPlay=2;
|
||||
ticks=1;
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::stop() {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
freelance=false;
|
||||
playing=false;
|
||||
extValuePresent=false;
|
||||
|
@ -890,27 +892,27 @@ void DivEngine::stop() {
|
|||
for (int i=0; i<song.systemLen; i++) {
|
||||
disCont[i].dispatch->notifyPlaybackStop();
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::halt() {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
halted=true;
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::resume() {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
halted=false;
|
||||
haltOn=DIV_HALT_NONE;
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::haltWhen(DivHaltPositions when) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
halted=false;
|
||||
haltOn=when;
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
bool DivEngine::isHalted() {
|
||||
|
@ -966,9 +968,9 @@ void DivEngine::reset() {
|
|||
}
|
||||
|
||||
void DivEngine::syncReset() {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
reset();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
const int sampleRates[6]={
|
||||
|
@ -1024,11 +1026,11 @@ int DivEngine::getEffectiveSampleRate(int rate) {
|
|||
}
|
||||
|
||||
void DivEngine::previewSample(int sample, int note) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
if (sample<0 || sample>=(int)song.sample.size()) {
|
||||
sPreview.sample=-1;
|
||||
sPreview.pos=0;
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return;
|
||||
}
|
||||
blip_clear(samp_bb);
|
||||
|
@ -1043,26 +1045,26 @@ void DivEngine::previewSample(int sample, int note) {
|
|||
sPreview.pos=0;
|
||||
sPreview.sample=sample;
|
||||
sPreview.wave=-1;
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::stopSamplePreview() {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
sPreview.sample=-1;
|
||||
sPreview.pos=0;
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::previewWave(int wave, int note) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
if (wave<0 || wave>=(int)song.wave.size()) {
|
||||
sPreview.wave=-1;
|
||||
sPreview.pos=0;
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return;
|
||||
}
|
||||
if (song.wave[wave]->len<=0) {
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return;
|
||||
}
|
||||
blip_clear(samp_bb);
|
||||
|
@ -1073,14 +1075,14 @@ void DivEngine::previewWave(int wave, int note) {
|
|||
sPreview.pos=0;
|
||||
sPreview.sample=-1;
|
||||
sPreview.wave=wave;
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::stopWavePreview() {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
sPreview.wave=-1;
|
||||
sPreview.pos=0;
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
String DivEngine::getConfigPath() {
|
||||
|
@ -1135,9 +1137,9 @@ bool DivEngine::getRepeatPattern() {
|
|||
}
|
||||
|
||||
void DivEngine::setRepeatPattern(bool value) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
repeatPattern=value;
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
bool DivEngine::hasExtValue() {
|
||||
|
@ -1177,7 +1179,7 @@ void DivEngine::toggleSolo(int chan) {
|
|||
}
|
||||
}
|
||||
}
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
if (!solo) {
|
||||
for (int i=0; i<chans; i++) {
|
||||
isMuted[i]=(i!=chan);
|
||||
|
@ -1193,31 +1195,31 @@ void DivEngine::toggleSolo(int chan) {
|
|||
}
|
||||
}
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::muteChannel(int chan, bool mute) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
isMuted[chan]=mute;
|
||||
if (disCont[dispatchOfChan[chan]].dispatch!=NULL) {
|
||||
disCont[dispatchOfChan[chan]].dispatch->muteChannel(dispatchChanOfChan[chan],isMuted[chan]);
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::unmuteAll() {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
for (int i=0; i<chans; i++) {
|
||||
isMuted[i]=false;
|
||||
if (disCont[dispatchOfChan[i]].dispatch!=NULL) {
|
||||
disCont[dispatchOfChan[i]].dispatch->muteChannel(dispatchChanOfChan[i],isMuted[i]);
|
||||
}
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
int DivEngine::addInstrument(int refChan) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
DivInstrument* ins=new DivInstrument;
|
||||
int insCount=(int)song.ins.size();
|
||||
ins->name=fmt::sprintf("Instrument %d",insCount);
|
||||
|
@ -1226,7 +1228,7 @@ int DivEngine::addInstrument(int refChan) {
|
|||
song.ins.push_back(ins);
|
||||
song.insLen=insCount+1;
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return insCount;
|
||||
}
|
||||
|
||||
|
@ -1949,18 +1951,18 @@ bool DivEngine::addInstrumentFromFile(const char* path) {
|
|||
}
|
||||
}
|
||||
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
int insCount=(int)song.ins.size();
|
||||
song.ins.push_back(ins);
|
||||
song.insLen=insCount+1;
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DivEngine::delInstrument(int index) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
if (index>=0 && index<(int)song.ins.size()) {
|
||||
for (int i=0; i<song.systemLen; i++) {
|
||||
|
@ -1981,18 +1983,18 @@ void DivEngine::delInstrument(int index) {
|
|||
}
|
||||
}
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
int DivEngine::addWave() {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
DivWavetable* wave=new DivWavetable;
|
||||
int waveCount=(int)song.wave.size();
|
||||
song.wave.push_back(wave);
|
||||
song.waveLen=waveCount+1;
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return waveCount;
|
||||
}
|
||||
|
||||
|
@ -2106,18 +2108,18 @@ bool DivEngine::addWaveFromFile(const char* path) {
|
|||
return false;
|
||||
}
|
||||
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
int waveCount=(int)song.wave.size();
|
||||
song.wave.push_back(wave);
|
||||
song.waveLen=waveCount+1;
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DivEngine::delWave(int index) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
if (index>=0 && index<(int)song.wave.size()) {
|
||||
delete song.wave[index];
|
||||
|
@ -2125,11 +2127,11 @@ void DivEngine::delWave(int index) {
|
|||
song.waveLen=song.wave.size();
|
||||
}
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
int DivEngine::addSample() {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
DivSample* sample=new DivSample;
|
||||
int sampleCount=(int)song.sample.size();
|
||||
|
@ -2138,22 +2140,29 @@ int DivEngine::addSample() {
|
|||
song.sampleLen=sampleCount+1;
|
||||
saveLock.unlock();
|
||||
renderSamples();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return sampleCount;
|
||||
}
|
||||
|
||||
bool DivEngine::addSampleFromFile(const char* path) {
|
||||
isBusy.lock();
|
||||
int DivEngine::addSampleFromFile(const char* path) {
|
||||
BUSY_BEGIN;
|
||||
SF_INFO si;
|
||||
SNDFILE* f=sf_open(path,SFM_READ,&si);
|
||||
if (f==NULL) {
|
||||
isBusy.unlock();
|
||||
return false;
|
||||
BUSY_END;
|
||||
int err=sf_error(NULL);
|
||||
if (err==SF_ERR_SYSTEM) {
|
||||
lastError=fmt::sprintf("could not open file! (%s %s)",sf_error_number(err),strerror(errno));
|
||||
} else {
|
||||
lastError=fmt::sprintf("could not open file! (%s)",sf_error_number(err));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (si.frames>1000000) {
|
||||
if (si.frames>16777215) {
|
||||
lastError="this sample is too big! max sample size is 16777215.";
|
||||
sf_close(f);
|
||||
isBusy.unlock();
|
||||
return false;
|
||||
BUSY_END;
|
||||
return -1;
|
||||
}
|
||||
short* buf=new short[si.channels*si.frames];
|
||||
if (sf_readf_short(f,buf,si.frames)!=si.frames) {
|
||||
|
@ -2219,12 +2228,12 @@ bool DivEngine::addSampleFromFile(const char* path) {
|
|||
song.sampleLen=sampleCount+1;
|
||||
saveLock.unlock();
|
||||
renderSamples();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return sampleCount;
|
||||
}
|
||||
|
||||
void DivEngine::delSample(int index) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
if (index>=0 && index<(int)song.sample.size()) {
|
||||
delete song.sample[index];
|
||||
|
@ -2233,13 +2242,13 @@ void DivEngine::delSample(int index) {
|
|||
renderSamples();
|
||||
}
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::addOrder(bool duplicate, bool where) {
|
||||
unsigned char order[DIV_MAX_CHANS];
|
||||
if (song.ordersLen>=0x7e) return;
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN_SOFT;
|
||||
if (duplicate) {
|
||||
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||
order[i]=song.orders.ord[i][curOrder];
|
||||
|
@ -2282,14 +2291,14 @@ void DivEngine::addOrder(bool duplicate, bool where) {
|
|||
playSub(false);
|
||||
}
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::deepCloneOrder(bool where) {
|
||||
unsigned char order[DIV_MAX_CHANS];
|
||||
if (song.ordersLen>=0x7e) return;
|
||||
warnings="";
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN_SOFT;
|
||||
for (int i=0; i<chans; i++) {
|
||||
bool didNotFind=true;
|
||||
logD("channel %d\n",i);
|
||||
|
@ -2334,12 +2343,12 @@ void DivEngine::deepCloneOrder(bool where) {
|
|||
playSub(false);
|
||||
}
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::deleteOrder() {
|
||||
if (song.ordersLen<=1) return;
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN_SOFT;
|
||||
saveLock.lock();
|
||||
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||
for (int j=curOrder; j<song.ordersLen; j++) {
|
||||
|
@ -2352,13 +2361,13 @@ void DivEngine::deleteOrder() {
|
|||
if (playing && !freelance) {
|
||||
playSub(false);
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::moveOrderUp() {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN_SOFT;
|
||||
if (curOrder<1) {
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return;
|
||||
}
|
||||
saveLock.lock();
|
||||
|
@ -2372,13 +2381,13 @@ void DivEngine::moveOrderUp() {
|
|||
if (playing && !freelance) {
|
||||
playSub(false);
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::moveOrderDown() {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN_SOFT;
|
||||
if (curOrder>=song.ordersLen-1) {
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return;
|
||||
}
|
||||
saveLock.lock();
|
||||
|
@ -2392,7 +2401,7 @@ void DivEngine::moveOrderDown() {
|
|||
if (playing && !freelance) {
|
||||
playSub(false);
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::exchangeIns(int one, int two) {
|
||||
|
@ -2412,114 +2421,114 @@ void DivEngine::exchangeIns(int one, int two) {
|
|||
|
||||
bool DivEngine::moveInsUp(int which) {
|
||||
if (which<1 || which>=(int)song.ins.size()) return false;
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
DivInstrument* prev=song.ins[which];
|
||||
saveLock.lock();
|
||||
song.ins[which]=song.ins[which-1];
|
||||
song.ins[which-1]=prev;
|
||||
exchangeIns(which,which-1);
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DivEngine::moveWaveUp(int which) {
|
||||
if (which<1 || which>=(int)song.wave.size()) return false;
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
DivWavetable* prev=song.wave[which];
|
||||
saveLock.lock();
|
||||
song.wave[which]=song.wave[which-1];
|
||||
song.wave[which-1]=prev;
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DivEngine::moveSampleUp(int which) {
|
||||
if (which<1 || which>=(int)song.sample.size()) return false;
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
DivSample* prev=song.sample[which];
|
||||
saveLock.lock();
|
||||
song.sample[which]=song.sample[which-1];
|
||||
song.sample[which-1]=prev;
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DivEngine::moveInsDown(int which) {
|
||||
if (which<0 || which>=((int)song.ins.size())-1) return false;
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
DivInstrument* prev=song.ins[which];
|
||||
saveLock.lock();
|
||||
song.ins[which]=song.ins[which+1];
|
||||
song.ins[which+1]=prev;
|
||||
exchangeIns(which,which+1);
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DivEngine::moveWaveDown(int which) {
|
||||
if (which<0 || which>=((int)song.wave.size())-1) return false;
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
DivWavetable* prev=song.wave[which];
|
||||
saveLock.lock();
|
||||
song.wave[which]=song.wave[which+1];
|
||||
song.wave[which+1]=prev;
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DivEngine::moveSampleDown(int which) {
|
||||
if (which<0 || which>=((int)song.sample.size())-1) return false;
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
DivSample* prev=song.sample[which];
|
||||
saveLock.lock();
|
||||
song.sample[which]=song.sample[which+1];
|
||||
song.sample[which+1]=prev;
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return true;
|
||||
}
|
||||
|
||||
void DivEngine::noteOn(int chan, int ins, int note, int vol) {
|
||||
if (chan<0 || chan>=chans) return;
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
pendingNotes.push(DivNoteEvent(chan,ins,note,vol,true));
|
||||
if (!playing) {
|
||||
reset();
|
||||
freelance=true;
|
||||
playing=true;
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::noteOff(int chan) {
|
||||
if (chan<0 || chan>=chans) return;
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
pendingNotes.push(DivNoteEvent(chan,-1,-1,-1,false));
|
||||
if (!playing) {
|
||||
reset();
|
||||
freelance=true;
|
||||
playing=true;
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::setOrder(unsigned char order) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN_SOFT;
|
||||
curOrder=order;
|
||||
if (order>=song.ordersLen) curOrder=0;
|
||||
if (playing && !freelance) {
|
||||
playSub(false);
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::setSysFlags(int system, unsigned int flags, bool restart) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN_SOFT;
|
||||
saveLock.lock();
|
||||
song.systemFlags[system]=flags;
|
||||
saveLock.unlock();
|
||||
|
@ -2528,11 +2537,11 @@ void DivEngine::setSysFlags(int system, unsigned int flags, bool restart) {
|
|||
if (restart && isPlaying()) {
|
||||
playSub(false);
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::setSongRate(float hz, bool pal) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
song.pal=!pal;
|
||||
song.hz=hz;
|
||||
|
@ -2549,7 +2558,7 @@ void DivEngine::setSongRate(float hz, bool pal) {
|
|||
}
|
||||
}
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::setAudio(DivAudioEngines which) {
|
||||
|
@ -2593,9 +2602,9 @@ bool DivEngine::switchMaster() {
|
|||
}
|
||||
|
||||
void DivEngine::synchronized(const std::function<void()>& what) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
what();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::lockSave(const std::function<void()>& what) {
|
||||
|
@ -2605,11 +2614,11 @@ void DivEngine::lockSave(const std::function<void()>& what) {
|
|||
}
|
||||
|
||||
void DivEngine::lockEngine(const std::function<void()>& what) {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
what();
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
TAAudioDesc& DivEngine::getAudioDescWant() {
|
||||
|
@ -2632,18 +2641,18 @@ void DivEngine::rescanAudioDevices() {
|
|||
}
|
||||
|
||||
void DivEngine::initDispatch() {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
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].setRates(got.rate);
|
||||
disCont[i].setQuality(lowQuality);
|
||||
}
|
||||
recalcChans();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::quitDispatch() {
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN;
|
||||
for (int i=0; i<song.systemLen; i++) {
|
||||
disCont[i].quit();
|
||||
}
|
||||
|
@ -2668,7 +2677,7 @@ void DivEngine::quitDispatch() {
|
|||
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||
isMuted[i]=0;
|
||||
}
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
#define CHECK_CONFIG_DIR_MAC() \
|
||||
|
|
|
@ -38,6 +38,10 @@
|
|||
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_ENGINE_VERSION 70
|
||||
|
||||
|
@ -185,6 +189,8 @@ class DivEngine {
|
|||
bool halted;
|
||||
bool forceMono;
|
||||
bool cmdStreamEnabled;
|
||||
bool softLocked;
|
||||
int softLockCount;
|
||||
int ticks, curRow, curOrder, remainingLoops, nextSpeed;
|
||||
double divider;
|
||||
int cycles;
|
||||
|
@ -489,7 +495,7 @@ class DivEngine {
|
|||
int addSample();
|
||||
|
||||
// add sample from file
|
||||
bool addSampleFromFile(const char* path);
|
||||
int addSampleFromFile(const char* path);
|
||||
|
||||
// delete sample
|
||||
void delSample(int index);
|
||||
|
@ -676,6 +682,8 @@ class DivEngine {
|
|||
halted(false),
|
||||
forceMono(false),
|
||||
cmdStreamEnabled(false),
|
||||
softLocked(0),
|
||||
softLockCount(0),
|
||||
ticks(0),
|
||||
curRow(0),
|
||||
curOrder(0),
|
||||
|
|
|
@ -733,14 +733,14 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
|
|||
}
|
||||
|
||||
if (active) quitDispatch();
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN_SOFT;
|
||||
saveLock.lock();
|
||||
song.unload();
|
||||
song=ds;
|
||||
recalcChans();
|
||||
renderSamples();
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
if (active) {
|
||||
initDispatch();
|
||||
syncReset();
|
||||
|
@ -1236,14 +1236,14 @@ bool DivEngine::loadFur(unsigned char* file, size_t len) {
|
|||
}
|
||||
|
||||
if (active) quitDispatch();
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN_SOFT;
|
||||
saveLock.lock();
|
||||
song.unload();
|
||||
song=ds;
|
||||
recalcChans();
|
||||
renderSamples();
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
if (active) {
|
||||
initDispatch();
|
||||
syncReset();
|
||||
|
@ -1602,14 +1602,14 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
|
|||
ds.insLen=ds.ins.size();
|
||||
|
||||
if (active) quitDispatch();
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN_SOFT;
|
||||
saveLock.lock();
|
||||
song.unload();
|
||||
song=ds;
|
||||
recalcChans();
|
||||
renderSamples();
|
||||
saveLock.unlock();
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
if (active) {
|
||||
initDispatch();
|
||||
syncReset();
|
||||
|
|
|
@ -52,6 +52,8 @@ static int orderedOps[4]={
|
|||
#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 NOTE_LINEAR(x) (((x)<<6)+baseFreqOff+log2(parent->song.tuning/440.0)*12.0*64.0)
|
||||
|
||||
const char* regCheatSheetOPM[]={
|
||||
"Test", "00",
|
||||
"NoteCtl", "08",
|
||||
|
@ -234,15 +236,15 @@ void DivPlatformArcade::tick() {
|
|||
if (chan[i].std.hadArp) {
|
||||
if (!chan[i].inPorta) {
|
||||
if (chan[i].std.arpMode) {
|
||||
chan[i].baseFreq=(chan[i].std.arp<<6)+baseFreqOff;
|
||||
chan[i].baseFreq=NOTE_LINEAR(chan[i].std.arp);
|
||||
} else {
|
||||
chan[i].baseFreq=((chan[i].note+(signed char)chan[i].std.arp)<<6)+baseFreqOff;
|
||||
chan[i].baseFreq=NOTE_LINEAR(chan[i].note+(signed char)chan[i].std.arp);
|
||||
}
|
||||
}
|
||||
chan[i].freqChanged=true;
|
||||
} else {
|
||||
if (chan[i].std.arpMode && chan[i].std.finishedArp) {
|
||||
chan[i].baseFreq=(chan[i].note<<6)+baseFreqOff;
|
||||
chan[i].baseFreq=NOTE_LINEAR(chan[i].note);
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
}
|
||||
|
@ -446,7 +448,7 @@ int DivPlatformArcade::dispatch(DivCommand c) {
|
|||
chan[c.chan].insChanged=false;
|
||||
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=(c.value<<6)+baseFreqOff;
|
||||
chan[c.chan].baseFreq=NOTE_LINEAR(c.value);
|
||||
chan[c.chan].note=c.value;
|
||||
chan[c.chan].freqChanged=true;
|
||||
}
|
||||
|
@ -510,7 +512,7 @@ int DivPlatformArcade::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
int destFreq=(c.value2<<6)+baseFreqOff;
|
||||
int destFreq=NOTE_LINEAR(c.value2);
|
||||
int newFreq;
|
||||
bool return2=false;
|
||||
if (destFreq>chan[c.chan].baseFreq) {
|
||||
|
@ -535,7 +537,7 @@ int DivPlatformArcade::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
case DIV_CMD_LEGATO: {
|
||||
chan[c.chan].baseFreq=(c.value<<6)+baseFreqOff;
|
||||
chan[c.chan].baseFreq=NOTE_LINEAR(c.value);
|
||||
chan[c.chan].freqChanged=true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -138,6 +138,13 @@ void DivPlatformOPLL::tick() {
|
|||
}
|
||||
}
|
||||
|
||||
if (chan[i].std.hadWave && chan[i].state.opllPreset!=16) {
|
||||
chan[i].state.opllPreset=chan[i].std.wave;
|
||||
if (i<9) {
|
||||
rWrite(0x30+i,((15-(chan[i].outVol*(15-chan[i].state.op[1].tl))/15)&15)|(chan[i].state.opllPreset<<4));
|
||||
}
|
||||
}
|
||||
|
||||
if (chan[i].state.opllPreset==0) {
|
||||
if (chan[i].std.hadAlg) { // SUS
|
||||
chan[i].state.alg=chan[i].std.alg;
|
||||
|
|
|
@ -1465,7 +1465,14 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
|||
memset(out[1],0,size*sizeof(float));
|
||||
}
|
||||
|
||||
isBusy.lock();
|
||||
if (softLocked) {
|
||||
if (!isBusy.try_lock()) {
|
||||
logV("audio is soft-locked (%d)\n",softLockCount++);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
isBusy.lock();
|
||||
}
|
||||
got.bufsize=size;
|
||||
|
||||
if (out!=NULL && ((sPreview.sample>=0 && sPreview.sample<(int)song.sample.size()) || (sPreview.wave>=0 && sPreview.wave<(int)song.wave.size()))) {
|
||||
|
|
|
@ -477,7 +477,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop) {
|
|||
stop();
|
||||
repeatPattern=false;
|
||||
setOrder(0);
|
||||
isBusy.lock();
|
||||
BUSY_BEGIN_SOFT;
|
||||
double origRate=got.rate;
|
||||
got.rate=44100;
|
||||
// determine loop point
|
||||
|
@ -1305,6 +1305,6 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop) {
|
|||
|
||||
logI("%d register writes total.\n",writeCount);
|
||||
|
||||
isBusy.unlock();
|
||||
BUSY_END;
|
||||
return w;
|
||||
}
|
||||
|
|
|
@ -2269,8 +2269,11 @@ bool FurnaceGUI::loop() {
|
|||
}
|
||||
break;
|
||||
case GUI_FILE_SAMPLE_OPEN:
|
||||
e->addSampleFromFile(copyOfName.c_str());
|
||||
MARK_MODIFIED;
|
||||
if (e->addSampleFromFile(copyOfName.c_str())==-1) {
|
||||
showError(e->getLastError());
|
||||
} else {
|
||||
MARK_MODIFIED;
|
||||
}
|
||||
break;
|
||||
case GUI_FILE_SAMPLE_SAVE:
|
||||
if (curSample>=0 && curSample<(int)e->song.sample.size()) {
|
||||
|
|
|
@ -1640,22 +1640,27 @@ void FurnaceGUI::drawInsEdit() {
|
|||
}
|
||||
bool dutyIsRel=(ins->type==DIV_INS_C64 && !ins->c64.dutyIsAbs);
|
||||
|
||||
const char* waveLabel="Waveform";
|
||||
int waveMax=(ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930 || ins->type==DIV_INS_VERA)?3:63;
|
||||
bool bitMode=false;
|
||||
if (ins->type==DIV_INS_C64 || ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930 || ins->type==DIV_INS_SAA1099) {
|
||||
bitMode=true;
|
||||
}
|
||||
if (ins->type==DIV_INS_STD) waveMax=0;
|
||||
if (ins->type==DIV_INS_TIA || ins->type==DIV_INS_VIC) waveMax=15;
|
||||
if (ins->type==DIV_INS_TIA || ins->type==DIV_INS_VIC || ins->type==DIV_INS_OPLL) waveMax=15;
|
||||
if (ins->type==DIV_INS_C64) waveMax=4;
|
||||
if (ins->type==DIV_INS_SAA1099) waveMax=2;
|
||||
if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPLL || ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPZ) waveMax=0;
|
||||
if (ins->type==DIV_INS_FM || ins->type==DIV_INS_OPL || ins->type==DIV_INS_OPZ) waveMax=0;
|
||||
if (ins->type==DIV_INS_MIKEY) waveMax=0;
|
||||
if (ins->type==DIV_INS_PET) {
|
||||
waveMax=8;
|
||||
bitMode=true;
|
||||
}
|
||||
|
||||
if (ins->type==DIV_INS_OPLL) {
|
||||
waveLabel="Patch";
|
||||
}
|
||||
|
||||
const char** waveNames=NULL;
|
||||
if (ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930 || ins->type==DIV_INS_SAA1099) waveNames=ayShapeBits;
|
||||
if (ins->type==DIV_INS_C64) waveNames=c64ShapeBits;
|
||||
|
@ -1695,7 +1700,7 @@ void FurnaceGUI::drawInsEdit() {
|
|||
}
|
||||
}
|
||||
if (waveMax>0) {
|
||||
NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,ins->std.waveMacroRel,0,waveMax,"wave","Waveform",bitMode?64:160,ins->std.waveMacroOpen,bitMode,waveNames,false,NULL,0,0,((ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930)?1:0),NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[3],0,waveMax,NULL,false);
|
||||
NORMAL_MACRO(ins->std.waveMacro,ins->std.waveMacroLen,ins->std.waveMacroLoop,ins->std.waveMacroRel,0,waveMax,"wave",waveLabel,bitMode?64:160,ins->std.waveMacroOpen,bitMode,waveNames,false,NULL,0,0,((ins->type==DIV_INS_AY || ins->type==DIV_INS_AY8930)?1:0),NULL,uiColors[GUI_COLOR_MACRO_WAVE],mmlString[3],0,waveMax,NULL,false);
|
||||
}
|
||||
if (ex1Max>0) {
|
||||
if (ins->type==DIV_INS_C64) {
|
||||
|
|
18
src/log.cpp
18
src/log.cpp
|
@ -17,10 +17,28 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
// TODO: improve these routines to allow logging to memory for eventual log window!
|
||||
|
||||
#include "ta-log.h"
|
||||
|
||||
int logLevel=LOGLEVEL_INFO;
|
||||
|
||||
int logV(const char* format, ...) {
|
||||
va_list va;
|
||||
int ret;
|
||||
if (logLevel<LOGLEVEL_TRACE) return 0;
|
||||
#ifdef _WIN32
|
||||
printf("[trace] ");
|
||||
#else
|
||||
printf("\x1b[1;37m[trace]\x1b[m ");
|
||||
#endif
|
||||
va_start(va,format);
|
||||
ret=vprintf(format,va);
|
||||
va_end(va);
|
||||
fflush(stdout);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int logD(const char* format, ...) {
|
||||
va_list va;
|
||||
int ret;
|
||||
|
|
|
@ -109,7 +109,9 @@ bool pConsole(String val) {
|
|||
}
|
||||
|
||||
bool pLogLevel(String val) {
|
||||
if (val=="debug") {
|
||||
if (val=="trace") {
|
||||
logLevel=LOGLEVEL_TRACE;
|
||||
} else if (val=="debug") {
|
||||
logLevel=LOGLEVEL_DEBUG;
|
||||
} else if (val=="info") {
|
||||
logLevel=LOGLEVEL_INFO;
|
||||
|
@ -118,7 +120,7 @@ bool pLogLevel(String val) {
|
|||
} else if (val=="error") {
|
||||
logLevel=LOGLEVEL_ERROR;
|
||||
} else {
|
||||
logE("invalid value for loglevel! valid values are: debug, info, warning, error.\n");
|
||||
logE("invalid value for loglevel! valid values are: trace, debug, info, warning, error.\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -26,9 +26,11 @@
|
|||
#define LOGLEVEL_WARN 1
|
||||
#define LOGLEVEL_INFO 2
|
||||
#define LOGLEVEL_DEBUG 3
|
||||
#define LOGLEVEL_TRACE 4
|
||||
|
||||
extern int logLevel;
|
||||
|
||||
int logV(const char* format, ...);
|
||||
int logD(const char* format, ...);
|
||||
int logI(const char* format, ...);
|
||||
int logW(const char* format, ...);
|
||||
|
|
Loading…
Reference in a new issue