Merge branch 'tildearrow:master' into SID3

This commit is contained in:
LTVA1 2024-08-23 12:53:29 +03:00 committed by GitHub
commit 1fbbe29d14
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 72 additions and 25 deletions

Binary file not shown.

View file

@ -46,7 +46,9 @@ void* TAAudioSDL::getContext() {
bool TAAudioSDL::quit() { bool TAAudioSDL::quit() {
if (!initialized) return false; if (!initialized) return false;
if (ai!=0) {
SDL_CloseAudioDevice(ai); SDL_CloseAudioDevice(ai);
}
if (running) { if (running) {
running=false; running=false;

View file

@ -34,5 +34,6 @@ class TAAudioSDL: public TAAudio {
std::vector<String> listAudioDevices(); std::vector<String> listAudioDevices();
bool init(TAAudioDesc& request, TAAudioDesc& response); bool init(TAAudioDesc& request, TAAudioDesc& response);
TAAudioSDL(): TAAudioSDL():
ai(0),
audioSysStarted(false) {} audioSysStarted(false) {}
}; };

View file

@ -580,7 +580,7 @@ class DivEngine {
void processRow(int i, bool afterDelay); void processRow(int i, bool afterDelay);
void nextOrder(); void nextOrder();
void nextRow(); void nextRow();
void performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool* sampleDir, bool isSecond, int* pendingFreq, int* playingSample, int* setPos, unsigned int* sampleOff8, unsigned int* sampleLen8, size_t bankOffset, bool directStream); void performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool* sampleDir, bool isSecond, int* pendingFreq, int* playingSample, int* setPos, unsigned int* sampleOff8, unsigned int* sampleLen8, size_t bankOffset, bool directStream, bool* sampleStoppable);
// returns true if end of song. // returns true if end of song.
bool nextTick(bool noAccum=false, bool inhibitLowLat=false); bool nextTick(bool noAccum=false, bool inhibitLowLat=false);
bool perSystemEffect(int ch, unsigned char effect, unsigned char effectVal); bool perSystemEffect(int ch, unsigned char effect, unsigned char effectVal);

View file

@ -165,8 +165,12 @@ int DivPlatformSMS::snCalcFreq(int ch) {
if (ch==3) CHIP_DIVIDER=noiseDivider; if (ch==3) CHIP_DIVIDER=noiseDivider;
int easyStartingPeriod=16; int easyStartingPeriod=16;
int easyThreshold=round(128.0*12.0*log((chipClock/(easyStartingPeriod*CHIP_DIVIDER))/(0.0625*parent->song.tuning))/log(2.0))-384+64; int easyThreshold=round(128.0*12.0*log((chipClock/(easyStartingPeriod*CHIP_DIVIDER))/(0.0625*parent->song.tuning))/log(2.0))-384+64;
if (parent->song.linearPitch==2 && easyNoise && chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2>(easyThreshold)) { int curFreq=chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2+(chan[ch].arpOff<<7);
int ret=(((easyStartingPeriod<<7))-(chan[ch].baseFreq+chan[ch].pitch+chan[ch].pitch2-(easyThreshold)))>>7; if (chan[ch].fixedArp) {
curFreq=chan[ch].baseNoteOverride<<7;
}
if (parent->song.linearPitch==2 && easyNoise && curFreq>easyThreshold) {
int ret=(((easyStartingPeriod<<7))-(curFreq-(easyThreshold)))>>7;
if (ret<0) ret=0; if (ret<0) ret=0;
return ret; return ret;
} }

View file

@ -840,6 +840,8 @@ void DivPlatformSNES::reset() {
memcpy(sampleMem,copyOfSampleMem,65536); memcpy(sampleMem,copyOfSampleMem,65536);
dsp.init(sampleMem); dsp.init(sampleMem);
dsp.set_output(NULL,0); dsp.set_output(NULL,0);
dsp.setupInterpolation(!interpolationOff);
memset(regPool,0,128); memset(regPool,0,128);
// this can't be 0 or channel 1 won't play // this can't be 0 or channel 1 won't play
// this can't be 0x100 either as that's used by SPC700 page 1 and the stack // this can't be 0x100 either as that's used by SPC700 page 1 and the stack
@ -1022,6 +1024,8 @@ void DivPlatformSNES::setFlags(const DivConfig& flags) {
initEchoFIR[7]=flags.getInt("echoFilter7",0); initEchoFIR[7]=flags.getInt("echoFilter7",0);
initEchoMask=flags.getInt("echoMask",0); initEchoMask=flags.getInt("echoMask",0);
interpolationOff=flags.getBool("interpolationOff",false);
} }
int DivPlatformSNES::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { int DivPlatformSNES::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {

View file

@ -69,6 +69,7 @@ class DivPlatformSNES: public DivDispatch {
bool writeEcho; bool writeEcho;
bool writeDryVol; bool writeDryVol;
bool echoOn; bool echoOn;
bool interpolationOff;
bool initEchoOn; bool initEchoOn;
signed char initEchoVolL; signed char initEchoVolL;

View file

@ -135,9 +135,19 @@ static short const gauss [512] =
1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305, 1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305,
}; };
void SPC_DSP::setupInterpolation(bool interpolate)
{
for(int i = 0; i < voice_count; i++)
{
m.voices[i].interpolate = interpolate;
}
}
inline int SPC_DSP::interpolate( voice_t const* v ) inline int SPC_DSP::interpolate( voice_t const* v )
{ {
// Make pointers into gaussian based on fractional position between samples // Make pointers into gaussian based on fractional position between samples
if(v->interpolate)
{
int offset = v->interp_pos >> 4 & 0xFF; int offset = v->interp_pos >> 4 & 0xFF;
short const* fwd = gauss + 255 - offset; short const* fwd = gauss + 255 - offset;
short const* rev = gauss + offset; // mirror left half of gaussian short const* rev = gauss + offset; // mirror left half of gaussian
@ -154,6 +164,11 @@ inline int SPC_DSP::interpolate( voice_t const* v )
out &= ~1; out &= ~1;
return out; return out;
} }
else
{
return v->buf [(v->interp_pos >> 12) + v->buf_pos]; //Furnace addition -- no interpolation
}
}
//// Counters //// Counters

View file

@ -27,6 +27,9 @@ public:
// output buffer could hold. // output buffer could hold.
int sample_count() const; int sample_count() const;
// Furnace addition: disable/enable Gaussian interpolation
void setupInterpolation(bool interpolate);
// Emulation // Emulation
// Resets DSP to power-on state // Resets DSP to power-on state
@ -122,6 +125,7 @@ public:
int hidden_env; // used by GAIN mode 7, very obscure quirk int hidden_env; // used by GAIN mode 7, very obscure quirk
uint8_t t_envx_out; uint8_t t_envx_out;
sample_t out[2]; // Furnace addition, for per-channel oscilloscope sample_t out[2]; // Furnace addition, for per-channel oscilloscope
bool interpolate; // Furnace addition, to disable interpolation
}; };
// Furnace addition, gets a voice // Furnace addition, gets a voice

View file

@ -24,7 +24,9 @@
constexpr int MASTER_CLOCK_PREC=(sizeof(void*)==8)?8:0; constexpr int MASTER_CLOCK_PREC=(sizeof(void*)==8)?8:0;
void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool* sampleDir, bool isSecond, int* pendingFreq, int* playingSample, int* setPos, unsigned int* sampleOff8, unsigned int* sampleLen8, size_t bankOffset, bool directStream) { // this function is so long
// may as well make it something else
void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool* sampleDir, bool isSecond, int* pendingFreq, int* playingSample, int* setPos, unsigned int* sampleOff8, unsigned int* sampleLen8, size_t bankOffset, bool directStream, bool* sampleStoppable) {
unsigned char baseAddr1=isSecond?0xa0:0x50; unsigned char baseAddr1=isSecond?0xa0:0x50;
unsigned char baseAddr2=isSecond?0x80:0; unsigned char baseAddr2=isSecond?0x80:0;
unsigned short baseAddr2S=isSecond?0x8000:0; unsigned short baseAddr2S=isSecond?0x8000:0;
@ -647,6 +649,7 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
logD("writing stream command %x:%x with stream ID %d",write.addr,write.val,streamID); logD("writing stream command %x:%x with stream ID %d",write.addr,write.val,streamID);
switch (write.addr&0xff) { switch (write.addr&0xff) {
case 0: // play sample case 0: // play sample
sampleStoppable[streamID]=true;
if (write.val<(unsigned int)song.sampleLen) { if (write.val<(unsigned int)song.sampleLen) {
if (playingSample[streamID]!=(int)write.val) { if (playingSample[streamID]!=(int)write.val) {
pendingFreq[streamID]=write.val; pendingFreq[streamID]=write.val;
@ -685,6 +688,7 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
} }
break; break;
case 1: { // set sample freq case 1: { // set sample freq
sampleStoppable[streamID]=true;
int realFreq=write.val; int realFreq=write.val;
if (realFreq<0) realFreq=0; if (realFreq<0) realFreq=0;
if (realFreq>44100) realFreq=44100; if (realFreq>44100) realFreq=44100;
@ -728,11 +732,14 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
break; break;
} }
case 2: // stop sample case 2: // stop sample
if (sampleStoppable[streamID]) {
w->writeC(0x94); w->writeC(0x94);
w->writeC(streamID); w->writeC(streamID);
loopSample[streamID]=-1; loopSample[streamID]=-1;
playingSample[streamID]=-1; playingSample[streamID]=-1;
pendingFreq[streamID]=-1; pendingFreq[streamID]=-1;
sampleStoppable[streamID]=false;
}
break; break;
case 3: // set sample direction case 3: // set sample direction
sampleDir[streamID]=write.val; sampleDir[streamID]=write.val;
@ -1224,6 +1231,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
bool sampleDir[DIV_MAX_CHANS]; bool sampleDir[DIV_MAX_CHANS];
int pendingFreq[DIV_MAX_CHANS]; int pendingFreq[DIV_MAX_CHANS];
int playingSample[DIV_MAX_CHANS]; int playingSample[DIV_MAX_CHANS];
bool sampleStoppable[DIV_MAX_CHANS];
int setPos[DIV_MAX_CHANS]; int setPos[DIV_MAX_CHANS];
std::vector<unsigned int> chipVol; std::vector<unsigned int> chipVol;
std::vector<DivDelayedWrite> delayedWrites[DIV_MAX_CHIPS]; std::vector<DivDelayedWrite> delayedWrites[DIV_MAX_CHIPS];
@ -1246,6 +1254,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
playingSample[i]=-1; playingSample[i]=-1;
setPos[i]=0; setPos[i]=0;
sampleDir[i]=false; sampleDir[i]=false;
sampleStoppable[i]=true;
} }
bool writeDACSamples=false; bool writeDACSamples=false;
@ -2514,7 +2523,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
for (int i=0; i<song.systemLen; i++) { for (int i=0; i<song.systemLen; i++) {
std::vector<DivRegWrite>& writes=disCont[i].dispatch->getRegisterWrites(); std::vector<DivRegWrite>& writes=disCont[i].dispatch->getRegisterWrites();
for (DivRegWrite& j: writes) { for (DivRegWrite& j: writes) {
performVGMWrite(w,song.system[i],j,streamIDs[i],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i],pendingFreq,playingSample,setPos,sampleOff8,sampleLen8,bankOffset[i],directStream); performVGMWrite(w,song.system[i],j,streamIDs[i],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i],pendingFreq,playingSample,setPos,sampleOff8,sampleLen8,bankOffset[i],directStream,sampleStoppable);
writeCount++; writeCount++;
} }
writes.clear(); writes.clear();
@ -2554,7 +2563,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
lastOne=i.second.time; lastOne=i.second.time;
} }
// write write // write write
performVGMWrite(w,song.system[i.first],i.second.write,streamIDs[i.first],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i.first],pendingFreq,playingSample,setPos,sampleOff8,sampleLen8,bankOffset[i.first],directStream); performVGMWrite(w,song.system[i.first],i.second.write,streamIDs[i.first],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i.first],pendingFreq,playingSample,setPos,sampleOff8,sampleLen8,bankOffset[i.first],directStream,sampleStoppable);
// handle global Furnace commands // handle global Furnace commands
writeCount++; writeCount++;

