Merge branch 'master' of https://github.com/tildearrow/furnace into es5506_alt

This commit is contained in:
cam900 2022-12-08 11:38:08 +09:00
commit ef08e9b0c2
11 changed files with 145 additions and 28 deletions

View File

@ -11,7 +11,7 @@ defaults:
shell: bash
env:
BUILD_TYPE: Release
BUILD_TYPE: Debug
jobs:
build:

View File

@ -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

View File

@ -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; i<len; i+=16) {
if (i+16>len) {
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;
}

View File

@ -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
}

View File

@ -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

View File

@ -783,7 +783,7 @@ void DivPlatformQSound::renderSamples(int sysID) {
for (int i=0; i<length; i++) {
sampleMem[(memPos+i)]=s->dataQSoundA[i];
}
sampleLoaded[i]=true;
sampleLoadedBS[i]=true;
}
offBS[i]=memPos;
memPos+=length+16;

View File

@ -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);
}
}

View File

@ -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()) {

View File

@ -61,10 +61,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),
@ -74,9 +74,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),
@ -86,6 +87,7 @@ struct DivSampleHistory {
loopStart(ls),
loopEnd(le),
loop(lp),
brrEmphasis(be),
loopMode(lm),
hasSample(false) {}
~DivSampleHistory();
@ -107,7 +109,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
@ -307,6 +309,7 @@ struct DivSample {
loopOffP(0),
depth(DIV_SAMPLE_DEPTH_16BIT),
loop(false),
brrEmphasis(true),
loopMode(DIV_SAMPLE_LOOP_FORWARD),
data8(NULL),
data16(NULL),

View File

@ -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; j<e->song.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();
}
}

View File

@ -191,6 +191,31 @@ void FurnaceGUI::drawSampleEdit() {
}
ImGui::Text("Length: %d",sample->samples);
bool isThereSNES=false;
for (int i=0; i<e->song.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();