From bdc66ae33eb43b1767a442d7fd666f96fe5c8af7 Mon Sep 17 00:00:00 2001 From: Natt Akuma Date: Sat, 22 Jun 2024 14:37:00 +0700 Subject: [PATCH] SNES: add an option to not encode BRR with unstable filters This is useful for seeking to anywhere within the sample using sample offset commands --- papers/format.md | 1 + src/engine/brrUtils.c | 9 +++++---- src/engine/brrUtils.h | 3 ++- src/engine/engine.h | 4 ++-- src/engine/fileOps/text.cpp | 1 + src/engine/sample.cpp | 13 ++++++++----- src/engine/sample.h | 11 +++++++---- src/gui/doAction.cpp | 1 + src/gui/sampleEdit.cpp | 13 +++++++++++++ 9 files changed, 40 insertions(+), 16 deletions(-) diff --git a/papers/format.md b/papers/format.md index 56c56ea46..479bb3067 100644 --- a/papers/format.md +++ b/papers/format.md @@ -586,6 +586,7 @@ size | description | - 0: BRR emphasis 1 | flags 2 (>=159) or reserved | - 0: dither + | - 1: no BRR filters (>=213) 4 | loop start | - -1 means no loop 4 | loop end diff --git a/src/engine/brrUtils.c b/src/engine/brrUtils.c index c4d07b398..38073fb4b 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, unsigned char emphasis) { +long brrEncode(short* buf, unsigned char* out, long len, long loopStart, unsigned char emphasis, unsigned char noFilter) { if (len==0) return 0; // encoding process: @@ -157,6 +157,7 @@ long brrEncode(short* buf, unsigned char* out, long len, long loopStart, unsigne long total=0; unsigned char filter=0; unsigned char range=0; + unsigned char numFilters=noFilter?2:4; short x0=0; short x1=0; @@ -211,7 +212,7 @@ long brrEncode(short* buf, unsigned char* out, long len, long loopStart, unsigne } // encode - for (int j=0; j<4; j++) { + for (int j=0; jwriteText(fmt::sprintf(" - mode: %s\n",sampleLoopModes[sample->loopMode&3])); } w->writeText(fmt::sprintf("- BRR emphasis: %s\n",trueFalse[sample->brrEmphasis?1:0])); + w->writeText(fmt::sprintf("- no BRR filters: %s\n",trueFalse[sample->brrNoFilter?1:0])); w->writeText(fmt::sprintf("- dither: %s\n",trueFalse[sample->dither?1:0])); // TODO' render matrix diff --git a/src/engine/sample.cpp b/src/engine/sample.cpp index a7e542c86..020e0dec7 100644 --- a/src/engine/sample.cpp +++ b/src/engine/sample.cpp @@ -56,7 +56,7 @@ void DivSample::putSampleData(SafeWriter* w) { w->writeC(depth); w->writeC(loopMode); w->writeC(brrEmphasis); - w->writeC(dither); + w->writeC((dither?1:0)|(brrNoFilter?2:0)); w->writeI(loop?loopStart:-1); w->writeI(loop?loopEnd:-1); @@ -134,7 +134,9 @@ DivDataErrors DivSample::readSampleData(SafeReader& reader, short version) { reader.readC(); } if (version>=159) { - dither=reader.readC()&1; + signed char c=reader.readC(); + dither=c&1; + if (version>=213) brrNoFilter=c&2; } else { reader.readC(); } @@ -1423,7 +1425,7 @@ void DivSample::render(unsigned int formatMask) { if (NOT_IN_FORMAT(DIV_SAMPLE_DEPTH_BRR)) { // BRR int sampleCount=loop?loopEnd:samples; if (!initInternal(DIV_SAMPLE_DEPTH_BRR,sampleCount)) return; - brrEncode(data16,dataBRR,sampleCount,loop?loopStart:-1,brrEmphasis); + brrEncode(data16,dataBRR,sampleCount,loop?loopStart:-1,brrEmphasis,brrNoFilter); } if (NOT_IN_FORMAT(DIV_SAMPLE_DEPTH_VOX)) { // VOX if (!initInternal(DIV_SAMPLE_DEPTH_VOX,samples)) return; @@ -1564,9 +1566,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,brrEmphasis,dither,loopMode); + h=new DivSampleHistory(duplicate,getCurBufLen(),samples,depth,rate,centerRate,loopStart,loopEnd,loop,brrEmphasis,brrNoFilter,dither,loopMode); } else { - h=new DivSampleHistory(depth,rate,centerRate,loopStart,loopEnd,loop,brrEmphasis,dither,loopMode); + h=new DivSampleHistory(depth,rate,centerRate,loopStart,loopEnd,loop,brrEmphasis,brrNoFilter,dither,loopMode); } if (!doNotPush) { while (!redoHist.empty()) { @@ -1600,6 +1602,7 @@ DivSampleHistory* DivSample::prepareUndo(bool data, bool doNotPush) { loopEnd=h->loopEnd; \ loop=h->loop; \ brrEmphasis=h->brrEmphasis; \ + brrNoFilter=h->brrNoFilter; \ dither=h->dither; \ loopMode=h->loopMode; diff --git a/src/engine/sample.h b/src/engine/sample.h index dda4b732b..5fc593d23 100644 --- a/src/engine/sample.h +++ b/src/engine/sample.h @@ -65,10 +65,10 @@ struct DivSampleHistory { unsigned int length, samples; DivSampleDepth depth; int rate, centerRate, loopStart, loopEnd; - bool loop, brrEmphasis, dither; + bool loop, brrEmphasis, brrNoFilter, dither; 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, bool be, bool di, 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, bool bf, bool di, DivSampleLoopMode lm): data((unsigned char*)d), length(l), samples(s), @@ -79,10 +79,11 @@ struct DivSampleHistory { loopEnd(le), loop(lp), brrEmphasis(be), + brrNoFilter(bf), dither(di), loopMode(lm), hasSample(true) {} - DivSampleHistory(DivSampleDepth de, int r, int cr, int ls, int le, bool lp, bool be, bool di, DivSampleLoopMode lm): + DivSampleHistory(DivSampleDepth de, int r, int cr, int ls, int le, bool lp, bool be, bool bf, bool di, DivSampleLoopMode lm): data(NULL), length(0), samples(0), @@ -93,6 +94,7 @@ struct DivSampleHistory { loopEnd(le), loop(lp), brrEmphasis(be), + brrNoFilter(bf), dither(di), loopMode(lm), hasSample(false) {} @@ -118,7 +120,7 @@ struct DivSample { // - 13: IMA ADPCM // - 16: 16-bit PCM DivSampleDepth depth; - bool loop, brrEmphasis, dither; + bool loop, brrEmphasis, brrNoFilter, dither; // valid values are: // - 0: Forward loop // - 1: Backward loop @@ -337,6 +339,7 @@ struct DivSample { depth(DIV_SAMPLE_DEPTH_16BIT), loop(false), brrEmphasis(true), + brrNoFilter(false), dither(false), loopMode(DIV_SAMPLE_LOOP_FORWARD), data8(NULL), diff --git a/src/gui/doAction.cpp b/src/gui/doAction.cpp index 985fc06ca..d6d8ea434 100644 --- a/src/gui/doAction.cpp +++ b/src/gui/doAction.cpp @@ -931,6 +931,7 @@ void FurnaceGUI::doAction(int what) { sample->loop=prevSample->loop; sample->loopMode=prevSample->loopMode; sample->brrEmphasis=prevSample->brrEmphasis; + sample->brrNoFilter=prevSample->brrNoFilter; sample->dither=prevSample->dither; sample->depth=prevSample->depth; if (sample->init(prevSample->samples)) { diff --git a/src/gui/sampleEdit.cpp b/src/gui/sampleEdit.cpp index dfcc1edc9..88337e39c 100644 --- a/src/gui/sampleEdit.cpp +++ b/src/gui/sampleEdit.cpp @@ -541,6 +541,19 @@ void FurnaceGUI::drawSampleEdit() { } } } + if (sample->depth!=DIV_SAMPLE_DEPTH_BRR && isThereSNES) { + bool bf=sample->brrNoFilter; + if (ImGui::Checkbox(_("no BRR filters"),&bf)) { + sample->prepareUndo(true); + sample->brrNoFilter=bf; + e->renderSamplesP(curSample); + updateSampleTex=true; + MARK_MODIFIED; + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip(_("enable this option to not use BRR blocks with filters\nand allow sample offset commands to be used safely.")); + } + } if (sample->depth!=DIV_SAMPLE_DEPTH_8BIT && e->getSampleFormatMask()&(1L<dither; if (ImGui::Checkbox(_("8-bit dither"),&di)) {