View file

@ -1969,6 +1969,8 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl
echoFilter[6]=flags.getInt("echoFilter6",0); echoFilter[6]=flags.getInt("echoFilter6",0);
echoFilter[7]=flags.getInt("echoFilter7",0); echoFilter[7]=flags.getInt("echoFilter7",0);
bool interpolationOff=flags.getBool("interpolationOff",false);
ImGui::Text(_("Volume scale:")); ImGui::Text(_("Volume scale:"));
if (CWSliderInt(_("Left##VolScaleL"),&vsL,0,127)) { if (CWSliderInt(_("Left##VolScaleL"),&vsL,0,127)) {
if (vsL<0) vsL=0; if (vsL<0) vsL=0;
@ -2084,6 +2086,10 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl
ImGui::Text(_("sum: %d"),filterSum); ImGui::Text(_("sum: %d"),filterSum);
ImGui::PopStyleColor(); ImGui::PopStyleColor();
if (ImGui::Checkbox(_("Disable Gaussian interpolation"),&interpolationOff)) {
altered=true;
}
if (altered) { if (altered) {
e->lockSave([&]() { e->lockSave([&]() {
flags.set("volScaleL",127-vsL); flags.set("volScaleL",127-vsL);
@ -2102,6 +2108,7 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl
flags.set("echoFilter6",echoFilter[6]); flags.set("echoFilter6",echoFilter[6]);
flags.set("echoFilter7",echoFilter[7]); flags.set("echoFilter7",echoFilter[7]);
flags.set("echoMask",echoMask); flags.set("echoMask",echoMask);
flags.set("interpolationOff",interpolationOff);
}); });
} }