From 561c2cb08c4b3f431e86080b7a9737ace8e7cb99 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 4 Dec 2022 15:20:46 -0500 Subject: [PATCH 01/18] prepare for BRR fixes --- src/engine/brrUtils.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/engine/brrUtils.c b/src/engine/brrUtils.c index e3b20c26d..1fc208a6f 100644 --- a/src/engine/brrUtils.c +++ b/src/engine/brrUtils.c @@ -56,6 +56,10 @@ last2=last1; \ last1=nextDec; \ +void brrEncodeBlock(short* buf, unsigned char* out, unsigned char flag, short* last1, short* last2) { + // encode one block using BRR +} + long brrEncode(short* buf, unsigned char* out, long len, long loopStart) { if (len==0) return 0; From e76dcdd0cfd6f467679c193bac3483728235a7b4 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 4 Dec 2022 16:12:30 -0500 Subject: [PATCH 02/18] add SDL audio driver debug line --- src/audio/sdlAudio.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/audio/sdlAudio.cpp b/src/audio/sdlAudio.cpp index f1d0e1e9d..2915f0343 100644 --- a/src/audio/sdlAudio.cpp +++ b/src/audio/sdlAudio.cpp @@ -106,6 +106,13 @@ bool TAAudioSDL::init(TAAudioDesc& request, TAAudioDesc& response) { audioSysStarted=true; } + const char* audioDriver=SDL_GetCurrentAudioDriver(); + if (audioDriver==NULL) { + logD("SDL audio driver: NULL!"); + } else { + logD("SDL audio driver: %s",audioDriver); + } + desc=request; desc.outFormat=TA_AUDIO_FORMAT_F32; From a63e2284c762c9ab081a72c70d7fe2e5ae5dcead Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 4 Dec 2022 17:19:21 -0500 Subject: [PATCH 03/18] GUI: mobile menu button dragging --- src/gui/editControls.cpp | 43 ++++++++++++++++++++++++++++++---------- src/gui/gui.cpp | 10 ++++++++++ src/gui/gui.h | 3 ++- 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/gui/editControls.cpp b/src/gui/editControls.cpp index a7582ff38..05c5d4c9f 100644 --- a/src/gui/editControls.cpp +++ b/src/gui/editControls.cpp @@ -23,19 +23,29 @@ void FurnaceGUI::drawMobileControls() { float timeScale=1.0f/(60.0f*ImGui::GetIO().DeltaTime); - if (mobileMenuOpen) { - if (mobileMenuPos<0.999f) { - WAKE_UP; - mobileMenuPos+=MIN(0.1,(1.0-mobileMenuPos)*0.65)*timeScale; + if (dragMobileMenu) { + if (portrait) { + mobileMenuPos=(dragMobileMenuOrigin.y-ImGui::GetMousePos().y)/(canvasH*0.65); } else { - mobileMenuPos=1.0f; + mobileMenuPos=(ImGui::GetMousePos().x-dragMobileMenuOrigin.x)/(canvasW*0.65); } + if (mobileMenuPos<0.0f) mobileMenuPos=0.0f; + if (mobileMenuPos>1.0f) mobileMenuPos=1.0f; } else { - if (mobileMenuPos>0.001f) { - WAKE_UP; - mobileMenuPos-=MIN(0.1,mobileMenuPos*0.65)*timeScale; + if (mobileMenuOpen) { + if (mobileMenuPos<0.999f) { + WAKE_UP; + mobileMenuPos+=MIN(0.1,(1.0-mobileMenuPos)*0.65)*timeScale; + } else { + mobileMenuPos=1.0f; + } } else { - mobileMenuPos=0.0f; + if (mobileMenuPos>0.001f) { + WAKE_UP; + mobileMenuPos-=MIN(0.1,mobileMenuPos*0.65)*timeScale; + } else { + mobileMenuPos=0.0f; + } } } ImGui::SetNextWindowPos(portrait?ImVec2(0.0f,((1.0-mobileMenuPos*0.65)*canvasH)-(0.16*canvasW)):ImVec2(0.5*canvasW*mobileMenuPos,0.0f)); @@ -54,7 +64,20 @@ void FurnaceGUI::drawMobileControls() { } } if (ImGui::Button(mobButtonName,buttonSize)) { - mobileMenuOpen=!mobileMenuOpen; + if (!dragMobileMenu) { + mobileMenuOpen=!mobileMenuOpen; + } + } + if (ImGui::IsItemActive() && ImGui::GetIO().MouseDragMaxDistanceSqr[ImGuiMouseButton_Left]>ImGui::GetIO().ConfigInertialScrollToleranceSqr*2.0f) { + if (!dragMobileMenu) { + dragMobileMenu=true; + dragMobileMenuOrigin=ImGui::GetMousePos(); + if (portrait) { + dragMobileMenuOrigin.y+=mobileMenuPos*canvasH*0.65f; + } else { + dragMobileMenuOrigin.x-=mobileMenuPos*canvasW*0.65f; + } + } } if (!portrait) ImGui::Separator(); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index f0d96ee21..8c5264c52 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -2931,6 +2931,14 @@ void FurnaceGUI::pointUp(int x, int y, int button) { } orderScrollLocked=false; orderScrollTolerance=false; + if (dragMobileMenu) { + dragMobileMenu=false; + if (mobileMenuOpen) { + mobileMenuOpen=(mobileMenuPos>=0.85f); + } else { + mobileMenuOpen=(mobileMenuPos>=0.15f); + } + } if (selecting) { if (!selectingFull) cursor=selEnd; finishSelection(); @@ -5785,6 +5793,7 @@ FurnaceGUI::FurnaceGUI(): keepLoopAlive(false), orderScrollLocked(false), orderScrollTolerance(false), + dragMobileMenu(false), curWindow(GUI_WINDOW_NOTHING), nextWindow(GUI_WINDOW_NOTHING), curWindowLast(GUI_WINDOW_NOTHING), @@ -5877,6 +5886,7 @@ FurnaceGUI::FurnaceGUI(): orderScroll(0.0f), orderScrollSlideOrigin(0.0f), orderScrollRealOrigin(0.0f,0.0f), + dragMobileMenuOrigin(0.0f,0.0f), layoutTimeBegin(0), layoutTimeEnd(0), layoutTimeDelta(0), diff --git a/src/gui/gui.h b/src/gui/gui.h index 8d233f9a9..587ff03a8 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1435,7 +1435,7 @@ class FurnaceGUI { SelectionPoint selStart, selEnd, cursor, cursorDrag, dragStart, dragEnd; bool selecting, selectingFull, dragging, curNibble, orderNibble, followOrders, followPattern, changeAllOrders, mobileUI; bool collapseWindow, demandScrollX, fancyPattern, wantPatName, firstFrame, tempoView, waveHex, waveSigned, waveGenVisible, lockLayout, editOptsVisible, latchNibble, nonLatchNibble; - bool keepLoopAlive, orderScrollLocked, orderScrollTolerance; + bool keepLoopAlive, orderScrollLocked, orderScrollTolerance, dragMobileMenu; FurnaceGUIWindows curWindow, nextWindow, curWindowLast; std::atomic curWindowThreadSafe; float peak[2]; @@ -1581,6 +1581,7 @@ class FurnaceGUI { float nextScroll, nextAddScroll, orderScroll, orderScrollSlideOrigin; ImVec2 orderScrollRealOrigin; + ImVec2 dragMobileMenuOrigin; int layoutTimeBegin, layoutTimeEnd, layoutTimeDelta; int renderTimeBegin, renderTimeEnd, renderTimeDelta; From 9026c1e03e067dacdf7f738cabfa5959956a139f Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 4 Dec 2022 22:00:17 -0500 Subject: [PATCH 04/18] this fails horribly --- src/engine/brrUtils.c | 81 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/src/engine/brrUtils.c b/src/engine/brrUtils.c index 1fc208a6f..c3f7e6366 100644 --- a/src/engine/brrUtils.c +++ b/src/engine/brrUtils.c @@ -56,8 +56,87 @@ last2=last1; \ last1=nextDec; \ -void brrEncodeBlock(short* buf, unsigned char* out, unsigned char flag, short* last1, short* last2) { +void brrEncodeBlock(const short* buf, unsigned char* out, unsigned char range, unsigned char filter, short* last1, short* last2) { // encode one block using BRR + switch (filter) { + case 0: + for (int j=0; j<16; j++) { + } + break; + case 1: + for (int j=0; j<16; j++) { + int s=NEXT_SAMPLE; + + pred1[j]=s-(((int)o1f1*15)>>4); + if (pred1[j]<-32768) pred1[j]=-32768; + if (pred1[j]>32767) pred1[j]=32767; + + o0=pred1[j]>>range1; + if (range1) if (pred1[j]&(1<<(range1>>1))) o0++; + if (o0>7) o0=7; + if (o0<-8) o0=-8; + o=o0&15; + if (j&1) { + next1[j>>1]|=o; + } else { + next1[j>>1]=o<<4; + } + + nextDec=o; + DO_ONE_DEC(range1); + //o2f1=last2<<1; + o1f1=last1<<1; + } + break; + case 2: + for (int j=0; j<16; j++) { + int s=NEXT_SAMPLE; + pred2[j]=s+(((int)o2f2*15)>>4)-(((int)o1f2*61)>>5); + if (pred2[j]<-32768) pred2[j]=-32768; + if (pred2[j]>32767) pred2[j]=32767; + + o0=pred2[j]>>range2; + if (range2) if (pred2[j]&(1<<(range2>>1))) o0++; + if (o0>7) o0=7; + if (o0<-8) o0=-8; + o=o0&15; + if (j&1) { + next2[j>>1]|=o; + } else { + next2[j>>1]=o<<4; + } + + nextDec=o; + DO_ONE_DEC(range2); + o2f2=last2<<1; + o1f2=last1<<1; + } + break; + case 3: + for (int j=0; j<16; j++) { + int s=NEXT_SAMPLE; + pred3[j]=s+(((int)o2f3*13)>>4)-(((int)o1f3*115)>>6); + if (pred3[j]<-32768) pred3[j]=-32768; + if (pred3[j]>32767) pred3[j]=32767; + + o0=pred3[j]>>range3; + if (range3) if (pred3[j]&(1<<(range3>>1))) o0++; + if (o0>7) o0=7; + if (o0<-8) o0=-8; + o=o0&15; + if (j&1) { + next3[j>>1]|=o; + } else { + next3[j>>1]=o<<4; + } + + nextDec=o; + DO_ONE_DEC(range3); + o2f3=last2<<1; + o1f3=last1<<1; + } + break; + } } long brrEncode(short* buf, unsigned char* out, long len, long loopStart) { From 165774d136cb0a4530a9f150e868920b6fc90082 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 4 Dec 2022 22:00:39 -0500 Subject: [PATCH 05/18] SN: move CHECK_CUSTOM_CLOCK --- src/engine/platform/sms.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index 0ce4c8361..41ef81ee0 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -498,6 +498,7 @@ void DivPlatformSMS::setFlags(const DivConfig& flags) { easyStartingPeriod=13; break; } + CHECK_CUSTOM_CLOCK; resetPhase=!flags.getBool("noPhaseReset",false); easyNoise=!flags.getBool("noEasyNoise",false); divider=16; @@ -568,7 +569,6 @@ void DivPlatformSMS::setFlags(const DivConfig& flags) { stereo=false; break; } - CHECK_CUSTOM_CLOCK; rate=chipClock/divider; for (int i=0; i<4; i++) { oscBuf[i]->rate=rate; From 648851b5b58109e1f19a004146389702e7e4991a Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 5 Dec 2022 04:14:07 -0500 Subject: [PATCH 06/18] re-write BRR encoder --- src/engine/brrUtils.c | 551 ++++++++++-------------------------------- 1 file changed, 129 insertions(+), 422 deletions(-) diff --git a/src/engine/brrUtils.c b/src/engine/brrUtils.c index c3f7e6366..844add144 100644 --- a/src/engine/brrUtils.c +++ b/src/engine/brrUtils.c @@ -21,6 +21,8 @@ */ #include "brrUtils.h" +#include +#include #define NEXT_SAMPLE buf[j]-(buf[j]>>3) @@ -56,86 +58,86 @@ last2=last1; \ last1=nextDec; \ -void brrEncodeBlock(const short* buf, unsigned char* out, unsigned char range, unsigned char filter, short* last1, short* last2) { +void brrEncodeBlock(const short* buf, unsigned char* out, unsigned char range, unsigned char filter, short* last1, short* last2, int* errorSum) { // encode one block using BRR - switch (filter) { - case 0: - for (int j=0; j<16; j++) { - } - break; - case 1: - for (int j=0; j<16; j++) { - int s=NEXT_SAMPLE; + unsigned char nibble=0; + short preOut=0; + int pred=0; + int nextDec=0; + int nextError=0; + *errorSum=0; + for (int j=0; j<16; j++) { + short s=NEXT_SAMPLE; + nibble<<=4; + switch (filter) { + case 0: // no filter + pred=s; + break; + case 1: // simple + pred=s-(((int)(*last1)*15)>>4); + break; + case 2: // complex + pred=s+(((int)(*last2)*15)>>4)-(((int)(*last1)*61)>>5); + break; + case 3: + pred=s+(((int)(*last2)*13)>>4)-(((int)(*last1)*115)>>6); + break; + } - pred1[j]=s-(((int)o1f1*15)>>4); - if (pred1[j]<-32768) pred1[j]=-32768; - if (pred1[j]>32767) pred1[j]=32767; + if (pred<-32768) pred=-32768; + if (pred>32767) pred=32767; - o0=pred1[j]>>range1; - if (range1) if (pred1[j]&(1<<(range1>>1))) o0++; - if (o0>7) o0=7; - if (o0<-8) o0=-8; - o=o0&15; - if (j&1) { - next1[j>>1]|=o; - } else { - next1[j>>1]=o<<4; - } + preOut=pred>>range; + if (range) { + if (pred&(1<<(range>>1))) preOut++; + if (filter==0 && range>=12) if (preOut<-7) preOut=-7; + } + if (preOut>7) preOut=7; + if (preOut<-8) preOut=-8; - nextDec=o; - DO_ONE_DEC(range1); - //o2f1=last2<<1; - o1f1=last1<<1; - } - break; - case 2: - for (int j=0; j<16; j++) { - int s=NEXT_SAMPLE; - pred2[j]=s+(((int)o2f2*15)>>4)-(((int)o1f2*61)>>5); - if (pred2[j]<-32768) pred2[j]=-32768; - if (pred2[j]>32767) pred2[j]=32767; + nibble=preOut&15; + if (j&1) { + out[j>>1]|=nibble; + } else { + out[j>>1]=nibble<<4; + } - o0=pred2[j]>>range2; - if (range2) if (pred2[j]&(1<<(range2>>1))) o0++; - if (o0>7) o0=7; - if (o0<-8) o0=-8; - o=o0&15; - if (j&1) { - next2[j>>1]|=o; - } else { - next2[j>>1]=o<<4; - } + // roll last1/last2 + nextDec=nibble; + if (nextDec&8) nextDec|=0xfffffff0; - nextDec=o; - DO_ONE_DEC(range2); - o2f2=last2<<1; - o1f2=last1<<1; - } - break; - case 3: - for (int j=0; j<16; j++) { - int s=NEXT_SAMPLE; - pred3[j]=s+(((int)o2f3*13)>>4)-(((int)o1f3*115)>>6); - if (pred3[j]<-32768) pred3[j]=-32768; - if (pred3[j]>32767) pred3[j]=32767; + if (range>=13) { /* invalid shift */ + nextDec=(nextDec<0)?0xfffff800:0; + } else { + nextDec<<=range; /* range */ + nextDec>>=1; + } - o0=pred3[j]>>range3; - if (range3) if (pred3[j]&(1<<(range3>>1))) o0++; - if (o0>7) o0=7; - if (o0<-8) o0=-8; - o=o0&15; - if (j&1) { - next3[j>>1]|=o; - } else { - next3[j>>1]=o<<4; - } + switch (filter) { /* filter */ + case 0: + break; + case 1: + nextDec+=(*last1)+((-(*last1))>>4); + break; + case 2: + nextDec+=(*last1)*2+((-(*last1)*3)>>5)-(*last2)+((*last2)>>4); + break; + case 3: + nextDec+=(*last1)*2+((-(*last1)*13)>>6)-(*last2)+(((*last2)*3)>>4); + break; + } - nextDec=o; - DO_ONE_DEC(range3); - o2f3=last2<<1; - o1f3=last1<<1; - } - break; + if (nextDec>32767) nextDec=32767; + if (nextDec<-32768) nextDec=-32768; + nextDec&=0x7fff; + if (nextDec&0x4000) nextDec|=0xffff8000; + + nextError=s-(nextDec<<1); + if (nextError<0) nextError=-nextError; + *errorSum+=nextError; + + *last2=*last1; + *last1=nextDec; } } @@ -146,375 +148,80 @@ long brrEncode(short* buf, unsigned char* out, long len, long loopStart) { // 1. read next group of 16 samples // 2. is this the first block? // - if yes, don't filter. output and then go to 1 - // 3. is this the loop block? - // - if yes, don't filter. output and then go to 1 - // 4. try encoding using 4 filters - // - perform linear prediction - // - calculate range - // - decode and apply correction to achieve low error + // 4. try encoding using 3 filters and 12 ranges (besides no filter) // 5. which one of these yields the least amount of error? // 6. output the one which does - // 7. is this the last block? - // - if yes, mark end and finish - // 8. go to 1 + // 7. do we still have more to encode? + // - if so, go to 1 + // 8. is loop point set? + // - if not, end process here + // 9. is transition between last block and loop block smooth? + // - if not, encode the loop block again and output it long total=0; - unsigned char next0[8]; - unsigned char next1[8]; - unsigned char next2[8]; - unsigned char next3[8]; unsigned char filter=0; - unsigned char range0=0; - unsigned char range1=0; - unsigned char range2=0; - unsigned char range3=0; + unsigned char range=0; unsigned char o=0; - int pred1[16]; - int pred2[16]; - int pred3[16]; - short o1=0; - short o2=0; - short o0=0; - short o1f1=0; - short o1f2=0; - short o1f3=0; - //short o2f1=0; - short o2f2=0; - short o2f3=0; - int last1=0; - int last2=0; - int nextDec=0; - int maxError[4]; - int avgError[4]; + short in[16]; + + short last1[4][13]; + short last2[4][13]; + int avgError[4][13]; + unsigned char possibleOut[4][13][8]; + + memset(in,0,16*sizeof(short)); + memset(last1,0,4*13*sizeof(short)); + memset(last2,0,4*13*sizeof(short)); + memset(avgError,0,4*13*sizeof(int)); + memset(possibleOut,0,4*13*8); len&=~15; loopStart&=~15; for (long i=0; i((8<>range0; - if (range0) if (s&(1<<(range1>>1))) o0++; - if (o0>7) o0=7; - if (o0<-8) o0=-8; - if (range0>=12) if (o0<-7) o0=-7; - o=o0&15; - if (j&1) { - next0[j>>1]|=o; - } else { - next0[j>>1]=o<<4; + memcpy(in,buf,16*sizeof(short)); + + // encode + for (int j=0; j<4; j++) { + for (int k=0; k<13; k++) { + brrEncodeBlock(in,possibleOut[j][k],k,j,&last1[j][k],&last2[j][k],&avgError[j][k]); } } - // encode with filter - if (i /*&& i!=loopStart*/) { - // 1: x = o0 - o1 * 15/16 - // 2: x = o0 + o2 * 15/16 - o1 * 61/32 - // 3: x = o0 + o2 * 13/16 - o1 * 115/64 - range1=0; - range2=0; - range3=0; - //o2f1=o2; - o2f2=o2; - o2f3=o2; - o1f1=o1; - o1f2=o1; - o1f3=o1; - // first pass - for (int j=0; j<16; j++) { - int s=NEXT_SAMPLE; - - pred1[j]=s-(((int)o1*15)>>4); - if (pred1[j]<-32768) pred1[j]=-32768; - if (pred1[j]>32767) pred1[j]=32767; - - pred2[j]=s+(((int)o2*15)>>4)-(((int)o1*61)>>5); - if (pred2[j]<-32768) pred2[j]=-32768; - if (pred2[j]>32767) pred2[j]=32767; - - pred3[j]=s+(((int)o2*13)>>4)-(((int)o1*115)>>6); - if (pred3[j]<-32768) pred3[j]=-32768; - if (pred3[j]>32767) pred3[j]=32767; - - o2=o1; - o1=s; - } - // calculate range of values - for (int j=0; j<16; j++) { - short s=pred1[j]; - if (s<0) s=-s; - while (range1<12 && s>((8<((8<((8<>4); - if (pred1[j]<-32768) pred1[j]=-32768; - if (pred1[j]>32767) pred1[j]=32767; - - o0=pred1[j]>>range1; - if (range1) if (pred1[j]&(1<<(range1>>1))) o0++; - if (o0>7) o0=7; - if (o0<-8) o0=-8; - o=o0&15; - if (j&1) { - next1[j>>1]|=o; - } else { - next1[j>>1]=o<<4; - } - - nextDec=o; - DO_ONE_DEC(range1); - //o2f1=last2<<1; - o1f1=last1<<1; - } - last1=prevLast1; - last2=prevLast2; - filter=2; - for (int j=0; j<16; j++) { - int s=NEXT_SAMPLE; - pred2[j]=s+(((int)o2f2*15)>>4)-(((int)o1f2*61)>>5); - if (pred2[j]<-32768) pred2[j]=-32768; - if (pred2[j]>32767) pred2[j]=32767; - - o0=pred2[j]>>range2; - if (range2) if (pred2[j]&(1<<(range2>>1))) o0++; - if (o0>7) o0=7; - if (o0<-8) o0=-8; - o=o0&15; - if (j&1) { - next2[j>>1]|=o; - } else { - next2[j>>1]=o<<4; - } - - nextDec=o; - DO_ONE_DEC(range2); - o2f2=last2<<1; - o1f2=last1<<1; - } - last1=prevLast1; - last2=prevLast2; - filter=3; - for (int j=0; j<16; j++) { - int s=NEXT_SAMPLE; - pred3[j]=s+(((int)o2f3*13)>>4)-(((int)o1f3*115)>>6); - if (pred3[j]<-32768) pred3[j]=-32768; - if (pred3[j]>32767) pred3[j]=32767; - - o0=pred3[j]>>range3; - if (range3) if (pred3[j]&(1<<(range3>>1))) o0++; - if (o0>7) o0=7; - if (o0<-8) o0=-8; - o=o0&15; - if (j&1) { - next3[j>>1]|=o; - } else { - next3[j>>1]=o<<4; - } - - nextDec=o; - DO_ONE_DEC(range3); - o2f3=last2<<1; - o1f3=last1<<1; - } - last1=prevLast1; - last2=prevLast2; - - // find best filter - int error=0; - - maxError[0]=0; - maxError[1]=0; - maxError[2]=0; - maxError[3]=0; - avgError[0]=0; - avgError[1]=0; - avgError[2]=0; - avgError[3]=0; - - // test filter 0 + // find best filter/range + int candError=0x7fffffff; + if (i==0) { filter=0; - for (int j=0; j<16; j++) { - int s=NEXT_SAMPLE; - if (j&1) { - nextDec=next0[j>>1]&15; - } else { - nextDec=next0[j>>1]>>4; - } - DO_ONE_DEC(range0); - error=s-(nextDec<<1); - if (error<0) error=-error; - avgError[0]+=error; - if (error>maxError[0]) maxError[0]=error; - } - last1=prevLast1; - last2=prevLast2; - - // test filter 1 - filter=1; - for (int j=0; j<16; j++) { - int s=NEXT_SAMPLE; - if (j&1) { - nextDec=next1[j>>1]&15; - } else { - nextDec=next1[j>>1]>>4; - } - DO_ONE_DEC(range1); - error=s-(nextDec<<1); - if (error<0) error=-error; - avgError[1]+=error; - if (error>maxError[1]) maxError[1]=error; - } - last1=prevLast1; - last2=prevLast2; - - // test filter 2 - filter=2; - for (int j=0; j<16; j++) { - int s=NEXT_SAMPLE; - if (j&1) { - nextDec=next2[j>>1]&15; - } else { - nextDec=next2[j>>1]>>4; - } - DO_ONE_DEC(range2); - error=s-(nextDec<<1); - if (error<0) error=-error; - avgError[2]+=error; - if (error>maxError[2]) maxError[2]=error; - } - last1=prevLast1; - last2=prevLast2; - - // test filter 3 - filter=3; - for (int j=0; j<16; j++) { - int s=NEXT_SAMPLE; - if (j&1) { - nextDec=next3[j>>1]&15; - } else { - nextDec=next3[j>>1]>>4; - } - DO_ONE_DEC(range3); - error=s-(nextDec<<1); - if (error<0) error=-error; - avgError[3]+=error; - if (error>maxError[3]) maxError[3]=error; - } - last1=prevLast1; - last2=prevLast2; - - // pick best filter - int candError=0x7fffffff; - for (int j=0; j<4; j++) { - if (avgError[j] %d\n",i>>4,avgError[0],avgError[1],avgError[2],avgError[3],filter); } else { - // don't filter on the first or loop block - filter=0; + for (int j=0; j<4; j++) { + for (int k=0; k<13; k++) { + if (avgError[j][k]=len)?((loopStart>=0)?3:1):0); + for (int j=0; j<8; j++) { + out[j+1]=possibleOut[filter][range][j]; } - switch (filter) { - case 0: - for (int j=0; j<8; j++) { - nextDec=next0[j]>>4; - DO_ONE_DEC(range0); - nextDec=next0[j]&15; - DO_ONE_DEC(range0); - } - o2=last2<<1; - o1=last1<<1; - - out[0]=(range0<<4)|(filter<<2)|((i+16>=len)?((loopStart>=0)?3:1):0); - out[1]=next0[0]; - out[2]=next0[1]; - out[3]=next0[2]; - out[4]=next0[3]; - out[5]=next0[4]; - out[6]=next0[5]; - out[7]=next0[6]; - out[8]=next0[7]; - break; - case 1: - for (int j=0; j<8; j++) { - nextDec=next1[j]>>4; - DO_ONE_DEC(range1); - nextDec=next1[j]&15; - DO_ONE_DEC(range1); - } - o2=last2<<1; - o1=last1<<1; - out[0]=(range1<<4)|(filter<<2)|((i+16>=len)?((loopStart>=0)?3:1):0); - out[1]=next1[0]; - out[2]=next1[1]; - out[3]=next1[2]; - out[4]=next1[3]; - out[5]=next1[4]; - out[6]=next1[5]; - out[7]=next1[6]; - out[8]=next1[7]; - break; - case 2: - for (int j=0; j<8; j++) { - nextDec=next2[j]>>4; - DO_ONE_DEC(range2); - nextDec=next2[j]&15; - DO_ONE_DEC(range2); - } - o2=last2<<1; - o1=last1<<1; - out[0]=(range2<<4)|(filter<<2)|((i+16>=len)?((loopStart>=0)?3:1):0); - out[1]=next2[0]; - out[2]=next2[1]; - out[3]=next2[2]; - out[4]=next2[3]; - out[5]=next2[4]; - out[6]=next2[5]; - out[7]=next2[6]; - out[8]=next2[7]; - break; - case 3: - for (int j=0; j<8; j++) { - nextDec=next3[j]>>4; - DO_ONE_DEC(range3); - nextDec=next3[j]&15; - DO_ONE_DEC(range3); - } - o2=last2<<1; - o1=last1<<1; - out[0]=(range3<<4)|(filter<<2)|((i+16>=len)?((loopStart>=0)?3:1):0); - out[1]=next3[0]; - out[2]=next3[1]; - out[3]=next3[2]; - out[4]=next3[3]; - out[5]=next3[4]; - out[6]=next3[5]; - out[7]=next3[6]; - out[8]=next3[7]; - break; + for (int j=0; j<4; j++) { + for (int k=0; k<13; k++) { + last1[j][k]=last1[filter][range]; + last2[j][k]=last2[filter][range]; + } } buf+=16; out+=9; From e21a6811341ac567efc0fc66dd74dd4b512f41ce Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 5 Dec 2022 10:51:54 -0500 Subject: [PATCH 07/18] enough debugging --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ffe48ee15..149d234c1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,7 @@ defaults: shell: bash env: - BUILD_TYPE: Debug + BUILD_TYPE: Release jobs: build: From 2dd8886db14ec3d6768d423d6e85d8ca23ac461b Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 5 Dec 2022 18:12:58 -0500 Subject: [PATCH 08/18] update brrUtils --- src/engine/brrUtils.c | 484 ++++++++++++------------------------------ 1 file changed, 134 insertions(+), 350 deletions(-) diff --git a/src/engine/brrUtils.c b/src/engine/brrUtils.c index e3b20c26d..ef3543750 100644 --- a/src/engine/brrUtils.c +++ b/src/engine/brrUtils.c @@ -21,6 +21,8 @@ */ #include "brrUtils.h" +#include +#include #define NEXT_SAMPLE buf[j]-(buf[j]>>3) @@ -56,6 +58,86 @@ last2=last1; \ last1=nextDec; \ +void brrEncodeBlock(const short* buf, unsigned char* out, unsigned char range, unsigned char filter, short* last1, short* last2, int* errorSum) { + // encode one block using BRR + unsigned char nibble=0; + int preOut=0; + int pred=0; + int nextDec=0; + int nextError=0; + *errorSum=0; + for (int j=0; j<16; j++) { + short s=NEXT_SAMPLE; + switch (filter) { + case 0: // no filter + pred=s; + break; + case 1: // simple + pred=s-(((int)(*last1*2)*15)>>4); + break; + case 2: // complex + pred=s+(((int)(*last2*2)*15)>>4)-(((int)(*last1*2)*61)>>5); + break; + case 3: + pred=s+(((int)(*last2*2)*13)>>4)-(((int)(*last1*2)*115)>>6); + break; + } + + if (pred<-32768) pred=-32768; + if (pred>32767) pred=32767; + + preOut=pred>>range; + if (range) { + if (pred&(1<<(range>>1))) preOut++; + if (filter==0 && range>=12) if (preOut<-7) preOut=-7; + } + if (preOut>7) preOut=7; + if (preOut<-8) preOut=-8; + + nibble=preOut&15; + if (j&1) { + out[j>>1]|=nibble; + } else { + out[j>>1]=nibble<<4; + } + + // roll last1/last2 + nextDec=nibble; + if (nextDec&8) nextDec|=0xfffffff0; + + if (range>=13) { /* invalid shift */ + nextDec=(nextDec<0)?0xfffff800:0; + } else { + nextDec<<=range; /* range */ + nextDec>>=1; + } + + switch (filter) { /* filter */ + case 0: + break; + case 1: + nextDec+=(*last1)+((-(*last1))>>4); + break; + case 2: + nextDec+=(*last1)*2+((-(*last1)*3)>>5)-(*last2)+((*last2)>>4); + break; + case 3: + nextDec+=(*last1)*2+((-(*last1)*13)>>6)-(*last2)+(((*last2)*3)>>4); + break; + } + + nextDec&=0x7fff; + if (nextDec&0x4000) nextDec|=0xffff8000; + + nextError=s-(nextDec<<1); + if (nextError<0) nextError=-nextError; + *errorSum+=nextError; + + *last2=*last1; + *last1=nextDec; + } +} + long brrEncode(short* buf, unsigned char* out, long len, long loopStart) { if (len==0) return 0; @@ -63,375 +145,77 @@ long brrEncode(short* buf, unsigned char* out, long len, long loopStart) { // 1. read next group of 16 samples // 2. is this the first block? // - if yes, don't filter. output and then go to 1 - // 3. is this the loop block? - // - if yes, don't filter. output and then go to 1 - // 4. try encoding using 4 filters - // - perform linear prediction - // - calculate range - // - decode and apply correction to achieve low error + // 4. try encoding using 3 filters and 12 ranges (besides no filter) // 5. which one of these yields the least amount of error? // 6. output the one which does - // 7. is this the last block? - // - if yes, mark end and finish - // 8. go to 1 + // 7. do we still have more to encode? + // - if so, go to 1 + // 8. is loop point set? + // - if not, end process here + // 9. is transition between last block and loop block smooth? + // - if not, encode the loop block again and output it long total=0; - unsigned char next0[8]; - unsigned char next1[8]; - unsigned char next2[8]; - unsigned char next3[8]; unsigned char filter=0; - unsigned char range0=0; - unsigned char range1=0; - unsigned char range2=0; - unsigned char range3=0; - unsigned char o=0; - int pred1[16]; - int pred2[16]; - int pred3[16]; - short o1=0; - short o2=0; - short o0=0; - short o1f1=0; - short o1f2=0; - short o1f3=0; - //short o2f1=0; - short o2f2=0; - short o2f3=0; + unsigned char range=0; - int last1=0; - int last2=0; - int nextDec=0; - int maxError[4]; - int avgError[4]; + short in[16]; + + short last1[4][13]; + short last2[4][13]; + int avgError[4][13]; + unsigned char possibleOut[4][13][8]; + + memset(in,0,16*sizeof(short)); + memset(last1,0,4*13*sizeof(short)); + memset(last2,0,4*13*sizeof(short)); + memset(avgError,0,4*13*sizeof(int)); + memset(possibleOut,0,4*13*8); len&=~15; loopStart&=~15; for (long i=0; i((8<>range0; - if (range0) if (s&(1<<(range1>>1))) o0++; - if (o0>7) o0=7; - if (o0<-8) o0=-8; - if (range0>=12) if (o0<-7) o0=-7; - o=o0&15; - if (j&1) { - next0[j>>1]|=o; - } else { - next0[j>>1]=o<<4; + memcpy(in,buf,16*sizeof(short)); + + // encode + for (int j=0; j<4; j++) { + for (int k=0; k<13; k++) { + brrEncodeBlock(in,possibleOut[j][k],k,j,&last1[j][k],&last2[j][k],&avgError[j][k]); } } - // encode with filter - if (i /*&& i!=loopStart*/) { - // 1: x = o0 - o1 * 15/16 - // 2: x = o0 + o2 * 15/16 - o1 * 61/32 - // 3: x = o0 + o2 * 13/16 - o1 * 115/64 - range1=0; - range2=0; - range3=0; - //o2f1=o2; - o2f2=o2; - o2f3=o2; - o1f1=o1; - o1f2=o1; - o1f3=o1; - // first pass - for (int j=0; j<16; j++) { - int s=NEXT_SAMPLE; - - pred1[j]=s-(((int)o1*15)>>4); - if (pred1[j]<-32768) pred1[j]=-32768; - if (pred1[j]>32767) pred1[j]=32767; - - pred2[j]=s+(((int)o2*15)>>4)-(((int)o1*61)>>5); - if (pred2[j]<-32768) pred2[j]=-32768; - if (pred2[j]>32767) pred2[j]=32767; - - pred3[j]=s+(((int)o2*13)>>4)-(((int)o1*115)>>6); - if (pred3[j]<-32768) pred3[j]=-32768; - if (pred3[j]>32767) pred3[j]=32767; - - o2=o1; - o1=s; - } - // calculate range of values - for (int j=0; j<16; j++) { - short s=pred1[j]; - if (s<0) s=-s; - while (range1<12 && s>((8<((8<((8<>4); - if (pred1[j]<-32768) pred1[j]=-32768; - if (pred1[j]>32767) pred1[j]=32767; - - o0=pred1[j]>>range1; - if (range1) if (pred1[j]&(1<<(range1>>1))) o0++; - if (o0>7) o0=7; - if (o0<-8) o0=-8; - o=o0&15; - if (j&1) { - next1[j>>1]|=o; - } else { - next1[j>>1]=o<<4; - } - - nextDec=o; - DO_ONE_DEC(range1); - //o2f1=last2<<1; - o1f1=last1<<1; - } - last1=prevLast1; - last2=prevLast2; - filter=2; - for (int j=0; j<16; j++) { - int s=NEXT_SAMPLE; - pred2[j]=s+(((int)o2f2*15)>>4)-(((int)o1f2*61)>>5); - if (pred2[j]<-32768) pred2[j]=-32768; - if (pred2[j]>32767) pred2[j]=32767; - - o0=pred2[j]>>range2; - if (range2) if (pred2[j]&(1<<(range2>>1))) o0++; - if (o0>7) o0=7; - if (o0<-8) o0=-8; - o=o0&15; - if (j&1) { - next2[j>>1]|=o; - } else { - next2[j>>1]=o<<4; - } - - nextDec=o; - DO_ONE_DEC(range2); - o2f2=last2<<1; - o1f2=last1<<1; - } - last1=prevLast1; - last2=prevLast2; - filter=3; - for (int j=0; j<16; j++) { - int s=NEXT_SAMPLE; - pred3[j]=s+(((int)o2f3*13)>>4)-(((int)o1f3*115)>>6); - if (pred3[j]<-32768) pred3[j]=-32768; - if (pred3[j]>32767) pred3[j]=32767; - - o0=pred3[j]>>range3; - if (range3) if (pred3[j]&(1<<(range3>>1))) o0++; - if (o0>7) o0=7; - if (o0<-8) o0=-8; - o=o0&15; - if (j&1) { - next3[j>>1]|=o; - } else { - next3[j>>1]=o<<4; - } - - nextDec=o; - DO_ONE_DEC(range3); - o2f3=last2<<1; - o1f3=last1<<1; - } - last1=prevLast1; - last2=prevLast2; - - // find best filter - int error=0; - - maxError[0]=0; - maxError[1]=0; - maxError[2]=0; - maxError[3]=0; - avgError[0]=0; - avgError[1]=0; - avgError[2]=0; - avgError[3]=0; - - // test filter 0 + // find best filter/range + int candError=0x7fffffff; + if (i==0) { filter=0; - for (int j=0; j<16; j++) { - int s=NEXT_SAMPLE; - if (j&1) { - nextDec=next0[j>>1]&15; - } else { - nextDec=next0[j>>1]>>4; - } - DO_ONE_DEC(range0); - error=s-(nextDec<<1); - if (error<0) error=-error; - avgError[0]+=error; - if (error>maxError[0]) maxError[0]=error; - } - last1=prevLast1; - last2=prevLast2; - - // test filter 1 - filter=1; - for (int j=0; j<16; j++) { - int s=NEXT_SAMPLE; - if (j&1) { - nextDec=next1[j>>1]&15; - } else { - nextDec=next1[j>>1]>>4; - } - DO_ONE_DEC(range1); - error=s-(nextDec<<1); - if (error<0) error=-error; - avgError[1]+=error; - if (error>maxError[1]) maxError[1]=error; - } - last1=prevLast1; - last2=prevLast2; - - // test filter 2 - filter=2; - for (int j=0; j<16; j++) { - int s=NEXT_SAMPLE; - if (j&1) { - nextDec=next2[j>>1]&15; - } else { - nextDec=next2[j>>1]>>4; - } - DO_ONE_DEC(range2); - error=s-(nextDec<<1); - if (error<0) error=-error; - avgError[2]+=error; - if (error>maxError[2]) maxError[2]=error; - } - last1=prevLast1; - last2=prevLast2; - - // test filter 3 - filter=3; - for (int j=0; j<16; j++) { - int s=NEXT_SAMPLE; - if (j&1) { - nextDec=next3[j>>1]&15; - } else { - nextDec=next3[j>>1]>>4; - } - DO_ONE_DEC(range3); - error=s-(nextDec<<1); - if (error<0) error=-error; - avgError[3]+=error; - if (error>maxError[3]) maxError[3]=error; - } - last1=prevLast1; - last2=prevLast2; - - // pick best filter - int candError=0x7fffffff; - for (int j=0; j<4; j++) { - if (avgError[j] %d\n",i>>4,avgError[0],avgError[1],avgError[2],avgError[3],filter); } else { - // don't filter on the first or loop block - filter=0; + for (int j=0; j<4; j++) { + for (int k=0; k<13; k++) { + if (avgError[j][k]>4; - DO_ONE_DEC(range0); - nextDec=next0[j]&15; - DO_ONE_DEC(range0); - } - o2=last2<<1; - o1=last1<<1; + // write + out[0]=(range<<4)|(filter<<2)|((i+16>=len)?((loopStart>=0)?3:1):0); + for (int j=0; j<8; j++) { + out[j+1]=possibleOut[filter][range][j]; + } - out[0]=(range0<<4)|(filter<<2)|((i+16>=len)?((loopStart>=0)?3:1):0); - out[1]=next0[0]; - out[2]=next0[1]; - out[3]=next0[2]; - out[4]=next0[3]; - out[5]=next0[4]; - out[6]=next0[5]; - out[7]=next0[6]; - out[8]=next0[7]; - break; - case 1: - for (int j=0; j<8; j++) { - nextDec=next1[j]>>4; - DO_ONE_DEC(range1); - nextDec=next1[j]&15; - DO_ONE_DEC(range1); - } - o2=last2<<1; - o1=last1<<1; - out[0]=(range1<<4)|(filter<<2)|((i+16>=len)?((loopStart>=0)?3:1):0); - out[1]=next1[0]; - out[2]=next1[1]; - out[3]=next1[2]; - out[4]=next1[3]; - out[5]=next1[4]; - out[6]=next1[5]; - out[7]=next1[6]; - out[8]=next1[7]; - break; - case 2: - for (int j=0; j<8; j++) { - nextDec=next2[j]>>4; - DO_ONE_DEC(range2); - nextDec=next2[j]&15; - DO_ONE_DEC(range2); - } - o2=last2<<1; - o1=last1<<1; - out[0]=(range2<<4)|(filter<<2)|((i+16>=len)?((loopStart>=0)?3:1):0); - out[1]=next2[0]; - out[2]=next2[1]; - out[3]=next2[2]; - out[4]=next2[3]; - out[5]=next2[4]; - out[6]=next2[5]; - out[7]=next2[6]; - out[8]=next2[7]; - break; - case 3: - for (int j=0; j<8; j++) { - nextDec=next3[j]>>4; - DO_ONE_DEC(range3); - nextDec=next3[j]&15; - DO_ONE_DEC(range3); - } - o2=last2<<1; - o1=last1<<1; - out[0]=(range3<<4)|(filter<<2)|((i+16>=len)?((loopStart>=0)?3:1):0); - out[1]=next3[0]; - out[2]=next3[1]; - out[3]=next3[2]; - out[4]=next3[3]; - out[5]=next3[4]; - out[6]=next3[5]; - out[7]=next3[6]; - out[8]=next3[7]; - break; + for (int j=0; j<4; j++) { + for (int k=0; k<13; k++) { + last1[j][k]=last1[filter][range]; + last2[j][k]=last2[filter][range]; + } } buf+=16; out+=9; From bf626ac68d00b4469c611d4774f073b35d072aef Mon Sep 17 00:00:00 2001 From: cam900 Date: Tue, 6 Dec 2022 09:00:34 +0900 Subject: [PATCH 09/18] Fix K007232 start address --- extern/vgsound_emu-modified/vgsound_emu/src/k007232/k007232.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/vgsound_emu-modified/vgsound_emu/src/k007232/k007232.cpp b/extern/vgsound_emu-modified/vgsound_emu/src/k007232/k007232.cpp index 3798f4c81..02aa34601 100644 --- a/extern/vgsound_emu-modified/vgsound_emu/src/k007232/k007232.cpp +++ b/extern/vgsound_emu-modified/vgsound_emu/src/k007232/k007232.cpp @@ -126,7 +126,7 @@ void k007232_core::voice_t::write(u8 address, u8 data) m_start = (m_start & ~0x0ff00) | (u32(data) << 8); break; case 4: // start address bit 16 - m_start = (m_start & ~0x10000) | (u32(bitfield(data, 16)) << 16); + m_start = (m_start & ~0x10000) | (u32(bitfield(data, 0)) << 16); break; case 5: // keyon trigger keyon(); From 0f63db2dac6ca84a084693555c76e54378d86982 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 5 Dec 2022 19:13:21 -0500 Subject: [PATCH 10/18] BRR loop fixes! --- src/engine/brrUtils.c | 67 +++++++++++++++++++++++++++++++++--- src/engine/brrUtils.h | 2 +- src/engine/platform/snes.cpp | 6 ++-- src/engine/sample.cpp | 6 ++-- 4 files changed, 69 insertions(+), 12 deletions(-) diff --git a/src/engine/brrUtils.c b/src/engine/brrUtils.c index ef3543750..a147c6ae0 100644 --- a/src/engine/brrUtils.c +++ b/src/engine/brrUtils.c @@ -171,10 +171,24 @@ long brrEncode(short* buf, unsigned char* out, long len, long loopStart) { memset(avgError,0,4*13*sizeof(int)); memset(possibleOut,0,4*13*8); - len&=~15; - loopStart&=~15; for (long i=0; ilen) { + long p=i; + for (int j=0; j<16; j++) { + if (p>=len) { + if (loopStart<0 || loopStart>=len) { + in[j]=0; + } else { + p=loopStart; + in[j]=buf[p++]; + } + } else { + in[j]=buf[p++]; + } + } + } else { + memcpy(in,&buf[i],16*sizeof(short)); + } // encode for (int j=0; j<4; j++) { @@ -206,7 +220,51 @@ long brrEncode(short* buf, unsigned char* out, long len, long loopStart) { } // write - out[0]=(range<<4)|(filter<<2)|((i+16>=len)?((loopStart>=0)?3:1):0); + out[0]=(range<<4)|(filter<<2)|((i+16>=len && loopStart<0)?1:0); + for (int j=0; j<8; j++) { + out[j+1]=possibleOut[filter][range][j]; + } + + for (int j=0; j<4; j++) { + for (int k=0; k<13; k++) { + last1[j][k]=last1[filter][range]; + last2[j][k]=last2[filter][range]; + } + } + out+=9; + total+=9; + } + // encode loop block + if (loopStart>=0) { + long p=loopStart; + for (int i=0; i<16; i++) { + if (p>=len) { + p=loopStart; + } + in[i]=buf[p++]; + } + + // encode (filter 0/1 only) + for (int j=0; j<2; j++) { + for (int k=0; k<13; k++) { + brrEncodeBlock(in,possibleOut[j][k],k,j,&last1[j][k],&last2[j][k],&avgError[j][k]); + } + } + + // find best filter/range + int candError=0x7fffffff; + for (int j=0; j<2; j++) { + for (int k=0; k<13; k++) { + if (avgError[j][k]=0 && chan[i].samplesong.sampleLen) { start=sampleOff[chan[i].sample]; - end=MIN(start+MAX(s->lengthBRR,1),getSampleMemCapacity()); + end=MIN(start+MAX(s->lengthBRR+((s->loop && s->depth!=DIV_SAMPLE_DEPTH_BRR)?9:0),1),getSampleMemCapacity()); loop=MAX(start,end-1); if (chan[i].audPos>0) { start=start+MIN(chan[i].audPos,s->lengthBRR-1)/16*9; } if (s->loopStart>=0) { - loop=start+s->loopStart/16*9; + loop=((s->depth!=DIV_SAMPLE_DEPTH_BRR)?9:0)+start+((s->loopStart/16)*9); } } else { start=0; @@ -817,7 +817,7 @@ void DivPlatformSNES::renderSamples(int sysID) { continue; } - int length=s->lengthBRR; + int length=s->lengthBRR+((s->loop && s->depth!=DIV_SAMPLE_DEPTH_BRR)?9:0); int actualLength=MIN((int)(getSampleMemCapacity()-memPos)/9*9,length); if (actualLength>0) { sampleOff[i]=memPos; diff --git a/src/engine/sample.cpp b/src/engine/sample.cpp index 5460aed32..950667109 100644 --- a/src/engine/sample.cpp +++ b/src/engine/sample.cpp @@ -490,8 +490,8 @@ bool DivSample::initInternal(DivSampleDepth d, int count) { case DIV_SAMPLE_DEPTH_BRR: // BRR if (dataBRR!=NULL) delete[] dataBRR; lengthBRR=9*((count+15)/16); - dataBRR=new unsigned char[lengthBRR]; - memset(dataBRR,0,lengthBRR); + dataBRR=new unsigned char[lengthBRR+9]; + memset(dataBRR,0,lengthBRR+9); break; case DIV_SAMPLE_DEPTH_VOX: // VOX if (dataVOX!=NULL) delete[] dataVOX; @@ -1100,7 +1100,7 @@ void DivSample::render(unsigned int formatMask) { } if (NOT_IN_FORMAT(DIV_SAMPLE_DEPTH_BRR)) { // BRR if (!initInternal(DIV_SAMPLE_DEPTH_BRR,samples)) return; - brrEncode(data16,dataBRR,(samples+15)&(~15),loop?loopStart:-1); + brrEncode(data16,dataBRR,samples,loop?loopStart:-1); } if (NOT_IN_FORMAT(DIV_SAMPLE_DEPTH_VOX)) { // VOX if (!initInternal(DIV_SAMPLE_DEPTH_VOX,samples)) return; From a69dc4731e10490a5b56aed28453f68e57bd0cef Mon Sep 17 00:00:00 2001 From: tildearrow Date: Mon, 5 Dec 2022 19:18:45 -0500 Subject: [PATCH 11/18] for real this time --- src/engine/brrUtils.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/engine/brrUtils.c b/src/engine/brrUtils.c index 76645de7f..a147c6ae0 100644 --- a/src/engine/brrUtils.c +++ b/src/engine/brrUtils.c @@ -126,8 +126,6 @@ void brrEncodeBlock(const short* buf, unsigned char* out, unsigned char range, u break; } - if (nextDec>32767) nextDec=32767; - if (nextDec<-32768) nextDec=-32768; nextDec&=0x7fff; if (nextDec&0x4000) nextDec|=0xffff8000; From 4f1412013a52f7a8dbe5a8a36f668d1895627bdc Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 6 Dec 2022 00:58:27 -0500 Subject: [PATCH 12/18] VIC-20: possibly fix sadfgbmk;lhsdhklj;asdf;kj --- src/engine/platform/vic20.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/platform/vic20.cpp b/src/engine/platform/vic20.cpp index 52a08836e..20ff0c8b4 100644 --- a/src/engine/platform/vic20.cpp +++ b/src/engine/platform/vic20.cpp @@ -80,7 +80,7 @@ void DivPlatformVIC20::calcAndWriteOutVol(int ch, int env) { } void DivPlatformVIC20::writeOutVol(int ch) { - if (!isMuted[ch]) { + if (!isMuted[ch] && chan[ch].active) { rWrite(14,chan[ch].outVol); } } From b149d1b92e630f5847aed1d2d8393961b1789afe Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 7 Dec 2022 01:47:11 -0500 Subject: [PATCH 13/18] enable debug builds again... #745 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 149d234c1..ffe48ee15 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,7 @@ defaults: shell: bash env: - BUILD_TYPE: Release + BUILD_TYPE: Debug jobs: build: From 056e67b2280f2d04f0cdd8b5ff77aa428dda7600 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 7 Dec 2022 02:57:19 -0500 Subject: [PATCH 14/18] dev129 - SNES: add option to toggle BRR emphasis --- papers/format.md | 10 +++++-- src/engine/brrUtils.c | 65 +++++++++++++++++++++++++++++++++++++----- src/engine/brrUtils.h | 6 ++-- src/engine/engine.h | 4 +-- src/engine/sample.cpp | 16 +++++++---- src/engine/sample.h | 11 ++++--- src/gui/sampleEdit.cpp | 25 ++++++++++++++++ 7 files changed, 113 insertions(+), 24 deletions(-) diff --git a/papers/format.md b/papers/format.md index e29b12891..685e1aefd 100644 --- a/papers/format.md +++ b/papers/format.md @@ -32,6 +32,8 @@ these fields are 0 in format versions prior to 100 (0.6pre1). the format versions are: +- 129: Furnace dev129 +- 128: Furnace dev128 - 127: Furnace dev127 - 126: Furnace dev126 - 125: Furnace dev125 @@ -1120,9 +1122,11 @@ size | description | - 16: 16-bit PCM 1 | loop direction (>=123) or reserved | - 0: forward - | - 0: backward - | - 0: ping-pong - 2 | reserved + | - 1: backward + | - 2: ping-pong + 1 | flags (>=129) or reserved + | - 0: BRR emphasis + 1 | reserved 4 | loop start | - -1 means no loop 4 | loop end diff --git a/src/engine/brrUtils.c b/src/engine/brrUtils.c index a147c6ae0..c4d07b398 100644 --- a/src/engine/brrUtils.c +++ b/src/engine/brrUtils.c @@ -138,7 +138,7 @@ void brrEncodeBlock(const short* buf, unsigned char* out, unsigned char range, u } } -long brrEncode(short* buf, unsigned char* out, long len, long loopStart) { +long brrEncode(short* buf, unsigned char* out, long len, long loopStart, unsigned char emphasis) { if (len==0) return 0; // encoding process: @@ -158,7 +158,12 @@ long brrEncode(short* buf, unsigned char* out, long len, long loopStart) { unsigned char filter=0; unsigned char range=0; - short in[16]; + short x0=0; + short x1=0; + short x2=0; + int emphOut=0; + + short in[17]; short last1[4][13]; short last2[4][13]; @@ -172,9 +177,9 @@ long brrEncode(short* buf, unsigned char* out, long len, long loopStart) { memset(possibleOut,0,4*13*8); for (long i=0; ilen) { + if (i+17>len) { long p=i; - for (int j=0; j<16; j++) { + for (int j=0; j<17; j++) { if (p>=len) { if (loopStart<0 || loopStart>=len) { in[j]=0; @@ -187,7 +192,22 @@ long brrEncode(short* buf, unsigned char* out, long len, long loopStart) { } } } else { - memcpy(in,&buf[i],16*sizeof(short)); + memcpy(in,&buf[i],17*sizeof(short)); + } + + // emphasis + if (emphasis) { + for (int j=0; j<17; j++) { + x0=x1; + x1=x2; + x2=in[j]; + + if (j==0) continue; + emphOut=((x1<<11)-x0*370-in[j]*374)/1305; + if (emphOut<-32768) emphOut=-32768; + if (emphOut>32767) emphOut=32767; + in[j-1]=emphOut; + } } // encode @@ -237,13 +257,27 @@ long brrEncode(short* buf, unsigned char* out, long len, long loopStart) { // encode loop block if (loopStart>=0) { long p=loopStart; - for (int i=0; i<16; i++) { + for (int i=0; i<17; i++) { if (p>=len) { p=loopStart; } in[i]=buf[p++]; } + if (emphasis) { + for (int j=0; j<17; j++) { + x0=x1; + x1=x2; + x2=in[j]; + + if (j==0) continue; + emphOut=((x1<<11)-x0*370-in[j]*374)/1305; + if (emphOut<-32768) emphOut=-32768; + if (emphOut>32767) emphOut=32767; + in[j-1]=emphOut; + } + } + // encode (filter 0/1 only) for (int j=0; j<2; j++) { for (int k=0; k<13; k++) { @@ -315,9 +349,11 @@ long brrEncode(short* buf, unsigned char* out, long len, long loopStart) { *out=next<<1; \ out++; -long brrDecode(unsigned char* buf, short* out, long len) { +long brrDecode(unsigned char* buf, short* out, long len, unsigned char emphasis) { if (len==0) return 0; + short* outOrig=out; + long total=0; int last1=0; @@ -344,5 +380,20 @@ long brrDecode(unsigned char* buf, short* out, long len) { buf+=9; } + if (emphasis) { + short x0=0; + short x1=0; + short x2=0; + for (long i=0; i<=total; i++) { + x0=x1; + x1=x2; + x2=(i>=total)?0:outOrig[i]; + + if (i==0) continue; + + outOrig[i-1]=(x0*370+x1*1305+x2*374)>>11; + } + } + return total; } diff --git a/src/engine/brrUtils.h b/src/engine/brrUtils.h index 11e7f0520..e4adc3a6d 100644 --- a/src/engine/brrUtils.h +++ b/src/engine/brrUtils.h @@ -33,18 +33,20 @@ extern "C" { * @param out output buffer. shall be at least 9*((15+len)/16) shorts in size (9 more if loopStart is not -1!) * @param len input length (should be a multiple of 16. if it isn't, the output will be padded). * @param loopStart beginning of loop area (may be -1 for no loop). this is used to ensure the respective block has no filter in order to loop properly. + * @param emphasis apply filter to compensate for Gaussian interpolation high frequency loss. * @return number of written samples. */ -long brrEncode(short* buf, unsigned char* out, long len, long loopStart); +long brrEncode(short* buf, unsigned char* out, long len, long loopStart, unsigned char emphasis); /** * read len bytes from buf, decode BRR and output to out. * @param buf input data. * @param out output buffer. shall be at least 16*(len/9) shorts in size. * @param len input length (shall be a multiple of 9). + * @param emphasis apply filter to simulate Gaussian interpolation high frequency loss. * @return number of written bytes. */ -long brrDecode(unsigned char* buf, short* out, long len); +long brrDecode(unsigned char* buf, short* out, long len, unsigned char emphasis); #ifdef __cplusplus } diff --git a/src/engine/engine.h b/src/engine/engine.h index ab028aca4..3b8881213 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -47,8 +47,8 @@ #define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock(); #define BUSY_END isBusy.unlock(); softLocked=false; -#define DIV_VERSION "dev128" -#define DIV_ENGINE_VERSION 128 +#define DIV_VERSION "dev129" +#define DIV_ENGINE_VERSION 129 // for imports #define DIV_VERSION_MOD 0xff01 #define DIV_VERSION_FC 0xff02 diff --git a/src/engine/sample.cpp b/src/engine/sample.cpp index 950667109..148e63fb5 100644 --- a/src/engine/sample.cpp +++ b/src/engine/sample.cpp @@ -52,8 +52,8 @@ void DivSample::putSampleData(SafeWriter* w) { w->writeI(centerRate); w->writeC(depth); w->writeC(loopMode); + w->writeC(brrEmphasis); w->writeC(0); // reserved - w->writeC(0); w->writeI(loop?loopStart:-1); w->writeI(loop?loopEnd:-1); @@ -125,9 +125,13 @@ DivDataErrors DivSample::readSampleData(SafeReader& reader, short version) { reader.readC(); } + if (version>=129) { + brrEmphasis=reader.readC(); + } else { + reader.readC(); + } // reserved reader.readC(); - reader.readC(); loopStart=reader.readI(); loopEnd=reader.readI(); @@ -1041,7 +1045,7 @@ void DivSample::render(unsigned int formatMask) { } break; case DIV_SAMPLE_DEPTH_BRR: // BRR - brrDecode(dataBRR,data16,lengthBRR); + brrDecode(dataBRR,data16,lengthBRR,brrEmphasis); break; case DIV_SAMPLE_DEPTH_VOX: // VOX oki_decode(dataVOX,data16,samples); @@ -1100,7 +1104,7 @@ void DivSample::render(unsigned int formatMask) { } if (NOT_IN_FORMAT(DIV_SAMPLE_DEPTH_BRR)) { // BRR if (!initInternal(DIV_SAMPLE_DEPTH_BRR,samples)) return; - brrEncode(data16,dataBRR,samples,loop?loopStart:-1); + brrEncode(data16,dataBRR,samples,loop?loopStart:-1,brrEmphasis); } if (NOT_IN_FORMAT(DIV_SAMPLE_DEPTH_VOX)) { // VOX if (!initInternal(DIV_SAMPLE_DEPTH_VOX,samples)) return; @@ -1174,9 +1178,9 @@ DivSampleHistory* DivSample::prepareUndo(bool data, bool doNotPush) { duplicate=new unsigned char[getCurBufLen()]; memcpy(duplicate,getCurBuf(),getCurBufLen()); } - h=new DivSampleHistory(duplicate,getCurBufLen(),samples,depth,rate,centerRate,loopStart,loopEnd,loop,loopMode); + h=new DivSampleHistory(duplicate,getCurBufLen(),samples,depth,rate,centerRate,loopStart,loopEnd,loop,brrEmphasis,loopMode); } else { - h=new DivSampleHistory(depth,rate,centerRate,loopStart,loopEnd,loop,loopMode); + h=new DivSampleHistory(depth,rate,centerRate,loopStart,loopEnd,loop,brrEmphasis,loopMode); } if (!doNotPush) { while (!redoHist.empty()) { diff --git a/src/engine/sample.h b/src/engine/sample.h index 0e233843c..86beea2d2 100644 --- a/src/engine/sample.h +++ b/src/engine/sample.h @@ -60,10 +60,10 @@ struct DivSampleHistory { unsigned int length, samples; DivSampleDepth depth; int rate, centerRate, loopStart, loopEnd; - bool loop; + bool loop, brrEmphasis; DivSampleLoopMode loopMode; bool hasSample; - DivSampleHistory(void* d, unsigned int l, unsigned int s, DivSampleDepth de, int r, int cr, int ls, int le, bool lp, DivSampleLoopMode lm): + DivSampleHistory(void* d, unsigned int l, unsigned int s, DivSampleDepth de, int r, int cr, int ls, int le, bool lp, bool be, DivSampleLoopMode lm): data((unsigned char*)d), length(l), samples(s), @@ -73,9 +73,10 @@ struct DivSampleHistory { loopStart(ls), loopEnd(le), loop(lp), + brrEmphasis(be), loopMode(lm), hasSample(true) {} - DivSampleHistory(DivSampleDepth de, int r, int cr, int ls, int le, bool lp, DivSampleLoopMode lm): + DivSampleHistory(DivSampleDepth de, int r, int cr, int ls, int le, bool lp, bool be, DivSampleLoopMode lm): data(NULL), length(0), samples(0), @@ -85,6 +86,7 @@ struct DivSampleHistory { loopStart(ls), loopEnd(le), loop(lp), + brrEmphasis(be), loopMode(lm), hasSample(false) {} ~DivSampleHistory(); @@ -106,7 +108,7 @@ struct DivSample { // - 10: VOX ADPCM // - 16: 16-bit PCM DivSampleDepth depth; - bool loop; + bool loop, brrEmphasis; // valid values are: // - 0: Forward loop // - 1: Backward loop @@ -306,6 +308,7 @@ struct DivSample { loopOffP(0), depth(DIV_SAMPLE_DEPTH_16BIT), loop(false), + brrEmphasis(true), loopMode(DIV_SAMPLE_LOOP_FORWARD), data8(NULL), data16(NULL), diff --git a/src/gui/sampleEdit.cpp b/src/gui/sampleEdit.cpp index fb50fd567..a953742b6 100644 --- a/src/gui/sampleEdit.cpp +++ b/src/gui/sampleEdit.cpp @@ -190,6 +190,31 @@ void FurnaceGUI::drawSampleEdit() { ImGui::EndCombo(); } + bool isThereSNES=false; + for (int i=0; isong.systemLen; i++) { + if (e->song.system[i]==DIV_SYSTEM_SNES) { + isThereSNES=true; + break; + } + } + if (sample->depth==DIV_SAMPLE_DEPTH_BRR || isThereSNES) { + bool be=sample->brrEmphasis; + if (ImGui::Checkbox("BRR emphasis",&be)) { + sample->prepareUndo(true); + sample->brrEmphasis=be; + e->renderSamplesP(); + updateSampleTex=true; + MARK_MODIFIED; + } + if (ImGui::IsItemHovered()) { + if (sample->depth==DIV_SAMPLE_DEPTH_BRR) { + ImGui::SetTooltip("this is a BRR sample.\nenabling this option will muffle it (only affects non-SNES chips)."); + } else { + ImGui::SetTooltip("enable this option to slightly boost high frequencies\nto compensate for the SNES' Gaussian filter's muffle."); + } + } + } + ImGui::TableNextColumn(); ImGui::Text("C-4 (Hz)"); ImGui::SameLine(); From c2bb86b2e489c79585dc18c8bd897b65652b5a12 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 7 Dec 2022 03:33:38 -0500 Subject: [PATCH 15/18] QSound: whoops --- src/engine/platform/qsound.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/platform/qsound.cpp b/src/engine/platform/qsound.cpp index cc411fa5f..e513d5313 100644 --- a/src/engine/platform/qsound.cpp +++ b/src/engine/platform/qsound.cpp @@ -783,7 +783,7 @@ void DivPlatformQSound::renderSamples(int sysID) { for (int i=0; idataQSoundA[i]; } - sampleLoaded[i]=true; + sampleLoadedBS[i]=true; } offBS[i]=memPos; memPos+=length+16; From a2be33cf95125498e9d71bdc574d6d03c40c3559 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 7 Dec 2022 03:42:54 -0500 Subject: [PATCH 16/18] GUI: add sample memory warnings in the sample list --- src/gui/dataList.cpp | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/gui/dataList.cpp b/src/gui/dataList.cpp index face74247..6d23fa2a1 100644 --- a/src/gui/dataList.cpp +++ b/src/gui/dataList.cpp @@ -684,20 +684,48 @@ void FurnaceGUI::actualWaveList() { void FurnaceGUI::actualSampleList() { for (int i=0; i<(int)e->song.sample.size(); i++) { + bool memWarning=false; + DivSample* sample=e->song.sample[i]; ImGui::TableNextRow(); ImGui::TableNextColumn(); + for (int j=0; jsong.systemLen; j++) { + DivDispatch* dispatch=e->getDispatch(j); + if (dispatch==NULL) continue; + + for (int k=0; k<4; k++) { + if (dispatch->getSampleMemCapacity(k)==0) continue; + if (!dispatch->isSampleLoaded(k,i) && sample->renderOn[k][j]) { + memWarning=true; + break; + } + } + if (memWarning) break; + } + if (memWarning) ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_SAMPLE_CHIP_WARNING]); if (ImGui::Selectable(fmt::sprintf("%d: %s##_SAM%d",i,sample->name,i).c_str(),curSample==i)) { curSample=i; samplePos=0; updateSampleTex=true; } - if (wantScrollList && curSample==i) ImGui::SetScrollHereY(); if (ImGui::IsItemHovered() && !mobileUI) { + ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_TEXT]); ImGui::SetTooltip("Bank %d: %s",i/12,sampleNote[i%12]); if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) { sampleEditOpen=true; } + ImGui::PopStyleColor(); } + if (memWarning) { + ImGui::SameLine(); + ImGui::Text(ICON_FA_EXCLAMATION_TRIANGLE); + if (ImGui::IsItemHovered() && !mobileUI) { + ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_TEXT]); + ImGui::SetTooltip("out of memory for this sample!"); + ImGui::PopStyleColor(); + } + ImGui::PopStyleColor(); + } + if (wantScrollList && curSample==i) ImGui::SetScrollHereY(); } } From c91e947ea3ae2235253815cd3f981a4e2789a88e Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 7 Dec 2022 23:27:19 -0500 Subject: [PATCH 17/18] SN: prepare for new easy threshold formula --- src/engine/platform/sms.cpp | 23 +++++++---------------- src/engine/platform/sms.h | 2 -- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index 41ef81ee0..16a7c5017 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -125,6 +125,9 @@ double DivPlatformSMS::NOTE_SN(int ch, int note) { if (parent->song.linearPitch==2 || !easyNoise) { return NOTE_PERIODIC(note); } + int easyStartingPeriod=16; + //int easyThreshold=round(CHIP_CLOCK/(parent->song.tuning*0.0625*pow(2.0,(float)(nbase+384)/(128.0*12.0)))/CHIP_DIVIDER); + int easyThreshold=round(log((CHIP_CLOCK/(easyStartingPeriod*CHIP_DIVIDER))/parent->song.tuning)/log(2.0)); if (note>easyThreshold) { return MAX(0,easyStartingPeriod-(note-easyThreshold)); } @@ -132,8 +135,9 @@ double DivPlatformSMS::NOTE_SN(int ch, int note) { } int DivPlatformSMS::snCalcFreq(int ch) { - if (parent->song.linearPitch==2 && easyNoise && chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2>(easyThreshold<<7)) { - int ret=(((easyStartingPeriod<<7)+0x40)-(chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2-(easyThreshold<<7)))>>7; + int easyThreshold=round(128.0*log((CHIP_CLOCK/(easyStartingPeriod*CHIP_DIVIDER))/parent->song.tuning)/log(2.0)); + if (parent->song.linearPitch==2 && easyNoise && chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2>(easyThreshold)) { + int ret=(((easyStartingPeriod<<7))-(chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2-(easyThreshold)))>>7; if (ret<0) ret=0; return ret; } @@ -464,38 +468,24 @@ void DivPlatformSMS::setFlags(const DivConfig& flags) { switch (flags.getInt("clockSel",0)) { case 1: chipClock=COLOR_PAL*4.0/5.0; - easyThreshold=84; - easyStartingPeriod=13; break; case 2: chipClock=4000000; - easyThreshold=86; - easyStartingPeriod=13; break; case 3: chipClock=COLOR_NTSC/2.0; - easyThreshold=72; - easyStartingPeriod=13; break; case 4: chipClock=3000000; - easyThreshold=81; - easyStartingPeriod=13; break; case 5: chipClock=2000000; - easyThreshold=74; - easyStartingPeriod=13; break; case 6: chipClock=COLOR_NTSC/8.0; - easyThreshold=48; - easyStartingPeriod=13; break; default: chipClock=COLOR_NTSC; - easyThreshold=84; - easyStartingPeriod=13; break; } CHECK_CUSTOM_CLOCK; @@ -569,6 +559,7 @@ void DivPlatformSMS::setFlags(const DivConfig& flags) { stereo=false; break; } + rate=chipClock/divider; for (int i=0; i<4; i++) { oscBuf[i]->rate=rate; diff --git a/src/engine/platform/sms.h b/src/engine/platform/sms.h index ce3ee5e72..41f0efe48 100644 --- a/src/engine/platform/sms.h +++ b/src/engine/platform/sms.h @@ -65,8 +65,6 @@ class DivPlatformSMS: public DivDispatch { int divider=16; double toneDivider=64.0; double noiseDivider=64.0; - int easyThreshold; - int easyStartingPeriod; bool updateSNMode; bool resetPhase; bool isRealSN; From 1caf61421b735e83a6e6f2cca56d94f29442a5af Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 7 Dec 2022 23:34:01 -0500 Subject: [PATCH 18/18] make Furnace fast --- .github/workflows/build.yml | 2 +- src/engine/platform/sms.cpp | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ffe48ee15..149d234c1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -11,7 +11,7 @@ defaults: shell: bash env: - BUILD_TYPE: Debug + BUILD_TYPE: Release jobs: build: diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index 16a7c5017..1d51f56bd 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -127,7 +127,7 @@ double DivPlatformSMS::NOTE_SN(int ch, int note) { } int easyStartingPeriod=16; //int easyThreshold=round(CHIP_CLOCK/(parent->song.tuning*0.0625*pow(2.0,(float)(nbase+384)/(128.0*12.0)))/CHIP_DIVIDER); - int easyThreshold=round(log((CHIP_CLOCK/(easyStartingPeriod*CHIP_DIVIDER))/parent->song.tuning)/log(2.0)); + int easyThreshold=round(log((chipClock/(easyStartingPeriod*CHIP_DIVIDER))/parent->song.tuning)/log(2.0)); if (note>easyThreshold) { return MAX(0,easyStartingPeriod-(note-easyThreshold)); } @@ -135,13 +135,16 @@ double DivPlatformSMS::NOTE_SN(int ch, int note) { } int DivPlatformSMS::snCalcFreq(int ch) { - int easyThreshold=round(128.0*log((CHIP_CLOCK/(easyStartingPeriod*CHIP_DIVIDER))/parent->song.tuning)/log(2.0)); + double CHIP_DIVIDER=toneDivider; + if (ch==3) CHIP_DIVIDER=noiseDivider; + int easyStartingPeriod=16; + int easyThreshold=round(128.0*log((chipClock/(easyStartingPeriod*CHIP_DIVIDER))/parent->song.tuning)/log(2.0)); if (parent->song.linearPitch==2 && easyNoise && chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2>(easyThreshold)) { int ret=(((easyStartingPeriod<<7))-(chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2-(easyThreshold)))>>7; if (ret<0) ret=0; return ret; } - return parent->calcFreq(chan[ch].baseFreq,chan[ch].pitch,true,0,chan[ch].pitch2,chipClock,ch==3?noiseDivider:toneDivider); + return parent->calcFreq(chan[ch].baseFreq,chan[ch].pitch,true,0,chan[ch].pitch2,chipClock,CHIP_DIVIDER); } void DivPlatformSMS::tick(bool sysTick) {