Merge branch 'master' of https://github.com/tildearrow/furnace into es5506_alt
This commit is contained in:
commit
536c345763
137 changed files with 2912 additions and 1818 deletions
|
|
@ -77,6 +77,15 @@ const char* DivEngine::getEffectDesc(unsigned char effect, int chan, bool notNul
|
|||
return "81xx: Set panning (left channel)";
|
||||
case 0x82:
|
||||
return "82xx: Set panning (right channel)";
|
||||
case 0x88:
|
||||
return "88xx: Set panning (rear channels; x: left; y: right)";
|
||||
break;
|
||||
case 0x89:
|
||||
return "89xx: Set panning (rear left channel)";
|
||||
break;
|
||||
case 0x8a:
|
||||
return "8Axx: Set panning (rear right channel)";
|
||||
break;
|
||||
case 0xc0: case 0xc1: case 0xc2: case 0xc3:
|
||||
return "Cxxx: Set tick rate (hz)";
|
||||
case 0xe0:
|
||||
|
|
@ -435,6 +444,7 @@ void writePackedCommandValues(SafeWriter* w, const DivCommand& c) {
|
|||
case DIV_CMD_FM_FINE:
|
||||
case DIV_CMD_AY_IO_WRITE:
|
||||
case DIV_CMD_AY_AUTO_PWM:
|
||||
case DIV_CMD_SURROUND_PANNING:
|
||||
w->writeC(2); // length
|
||||
w->writeC(c.value);
|
||||
w->writeC(c.value2);
|
||||
|
|
@ -897,11 +907,7 @@ void DivEngine::runExportThread() {
|
|||
for (int i=0; i<song.systemLen; i++) {
|
||||
sf[i]=NULL;
|
||||
si[i].samplerate=got.rate;
|
||||
if (disCont[i].dispatch->isStereo()) {
|
||||
si[i].channels=2;
|
||||
} else {
|
||||
si[i].channels=1;
|
||||
}
|
||||
si[i].channels=disCont[i].dispatch->getOutputCount();
|
||||
si[i].format=SF_FORMAT_WAV|SF_FORMAT_PCM_16;
|
||||
}
|
||||
|
||||
|
|
@ -944,11 +950,12 @@ void DivEngine::runExportThread() {
|
|||
if (isFadingOut) {
|
||||
double mul=(1.0-((double)curFadeOutSample/(double)fadeOutSamples));
|
||||
for (int i=0; i<song.systemLen; i++) {
|
||||
if (!disCont[i].dispatch->isStereo()) {
|
||||
sysBuf[i][j]=(double)disCont[i].bbOut[0][j]*mul;
|
||||
} else {
|
||||
sysBuf[i][j<<1]=(double)disCont[i].bbOut[0][j]*mul;
|
||||
sysBuf[i][1+(j<<1)]=(double)disCont[i].bbOut[1][j]*mul;
|
||||
for (int k=0; k<si[i].channels; k++) {
|
||||
if (disCont[i].bbOut[k]==NULL) {
|
||||
sysBuf[i][k+(j*si[i].channels)]=0;
|
||||
} else {
|
||||
sysBuf[i][k+(j*si[i].channels)]=(double)disCont[i].bbOut[k][j]*mul;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (++curFadeOutSample>=fadeOutSamples) {
|
||||
|
|
@ -957,11 +964,12 @@ void DivEngine::runExportThread() {
|
|||
}
|
||||
} else {
|
||||
for (int i=0; i<song.systemLen; i++) {
|
||||
if (!disCont[i].dispatch->isStereo()) {
|
||||
sysBuf[i][j]=disCont[i].bbOut[0][j];
|
||||
} else {
|
||||
sysBuf[i][j<<1]=disCont[i].bbOut[0][j];
|
||||
sysBuf[i][1+(j<<1)]=disCont[i].bbOut[1][j];
|
||||
for (int k=0; k<si[i].channels; k++) {
|
||||
if (disCont[i].bbOut[k]==NULL) {
|
||||
sysBuf[i][k+(j*si[i].channels)]=0;
|
||||
} else {
|
||||
sysBuf[i][k+(j*si[i].channels)]=disCont[i].bbOut[k][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lastLoopPos>-1 && j>=lastLoopPos && totalLoops>=exportLoopCount) {
|
||||
|
|
@ -1333,8 +1341,8 @@ String DivEngine::decodeSysDesc(String desc) {
|
|||
int val=0;
|
||||
int curStage=0;
|
||||
int sysID=0;
|
||||
int sysVol=0;
|
||||
int sysPan=0;
|
||||
float sysVol=0;
|
||||
float sysPan=0;
|
||||
int sysFlags=0;
|
||||
int curSys=0;
|
||||
desc+=' '; // ha
|
||||
|
|
@ -1349,24 +1357,25 @@ String DivEngine::decodeSysDesc(String desc) {
|
|||
curStage++;
|
||||
break;
|
||||
case 1:
|
||||
sysVol=val;
|
||||
sysVol=(float)val/64.0f;
|
||||
curStage++;
|
||||
break;
|
||||
case 2:
|
||||
sysPan=val;
|
||||
sysPan=(float)val/127.0f;
|
||||
curStage++;
|
||||
break;
|
||||
case 3:
|
||||
sysFlags=val;
|
||||
|
||||
if (sysID!=0) {
|
||||
if (sysVol<-128) sysVol=-128;
|
||||
if (sysVol>127) sysVol=127;
|
||||
if (sysPan<-128) sysPan=-128;
|
||||
if (sysPan>127) sysPan=127;
|
||||
if (sysVol<-1.0f) sysVol=-1.0f;
|
||||
if (sysVol>1.0f) sysVol=1.0f;
|
||||
if (sysPan<-1.0f) sysPan=-1.0f;
|
||||
if (sysPan>1.0f) sysPan=1.0f;
|
||||
newDesc.set(fmt::sprintf("id%d",curSys),sysID);
|
||||
newDesc.set(fmt::sprintf("vol%d",curSys),sysVol);
|
||||
newDesc.set(fmt::sprintf("pan%d",curSys),sysPan);
|
||||
newDesc.set(fmt::sprintf("fr%d",curSys),0.0f);
|
||||
DivConfig newFlagsC;
|
||||
newFlagsC.clear();
|
||||
convertOldFlags((unsigned int)sysFlags,newFlagsC,systemFromFileFur(sysID));
|
||||
|
|
@ -1396,7 +1405,7 @@ String DivEngine::decodeSysDesc(String desc) {
|
|||
return newDesc.toBase64();
|
||||
}
|
||||
|
||||
void DivEngine::initSongWithDesc(const char* description, bool inBase64) {
|
||||
void DivEngine::initSongWithDesc(const char* description, bool inBase64, bool oldVol) {
|
||||
int chanCount=0;
|
||||
DivConfig c;
|
||||
if (inBase64) {
|
||||
|
|
@ -1415,9 +1424,16 @@ void DivEngine::initSongWithDesc(const char* description, bool inBase64) {
|
|||
song.system[index]=DIV_SYSTEM_NULL;
|
||||
break;
|
||||
}
|
||||
song.systemVol[index]=c.getInt(fmt::sprintf("vol%d",index),DIV_SYSTEM_NULL);
|
||||
song.systemPan[index]=c.getInt(fmt::sprintf("pan%d",index),DIV_SYSTEM_NULL);
|
||||
song.systemVol[index]=c.getFloat(fmt::sprintf("vol%d",index),1.0f);
|
||||
song.systemPan[index]=c.getFloat(fmt::sprintf("pan%d",index),0.0f);
|
||||
song.systemPanFR[index]=c.getFloat(fmt::sprintf("fr%d",index),0.0f);
|
||||
song.systemFlags[index].clear();
|
||||
|
||||
if (oldVol) {
|
||||
song.systemVol[index]/=64.0f;
|
||||
song.systemPan[index]/=127.0f;
|
||||
}
|
||||
|
||||
String flags=c.getString(fmt::sprintf("flags%d",index),"");
|
||||
song.systemFlags[index].loadFromBase64(flags.c_str());
|
||||
}
|
||||
|
|
@ -1667,14 +1683,36 @@ bool DivEngine::addSystem(DivSystem which) {
|
|||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
song.system[song.systemLen]=which;
|
||||
song.systemVol[song.systemLen]=64;
|
||||
song.systemVol[song.systemLen]=1.0;
|
||||
song.systemPan[song.systemLen]=0;
|
||||
song.systemPanFR[song.systemLen]=0;
|
||||
song.systemFlags[song.systemLen++].clear();
|
||||
recalcChans();
|
||||
saveLock.unlock();
|
||||
BUSY_END;
|
||||
initDispatch();
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
if (song.patchbayAuto) {
|
||||
autoPatchbay();
|
||||
} else {
|
||||
int i=song.systemLen-1;
|
||||
if (disCont[i].dispatch!=NULL) {
|
||||
unsigned int outs=disCont[i].dispatch->getOutputCount();
|
||||
if (outs>16) outs=16;
|
||||
if (outs<2) {
|
||||
for (unsigned int j=0; j<DIV_MAX_OUTPUTS; j++) {
|
||||
song.patchbay.push_back((i<<20)|j);
|
||||
}
|
||||
} else {
|
||||
for (unsigned int j=0; j<outs; j++) {
|
||||
|
||||
song.patchbay.push_back((i<<20)|(j<<16)|j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
saveLock.unlock();
|
||||
renderSamples();
|
||||
reset();
|
||||
BUSY_END;
|
||||
|
|
@ -1707,12 +1745,21 @@ bool DivEngine::removeSystem(int index, bool preserveOrder) {
|
|||
}
|
||||
}
|
||||
|
||||
// patchbay
|
||||
for (size_t i=0; i<song.patchbay.size(); i++) {
|
||||
if (((song.patchbay[i]>>20)&0xfff)==(unsigned int)index) {
|
||||
song.patchbay.erase(song.patchbay.begin()+i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
song.system[index]=DIV_SYSTEM_NULL;
|
||||
song.systemLen--;
|
||||
for (int i=index; i<song.systemLen; i++) {
|
||||
song.system[i]=song.system[i+1];
|
||||
song.systemVol[i]=song.systemVol[i+1];
|
||||
song.systemPan[i]=song.systemPan[i+1];
|
||||
song.systemPanFR[i]=song.systemPanFR[i+1];
|
||||
song.systemFlags[i]=song.systemFlags[i+1];
|
||||
}
|
||||
recalcChans();
|
||||
|
|
@ -1827,23 +1874,36 @@ bool DivEngine::swapSystem(int src, int dest, bool preserveOrder) {
|
|||
}
|
||||
|
||||
DivSystem srcSystem=song.system[src];
|
||||
float srcVol=song.systemVol[src];
|
||||
float srcPan=song.systemPan[src];
|
||||
float srcPanFR=song.systemPanFR[src];
|
||||
|
||||
song.system[src]=song.system[dest];
|
||||
song.system[dest]=srcSystem;
|
||||
|
||||
song.systemVol[src]^=song.systemVol[dest];
|
||||
song.systemVol[dest]^=song.systemVol[src];
|
||||
song.systemVol[src]^=song.systemVol[dest];
|
||||
song.systemVol[src]=song.systemVol[dest];
|
||||
song.systemVol[dest]=srcVol;
|
||||
|
||||
song.systemPan[src]^=song.systemPan[dest];
|
||||
song.systemPan[dest]^=song.systemPan[src];
|
||||
song.systemPan[src]^=song.systemPan[dest];
|
||||
song.systemPan[src]=song.systemPan[dest];
|
||||
song.systemPan[dest]=srcPan;
|
||||
|
||||
song.systemPanFR[src]=song.systemPanFR[dest];
|
||||
song.systemPanFR[dest]=srcPanFR;
|
||||
|
||||
// I am kinda scared to use std::swap
|
||||
DivConfig oldFlags=song.systemFlags[src];
|
||||
song.systemFlags[src]=song.systemFlags[dest];
|
||||
song.systemFlags[dest]=oldFlags;
|
||||
|
||||
// patchbay
|
||||
for (unsigned int& i: song.patchbay) {
|
||||
if (((i>>20)&0xfff)==(unsigned int)src) {
|
||||
i=(i&(~0xfff00000))|((unsigned int)dest<<20);
|
||||
} else if (((i>>20)&0xfff)==(unsigned int)dest) {
|
||||
i=(i&(~0xfff00000))|((unsigned int)src<<20);
|
||||
}
|
||||
}
|
||||
|
||||
recalcChans();
|
||||
saveLock.unlock();
|
||||
BUSY_END;
|
||||
|
|
@ -1904,10 +1964,11 @@ String DivEngine::getPlaybackDebugInfo() {
|
|||
"speed1: %d\n"
|
||||
"speed2: %d\n"
|
||||
"tempoAccum: %d\n"
|
||||
"totalProcessed: %d\n",
|
||||
"totalProcessed: %d\n"
|
||||
"bufferPos: %d\n",
|
||||
curOrder,prevOrder,curRow,prevRow,ticks,subticks,totalLoops,lastLoopPos,nextSpeed,divider,cycles,clockDrift,
|
||||
changeOrd,changePos,totalSeconds,totalTicks,totalTicksR,totalCmds,lastCmds,cmdsPerSecond,globalPitch,
|
||||
(int)extValue,(int)speed1,(int)speed2,(int)tempoAccum,(int)totalProcessed
|
||||
(int)extValue,(int)speed1,(int)speed2,(int)tempoAccum,(int)totalProcessed,(int)bufferPos
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -3752,6 +3813,102 @@ bool DivEngine::moveSampleDown(int which) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void DivEngine::autoPatchbay() {
|
||||
song.patchbay.clear();
|
||||
for (unsigned int i=0; i<song.systemLen; i++) {
|
||||
if (disCont[i].dispatch==NULL) continue;
|
||||
|
||||
unsigned int outs=disCont[i].dispatch->getOutputCount();
|
||||
if (outs>16) outs=16;
|
||||
if (outs<2) {
|
||||
for (unsigned int j=0; j<DIV_MAX_OUTPUTS; j++) {
|
||||
song.patchbay.push_back((i<<20)|j);
|
||||
}
|
||||
} else {
|
||||
for (unsigned int j=0; j<outs; j++) {
|
||||
|
||||
song.patchbay.push_back((i<<20)|(j<<16)|j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// wave/sample preview
|
||||
for (unsigned int j=0; j<DIV_MAX_OUTPUTS; j++) {
|
||||
song.patchbay.push_back(0xffd00000|j);
|
||||
}
|
||||
|
||||
// metronome
|
||||
for (unsigned int j=0; j<DIV_MAX_OUTPUTS; j++) {
|
||||
song.patchbay.push_back(0xffe00000|j);
|
||||
}
|
||||
}
|
||||
|
||||
void DivEngine::autoPatchbayP() {
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
autoPatchbay();
|
||||
saveLock.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
bool DivEngine::patchConnect(unsigned int src, unsigned int dest) {
|
||||
unsigned int armed=(src<<16)|(dest&0xffff);
|
||||
for (unsigned int i: song.patchbay) {
|
||||
if (i==armed) return false;
|
||||
}
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
song.patchbay.push_back(armed);
|
||||
song.patchbayAuto=false;
|
||||
saveLock.unlock();
|
||||
BUSY_END;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DivEngine::patchDisconnect(unsigned int src, unsigned int dest) {
|
||||
unsigned int armed=(src<<16)|(dest&0xffff);
|
||||
for (auto i=song.patchbay.begin(); i!=song.patchbay.end(); i++) {
|
||||
if (*i==armed) {
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
song.patchbay.erase(i);
|
||||
song.patchbayAuto=false;
|
||||
saveLock.unlock();
|
||||
BUSY_END;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DivEngine::patchDisconnectAll(unsigned int portSet) {
|
||||
BUSY_BEGIN;
|
||||
saveLock.lock();
|
||||
|
||||
if (portSet&0x1000) {
|
||||
portSet&=0xfff;
|
||||
|
||||
for (size_t i=0; i<song.patchbay.size(); i++) {
|
||||
if ((song.patchbay[i]&0xfff0)==(portSet<<4)) {
|
||||
song.patchbay.erase(song.patchbay.begin()+i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
portSet&=0xfff;
|
||||
|
||||
for (size_t i=0; i<song.patchbay.size(); i++) {
|
||||
if ((song.patchbay[i]&0xfff00000)==(portSet<<20)) {
|
||||
song.patchbay.erase(song.patchbay.begin()+i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
saveLock.unlock();
|
||||
BUSY_END;
|
||||
}
|
||||
|
||||
void DivEngine::noteOn(int chan, int ins, int note, int vol) {
|
||||
if (chan<0 || chan>=chans) return;
|
||||
BUSY_BEGIN;
|
||||
|
|
@ -3891,6 +4048,14 @@ void DivEngine::updateSysFlags(int system, bool restart) {
|
|||
BUSY_BEGIN_SOFT;
|
||||
disCont[system].dispatch->setFlags(song.systemFlags[system]);
|
||||
disCont[system].setRates(got.rate);
|
||||
|
||||
// patchbay
|
||||
if (song.patchbayAuto) {
|
||||
saveLock.lock();
|
||||
autoPatchbay();
|
||||
saveLock.unlock();
|
||||
}
|
||||
|
||||
if (restart && isPlaying()) {
|
||||
playSub(false);
|
||||
}
|
||||
|
|
@ -4055,6 +4220,11 @@ void DivEngine::initDispatch() {
|
|||
disCont[i].setRates(got.rate);
|
||||
disCont[i].setQuality(lowQuality);
|
||||
}
|
||||
if (song.patchbayAuto) {
|
||||
saveLock.lock();
|
||||
autoPatchbay();
|
||||
saveLock.unlock();
|
||||
}
|
||||
recalcChans();
|
||||
BUSY_END;
|
||||
}
|
||||
|
|
@ -4153,10 +4323,13 @@ bool DivEngine::initAudioBackend() {
|
|||
want.rate=getConfInt("audioRate",44100);
|
||||
want.fragments=2;
|
||||
want.inChans=0;
|
||||
want.outChans=2;
|
||||
want.outChans=getConfInt("audioChans",2);
|
||||
want.outFormat=TA_AUDIO_FORMAT_F32;
|
||||
want.name="Furnace";
|
||||
|
||||
if (want.outChans<1) want.outChans=1;
|
||||
if (want.outChans>16) want.outChans=16;
|
||||
|
||||
output->setCallback(process,this);
|
||||
|
||||
if (!output->init(want,got)) {
|
||||
|
|
@ -4167,6 +4340,13 @@ bool DivEngine::initAudioBackend() {
|
|||
return false;
|
||||
}
|
||||
|
||||
for (int i=0; i<got.outChans; i++) {
|
||||
if (oscBuf[i]==NULL) {
|
||||
oscBuf[i]=new float[32768];
|
||||
}
|
||||
memset(oscBuf[i],0,32768*sizeof(float));
|
||||
}
|
||||
|
||||
if (output->initMidi(false)) {
|
||||
midiIns=output->midiIn->listDevices();
|
||||
midiOuts=output->midiOut->listDevices();
|
||||
|
|
@ -4248,13 +4428,15 @@ bool DivEngine::init() {
|
|||
if (!hasLoadedSomething) {
|
||||
logD("setting default preset");
|
||||
String preset=getConfString("initialSys2","");
|
||||
bool oldVol=getConfInt("configVersion",DIV_ENGINE_VERSION)<135;
|
||||
if (preset.empty()) {
|
||||
// try loading old preset
|
||||
preset=decodeSysDesc(getConfString("initialSys",""));
|
||||
oldVol=false;
|
||||
}
|
||||
logD("preset size %ld",preset.size());
|
||||
if (preset.size()>0 && (preset.size()&3)==0) {
|
||||
initSongWithDesc(preset.c_str());
|
||||
initSongWithDesc(preset.c_str(),true,oldVol);
|
||||
}
|
||||
String sysName=getConfString("initialSysName","");
|
||||
if (sysName=="") {
|
||||
|
|
@ -4283,6 +4465,9 @@ bool DivEngine::init() {
|
|||
|
||||
samp_bbIn=new short[32768];
|
||||
samp_bbInLen=32768;
|
||||
|
||||
metroBuf=new float[8192];
|
||||
metroBufLen=8192;
|
||||
|
||||
blip_set_rates(samp_bb,44100,got.rate);
|
||||
|
||||
|
|
@ -4299,12 +4484,6 @@ bool DivEngine::init() {
|
|||
keyHit[i]=false;
|
||||
}
|
||||
|
||||
oscBuf[0]=new float[32768];
|
||||
oscBuf[1]=new float[32768];
|
||||
|
||||
memset(oscBuf[0],0,32768*sizeof(float));
|
||||
memset(oscBuf[1],0,32768*sizeof(float));
|
||||
|
||||
initDispatch();
|
||||
renderSamples();
|
||||
reset();
|
||||
|
|
@ -4313,6 +4492,10 @@ bool DivEngine::init() {
|
|||
if (!haveAudio) {
|
||||
return false;
|
||||
} else {
|
||||
if (output==NULL) {
|
||||
logE("output is NULL!");
|
||||
return false;
|
||||
}
|
||||
if (!output->setRun(true)) {
|
||||
logE("error while activating!");
|
||||
return false;
|
||||
|
|
@ -4327,8 +4510,14 @@ bool DivEngine::quit() {
|
|||
logI("saving config.");
|
||||
saveConf();
|
||||
active=false;
|
||||
delete[] oscBuf[0];
|
||||
delete[] oscBuf[1];
|
||||
for (int i=0; i<DIV_MAX_OUTPUTS; i++) {
|
||||
if (oscBuf[i]!=NULL) delete[] oscBuf[i];
|
||||
}
|
||||
if (metroBuf!=NULL) {
|
||||
delete[] metroBuf;
|
||||
metroBuf=NULL;
|
||||
metroBufLen=0;
|
||||
}
|
||||
if (yrw801ROM!=NULL) delete[] yrw801ROM;
|
||||
if (tg100ROM!=NULL) delete[] tg100ROM;
|
||||
if (mu5ROM!=NULL) delete[] mu5ROM;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue