mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-01 18:42:40 +00:00
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
This commit is contained in:
parent
6a7e7ba571
commit
bdc66ae33e
9 changed files with 40 additions and 16 deletions
|
@ -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
|
||||
|
|
|
@ -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; j<numFilters; j++) {
|
||||
for (int k=0; k<13; k++) {
|
||||
brrEncodeBlock(in,possibleOut[j][k],k,j,&last1[j][k],&last2[j][k],&avgError[j][k]);
|
||||
}
|
||||
|
@ -228,7 +229,7 @@ long brrEncode(short* buf, unsigned char* out, long len, long loopStart, unsigne
|
|||
}
|
||||
}
|
||||
} else {
|
||||
for (int j=0; j<4; j++) {
|
||||
for (int j=0; j<numFilters; j++) {
|
||||
for (int k=0; k<13; k++) {
|
||||
if (avgError[j][k]<candError) {
|
||||
candError=avgError[j][k];
|
||||
|
@ -245,7 +246,7 @@ long brrEncode(short* buf, unsigned char* out, long len, long loopStart, unsigne
|
|||
out[j+1]=possibleOut[filter][range][j];
|
||||
}
|
||||
|
||||
for (int j=0; j<4; j++) {
|
||||
for (int j=0; j<numFilters; j++) {
|
||||
for (int k=0; k<13; k++) {
|
||||
last1[j][k]=last1[filter][range];
|
||||
last2[j][k]=last2[filter][range];
|
||||
|
|
|
@ -34,9 +34,10 @@ extern "C" {
|
|||
* @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.
|
||||
* @param noFilter do not use filters in any block. this is used to allow seeking to any sample position.
|
||||
* @return number of written samples.
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* read len bytes from buf, decode BRR and output to out.
|
||||
|
|
|
@ -54,8 +54,8 @@ class DivWorkPool;
|
|||
|
||||
//#define DIV_UNSTABLE
|
||||
|
||||
#define DIV_VERSION "0.6.4"
|
||||
#define DIV_ENGINE_VERSION 212
|
||||
#define DIV_VERSION "dev213"
|
||||
#define DIV_ENGINE_VERSION 213
|
||||
// for imports
|
||||
#define DIV_VERSION_MOD 0xff01
|
||||
#define DIV_VERSION_FC 0xff02
|
||||
|
|
|
@ -261,6 +261,7 @@ SafeWriter* DivEngine::saveText(bool separatePatterns) {
|
|||
w->writeText(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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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<<DIV_SAMPLE_DEPTH_8BIT)) {
|
||||
bool di=sample->dither;
|
||||
if (ImGui::Checkbox(_("8-bit dither"),&di)) {
|
||||
|
|
Loading…
Reference in a new issue