earliest multi-chip support
no saving, no adding chips yet... only the beginning
This commit is contained in:
parent
7080434ed4
commit
06c7ac92a2
|
@ -17,6 +17,32 @@ void DivDispatchContainer::setRates(double gotRate) {
|
||||||
blip_set_rates(bb[1],dispatch->rate,gotRate);
|
blip_set_rates(bb[1],dispatch->rate,gotRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivDispatchContainer::acquire(size_t offset, size_t count) {
|
||||||
|
dispatch->acquire(bbIn[0],bbIn[1],offset,count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivDispatchContainer::fillBuf(size_t runtotal, size_t size) {
|
||||||
|
for (size_t i=0; i<runtotal; i++) {
|
||||||
|
temp[0]=bbIn[0][i];
|
||||||
|
blip_add_delta(bb[0],i,temp[0]-prevSample[0]);
|
||||||
|
prevSample[0]=temp[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dispatch->isStereo()) for (size_t i=0; i<runtotal; i++) {
|
||||||
|
temp[1]=bbIn[1][i];
|
||||||
|
blip_add_delta(bb[1],i,temp[1]-prevSample[1]);
|
||||||
|
prevSample[1]=temp[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
blip_end_frame(bb[0],runtotal);
|
||||||
|
blip_read_samples(bb[0],bbOut[0],size,0);
|
||||||
|
|
||||||
|
if (dispatch->isStereo()) {
|
||||||
|
blip_end_frame(bb[1],runtotal);
|
||||||
|
blip_read_samples(bb[1],bbOut[1],size,0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DivDispatchContainer::clear() {
|
void DivDispatchContainer::clear() {
|
||||||
blip_clear(bb[0]);
|
blip_clear(bb[0]);
|
||||||
blip_clear(bb[1]);
|
blip_clear(bb[1]);
|
||||||
|
|
|
@ -1940,7 +1940,7 @@ void DivEngine::addOrder(bool duplicate, bool where) {
|
||||||
if (song.ordersLen>=0x7e) return;
|
if (song.ordersLen>=0x7e) return;
|
||||||
isBusy.lock();
|
isBusy.lock();
|
||||||
if (duplicate) {
|
if (duplicate) {
|
||||||
for (int i=0; i<32; i++) {
|
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||||
order[i]=song.orders.ord[i][curOrder];
|
order[i]=song.orders.ord[i][curOrder];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1960,12 +1960,12 @@ void DivEngine::addOrder(bool duplicate, bool where) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (where) { // at the end
|
if (where) { // at the end
|
||||||
for (int i=0; i<32; i++) {
|
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||||
song.orders.ord[i][song.ordersLen]=order[i];
|
song.orders.ord[i][song.ordersLen]=order[i];
|
||||||
}
|
}
|
||||||
song.ordersLen++;
|
song.ordersLen++;
|
||||||
} else { // after current order
|
} else { // after current order
|
||||||
for (int i=0; i<32; i++) {
|
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||||
for (int j=song.ordersLen; j>curOrder; j--) {
|
for (int j=song.ordersLen; j>curOrder; j--) {
|
||||||
song.orders.ord[i][j]=song.orders.ord[i][j-1];
|
song.orders.ord[i][j]=song.orders.ord[i][j-1];
|
||||||
}
|
}
|
||||||
|
@ -1983,7 +1983,7 @@ void DivEngine::addOrder(bool duplicate, bool where) {
|
||||||
void DivEngine::deleteOrder() {
|
void DivEngine::deleteOrder() {
|
||||||
if (song.ordersLen<=1) return;
|
if (song.ordersLen<=1) return;
|
||||||
isBusy.lock();
|
isBusy.lock();
|
||||||
for (int i=0; i<32; 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++) {
|
||||||
song.orders.ord[i][j]=song.orders.ord[i][j+1];
|
song.orders.ord[i][j]=song.orders.ord[i][j+1];
|
||||||
}
|
}
|
||||||
|
@ -2002,7 +2002,7 @@ void DivEngine::moveOrderUp() {
|
||||||
isBusy.unlock();
|
isBusy.unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i=0; i<32; i++) {
|
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||||
song.orders.ord[i][curOrder]^=song.orders.ord[i][curOrder-1];
|
song.orders.ord[i][curOrder]^=song.orders.ord[i][curOrder-1];
|
||||||
song.orders.ord[i][curOrder-1]^=song.orders.ord[i][curOrder];
|
song.orders.ord[i][curOrder-1]^=song.orders.ord[i][curOrder];
|
||||||
song.orders.ord[i][curOrder]^=song.orders.ord[i][curOrder-1];
|
song.orders.ord[i][curOrder]^=song.orders.ord[i][curOrder-1];
|
||||||
|
@ -2020,7 +2020,7 @@ void DivEngine::moveOrderDown() {
|
||||||
isBusy.unlock();
|
isBusy.unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i=0; i<32; i++) {
|
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||||
song.orders.ord[i][curOrder]^=song.orders.ord[i][curOrder+1];
|
song.orders.ord[i][curOrder]^=song.orders.ord[i][curOrder+1];
|
||||||
song.orders.ord[i][curOrder+1]^=song.orders.ord[i][curOrder];
|
song.orders.ord[i][curOrder+1]^=song.orders.ord[i][curOrder];
|
||||||
song.orders.ord[i][curOrder]^=song.orders.ord[i][curOrder+1];
|
song.orders.ord[i][curOrder]^=song.orders.ord[i][curOrder+1];
|
||||||
|
@ -2278,15 +2278,17 @@ bool DivEngine::init(String outName) {
|
||||||
while (remainingLoops) {
|
while (remainingLoops) {
|
||||||
nextBuf(NULL,NULL,0,2,got.bufsize);
|
nextBuf(NULL,NULL,0,2,got.bufsize);
|
||||||
|
|
||||||
if (dispatch->isStereo()) {
|
for (int h=0; h<song.systemLen; h++) {
|
||||||
for (size_t i=0; i<got.bufsize; i++) {
|
if (disCont[h].dispatch->isStereo()) {
|
||||||
ilBuffer[i<<1]=bbOut[0][i];
|
for (size_t i=0; i<got.bufsize; i++) {
|
||||||
ilBuffer[1+(i<<1)]=bbOut[1][i];
|
ilBuffer[i<<1]=disCont[h].bbOut[0][i];
|
||||||
}
|
ilBuffer[1+(i<<1)]=disCont[h].bbOut[1][i];
|
||||||
} else {
|
}
|
||||||
for (size_t i=0; i<got.bufsize; i++) {
|
} else {
|
||||||
ilBuffer[i<<1]=bbOut[0][i];
|
for (size_t i=0; i<got.bufsize; i++) {
|
||||||
ilBuffer[1+(i<<1)]=bbOut[0][i];
|
ilBuffer[i<<1]=disCont[h].bbOut[0][i];
|
||||||
|
ilBuffer[1+(i<<1)]=disCont[h].bbOut[0][i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,8 @@ struct DivDispatchContainer {
|
||||||
int cycles, clockDrift;
|
int cycles, clockDrift;
|
||||||
|
|
||||||
void setRates(double gotRate);
|
void setRates(double gotRate);
|
||||||
|
void acquire(size_t offset, size_t count);
|
||||||
|
void fillBuf(size_t runtotal, size_t size);
|
||||||
void clear();
|
void clear();
|
||||||
void init(DivSystem sys, DivEngine* eng, int chanCount, double gotRate, bool pal);
|
void init(DivSystem sys, DivEngine* eng, int chanCount, double gotRate, bool pal);
|
||||||
void quit();
|
void quit();
|
||||||
|
|
|
@ -711,7 +711,7 @@ bool DivEngine::nextTick(bool noAccum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<song.systemLen; i++) {
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
DivDispatchContainer& dc=dispatch[i];
|
DivDispatchContainer& dc=disCont[i];
|
||||||
dc.cycles=dc.dispatch->rate/divider;
|
dc.cycles=dc.dispatch->rate/divider;
|
||||||
dc.clockDrift+=dc.dispatch->rate%divider;
|
dc.clockDrift+=dc.dispatch->rate%divider;
|
||||||
if (dc.clockDrift>=divider) {
|
if (dc.clockDrift>=divider) {
|
||||||
|
@ -858,26 +858,26 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
||||||
isBusy.lock();
|
isBusy.lock();
|
||||||
if (out!=NULL && sPreview.sample>=0 && sPreview.sample<(int)song.sample.size()) {
|
if (out!=NULL && sPreview.sample>=0 && sPreview.sample<(int)song.sample.size()) {
|
||||||
DivSample* s=song.sample[sPreview.sample];
|
DivSample* s=song.sample[sPreview.sample];
|
||||||
size_t prevtotal=blip_clocks_needed(bb[2],size);
|
size_t prevtotal=blip_clocks_needed(samp_bb,size);
|
||||||
|
|
||||||
for (size_t i=0; i<prevtotal; i++) {
|
for (size_t i=0; i<prevtotal; i++) {
|
||||||
if (sPreview.pos>=s->rendLength) {
|
if (sPreview.pos>=s->rendLength) {
|
||||||
temp[2]=0;
|
samp_temp=0;
|
||||||
} else {
|
} else {
|
||||||
temp[2]=s->rendData[sPreview.pos++];
|
samp_temp=s->rendData[sPreview.pos++];
|
||||||
}
|
}
|
||||||
if (s->depth==8) temp[2]<<=8;
|
if (s->depth==8) samp_temp<<=8;
|
||||||
blip_add_delta(bb[2],i,temp[2]-prevSample[2]);
|
blip_add_delta(samp_bb,i,samp_temp-samp_prevSample);
|
||||||
prevSample[2]=temp[2];
|
samp_prevSample=samp_temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sPreview.pos>=s->rendLength) sPreview.sample=-1;
|
if (sPreview.pos>=s->rendLength) sPreview.sample=-1;
|
||||||
|
|
||||||
blip_end_frame(bb[2],prevtotal);
|
blip_end_frame(samp_bb,prevtotal);
|
||||||
blip_read_samples(bb[2],bbOut[2],size,0);
|
blip_read_samples(samp_bb,samp_bbOut,size,0);
|
||||||
for (size_t i=0; i<size; i++) {
|
for (size_t i=0; i<size; i++) {
|
||||||
out[0][i]+=(float)bbOut[2][i]/32768.0;
|
out[0][i]+=(float)samp_bbOut[i]/32768.0;
|
||||||
out[1][i]+=(float)bbOut[2][i]/32768.0;
|
out[1][i]+=(float)samp_bbOut[i]/32768.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -887,14 +887,20 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
||||||
}
|
}
|
||||||
|
|
||||||
// logic starts here
|
// logic starts here
|
||||||
size_t runtotal=blip_clocks_needed(bb[0],size);
|
size_t runtotal[32];
|
||||||
|
size_t runLeft[32];
|
||||||
if (runtotal>bbInLen) {
|
size_t runPos[32];
|
||||||
delete bbIn[0];
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
delete bbIn[1];
|
runtotal[i]=blip_clocks_needed(disCont[i].bb[0],size);
|
||||||
bbIn[0]=new short[runtotal+256];
|
if (runtotal[i]>disCont[i].bbInLen) {
|
||||||
bbIn[1]=new short[runtotal+256];
|
delete disCont[i].bbIn[0];
|
||||||
bbInLen=runtotal+256;
|
delete disCont[i].bbIn[1];
|
||||||
|
disCont[i].bbIn[0]=new short[runtotal[i]+256];
|
||||||
|
disCont[i].bbIn[1]=new short[runtotal[i]+256];
|
||||||
|
disCont[i].bbInLen=runtotal[i]+256;
|
||||||
|
}
|
||||||
|
runLeft[i]=runtotal[i];
|
||||||
|
runPos[i]=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (metroTickLen<size) {
|
if (metroTickLen<size) {
|
||||||
|
@ -905,61 +911,58 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
||||||
|
|
||||||
memset(metroTick,0,size);
|
memset(metroTick,0,size);
|
||||||
|
|
||||||
size_t runLeft=runtotal;
|
while (true) {
|
||||||
size_t runPos=0;
|
bool allDone=true;
|
||||||
totalProcessed=0;
|
bool getOut=true;
|
||||||
while (runLeft) {
|
// 1. check whether we are done with all buffers
|
||||||
if (!remainingLoops) {
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
memset(bbIn[0]+runPos,0,runLeft*sizeof(short));
|
if (runLeft[i]>0) {
|
||||||
memset(bbIn[1]+runPos,0,runLeft*sizeof(short));
|
getOut=false;
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
if ((int)runLeft>=cycles) {
|
|
||||||
runLeft-=cycles;
|
|
||||||
dispatch->acquire(bbIn[0],bbIn[1],runPos,cycles);
|
|
||||||
runPos+=cycles;
|
|
||||||
unsigned int realPos=(runPos*size)/runtotal;
|
|
||||||
if (realPos>=size) realPos=size-1;
|
|
||||||
if (song.hilightA>0) {
|
|
||||||
if ((curRow%song.hilightA)==0 && ticks==1) metroTick[realPos]=1;
|
|
||||||
}
|
|
||||||
if (song.hilightB>0) {
|
|
||||||
if ((curRow%song.hilightB)==0 && ticks==1) metroTick[realPos]=2;
|
|
||||||
}
|
|
||||||
if (nextTick()) {
|
|
||||||
if (remainingLoops>0) {
|
|
||||||
remainingLoops--;
|
|
||||||
if (!remainingLoops) logI("end of song!\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dispatch->acquire(bbIn[0],bbIn[1],runPos,runLeft);
|
|
||||||
cycles-=runLeft;
|
|
||||||
runPos=runtotal;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (getOut) break;
|
||||||
|
|
||||||
|
// 2. check whether we gonna tick
|
||||||
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
|
if (disCont[i].cycles>0) {
|
||||||
|
allDone=false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allDone) {
|
||||||
|
// we have to tick
|
||||||
|
unsigned int realPos=(runPos[0]*size)/runtotal[0];
|
||||||
|
if (realPos>=size) realPos=size-1;
|
||||||
|
if (song.hilightA>0) {
|
||||||
|
if ((curRow%song.hilightA)==0 && ticks==1) metroTick[realPos]=1;
|
||||||
|
}
|
||||||
|
if (song.hilightB>0) {
|
||||||
|
if ((curRow%song.hilightB)==0 && ticks==1) metroTick[realPos]=2;
|
||||||
|
}
|
||||||
|
if (nextTick()) {
|
||||||
|
if (remainingLoops>0) {
|
||||||
|
remainingLoops--;
|
||||||
|
if (!remainingLoops) logI("end of song!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. fill buffers as needed
|
||||||
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
|
if (runLeft[i]<=0) continue;
|
||||||
|
int total=runLeft[i];
|
||||||
|
if (total>disCont[i].cycles) total=disCont[i].cycles;
|
||||||
|
runLeft[i]-=total;
|
||||||
|
disCont[i].cycles-=total;
|
||||||
|
disCont[i].acquire(runPos[i],total);
|
||||||
|
runPos[i]+=total;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
totalProcessed=(1+runPos)*got.rate/dispatch->rate;
|
totalProcessed=(1+runPos[0])*got.rate/disCont[0].dispatch->rate;
|
||||||
|
|
||||||
for (size_t i=0; i<runtotal; i++) {
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
temp[0]=bbIn[0][i];
|
disCont[i].fillBuf(runtotal[i],size);
|
||||||
blip_add_delta(bb[0],i,temp[0]-prevSample[0]);
|
|
||||||
prevSample[0]=temp[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dispatch->isStereo()) for (size_t i=0; i<runtotal; i++) {
|
|
||||||
temp[1]=bbIn[1][i];
|
|
||||||
blip_add_delta(bb[1],i,temp[1]-prevSample[1]);
|
|
||||||
prevSample[1]=temp[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
blip_end_frame(bb[0],runtotal);
|
|
||||||
blip_read_samples(bb[0],bbOut[0],size,0);
|
|
||||||
|
|
||||||
if (dispatch->isStereo()) {
|
|
||||||
blip_end_frame(bb[1],runtotal);
|
|
||||||
blip_read_samples(bb[1],bbOut[1],size,0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out==NULL) {
|
if (out==NULL) {
|
||||||
|
@ -967,15 +970,17 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dispatch->isStereo()) {
|
for (int i=0; i<song.systemLen; i++) {
|
||||||
for (size_t i=0; i<size; i++) {
|
if (disCont[i].dispatch->isStereo()) {
|
||||||
out[0][i]+=(float)bbOut[0][i]/16384.0;
|
for (size_t j=0; j<size; j++) {
|
||||||
out[1][i]+=(float)bbOut[1][i]/16384.0;
|
out[0][j]+=(float)disCont[i].bbOut[0][j]/16384.0;
|
||||||
}
|
out[1][j]+=(float)disCont[i].bbOut[1][j]/16384.0;
|
||||||
} else {
|
}
|
||||||
for (size_t i=0; i<size; i++) {
|
} else {
|
||||||
out[0][i]+=(float)bbOut[0][i]/16384.0;
|
for (size_t j=0; j<size; j++) {
|
||||||
out[1][i]+=(float)bbOut[0][i]/16384.0;
|
out[0][j]+=(float)disCont[i].bbOut[0][j]/16384.0;
|
||||||
|
out[1][j]+=(float)disCont[i].bbOut[0][j]/16384.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1742,7 +1742,7 @@ void FurnaceGUI::makeUndo(ActionType action) {
|
||||||
s.nibble=curNibble;
|
s.nibble=curNibble;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case GUI_ACTION_CHANGE_ORDER:
|
case GUI_ACTION_CHANGE_ORDER:
|
||||||
for (int i=0; i<32; i++) {
|
for (int i=0; i<DIV_MAX_CHANS; i++) {
|
||||||
for (int j=0; j<128; j++) {
|
for (int j=0; j<128; j++) {
|
||||||
if (oldOrders.ord[i][j]!=e->song.orders.ord[i][j]) {
|
if (oldOrders.ord[i][j]!=e->song.orders.ord[i][j]) {
|
||||||
s.ord.push_back(UndoOrderData(i,j,oldOrders.ord[i][j],e->song.orders.ord[i][j]));
|
s.ord.push_back(UndoOrderData(i,j,oldOrders.ord[i][j],e->song.orders.ord[i][j]));
|
||||||
|
@ -3076,7 +3076,6 @@ FurnaceGUI::FurnaceGUI():
|
||||||
macroDragActive(false),
|
macroDragActive(false),
|
||||||
nextScroll(-1.0f),
|
nextScroll(-1.0f),
|
||||||
nextAddScroll(0.0f),
|
nextAddScroll(0.0f),
|
||||||
oldSystem(DIV_SYSTEM_NULL),
|
|
||||||
oldOrdersLen(0) {
|
oldOrdersLen(0) {
|
||||||
uiColors[GUI_COLOR_BACKGROUND]=ImVec4(0.1f,0.1f,0.1f,1.0f);
|
uiColors[GUI_COLOR_BACKGROUND]=ImVec4(0.1f,0.1f,0.1f,1.0f);
|
||||||
uiColors[GUI_COLOR_FRAME_BACKGROUND]=ImVec4(0.0f,0.0f,0.0f,0.85f);
|
uiColors[GUI_COLOR_FRAME_BACKGROUND]=ImVec4(0.0f,0.0f,0.0f,0.85f);
|
||||||
|
|
|
@ -123,7 +123,6 @@ struct UndoStep {
|
||||||
SelectionPoint cursor, selStart, selEnd;
|
SelectionPoint cursor, selStart, selEnd;
|
||||||
int order;
|
int order;
|
||||||
bool nibble;
|
bool nibble;
|
||||||
DivSystem oldSystem, newSystem;
|
|
||||||
int oldOrdersLen, newOrdersLen;
|
int oldOrdersLen, newOrdersLen;
|
||||||
int oldPatLen, newPatLen;
|
int oldPatLen, newPatLen;
|
||||||
std::vector<UndoOrderData> ord;
|
std::vector<UndoOrderData> ord;
|
||||||
|
@ -202,7 +201,6 @@ class FurnaceGUI {
|
||||||
|
|
||||||
ImVec2 patWindowPos, patWindowSize;
|
ImVec2 patWindowPos, patWindowSize;
|
||||||
|
|
||||||
DivSystem oldSystem;
|
|
||||||
int oldOrdersLen;
|
int oldOrdersLen;
|
||||||
DivOrders oldOrders;
|
DivOrders oldOrders;
|
||||||
DivPattern* oldPat[128];
|
DivPattern* oldPat[128];
|
||||||
|
|
Loading…
Reference in a new issue