From 4f1412013a52f7a8dbe5a8a36f668d1895627bdc Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 6 Dec 2022 00:58:27 -0500 Subject: [PATCH 1/5] 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 52a08836..20ff0c8b 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 2/5] 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 149d234c..ffe48ee1 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 3/5] 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 e29b1289..685e1aef 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 a147c6ae..c4d07b39 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 11e7f052..e4adc3a6 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 ab028aca..3b888121 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 95066710..148e63fb 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 0e233843..86beea2d 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 fb50fd56..a953742b 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 4/5] 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 cc411fa5..e513d531 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 5/5] 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 face7424..6d23fa2a 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(); } }