diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 9837102e7..843a78d8d 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -917,6 +917,11 @@ class DivDispatch { */ virtual void notifyWaveChange(int wave); + /** + * notify sample change. + */ + virtual void notifySampleChange(int sample); + /** * notify addition of an instrument. */ diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 8735f1b81..3dd9d85c1 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -283,6 +283,14 @@ void DivEngine::notifyWaveChange(int wave) { BUSY_END; } +void DivEngine::notifySampleChange(int sample) { + BUSY_BEGIN; + for (int i=0; inotifySampleChange(sample); + } + BUSY_END; +} + int DivEngine::loadSampleROM(String path, ssize_t expectedSize, unsigned char*& ret) { ret=NULL; if (path.empty()) { @@ -595,10 +603,41 @@ void DivEngine::createNewFromDefaults() { BUSY_END; } +void DivEngine::copyChannel(int src, int dest) { + logV("copying channel %d to %d",src,dest); + if (src==dest) { + logV("not copying because it's the same channel!"); + return; + } + + for (int i=0; iord[dest][i]=curOrders->ord[src][i]; + + DivPattern* srcPat=curPat[src].data[i]; + DivPattern* destPat=curPat[dest].data[i]; + if (srcPat==NULL) { + if (destPat!=NULL) { + delete destPat; + curPat[dest].data[i]=NULL; + } + } else { + curPat[src].data[i]->copyOn(curPat[dest].getPattern(i, true)); + } + } + + curPat[dest].effectCols=curPat[src].effectCols; + + curSubSong->chanName[dest]=curSubSong->chanName[src]; + curSubSong->chanShortName[dest]=curSubSong->chanShortName[src]; + curSubSong->chanShow[dest]=curSubSong->chanShow[src]; + curSubSong->chanShowChanOsc[dest]=curSubSong->chanShowChanOsc[src]; + curSubSong->chanCollapse[dest]=curSubSong->chanCollapse[src]; +} + void DivEngine::swapChannels(int src, int dest) { logV("swapping channel %d with %d",src,dest); if (src==dest) { - logV("not swapping channels because it's the same channel!",src,dest); + logV("not swapping channels because it's the same channel!"); return; } @@ -738,6 +777,16 @@ void DivEngine::checkAssetDir(std::vector& dir, size_t entries) { delete[] inAssetDir; } +void DivEngine::copyChannelP(int src, int dest) { + if (src<0 || src>=chans) return; + if (dest<0 || dest>=chans) return; + BUSY_BEGIN; + saveLock.lock(); + copyChannel(src,dest); + saveLock.unlock(); + BUSY_END; +} + void DivEngine::swapChannelsP(int src, int dest) { if (src<0 || src>=chans) return; if (dest<0 || dest>=chans) return; diff --git a/src/engine/engine.h b/src/engine/engine.h index 2c7c2ccb7..a0e181c5d 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -649,6 +649,7 @@ class DivEngine { void exchangeWave(int one, int two); void exchangeSample(int one, int two); + void copyChannel(int src, int dest); void swapChannels(int src, int dest); void stompChannel(int ch); @@ -748,6 +749,8 @@ class DivEngine { void notifyInsChange(int ins); // notify wavetable change void notifyWaveChange(int wave); + // notify sample change + void notifySampleChange(int sample); // dispatch a command int dispatchCmd(DivCommand c); @@ -1260,6 +1263,9 @@ class DivEngine { // >=0: render specific sample void renderSamplesP(int whichSample=-1); + // public copy channel + void copyChannelP(int src, int dest); + // public swap channels void swapChannelsP(int src, int dest); diff --git a/src/engine/fileOpsSample.cpp b/src/engine/fileOpsSample.cpp index 8c89d451d..f522160ff 100644 --- a/src/engine/fileOpsSample.cpp +++ b/src/engine/fileOpsSample.cpp @@ -402,13 +402,12 @@ std::vector DivEngine::sampleFromFile(const char* path) { { // There's no documentation on libsndfile detune range, but the code // implies -50..50. Yet when loading a file you can get a >50 value. - // disabled for now - /* - if(inst.detune > 50) - inst.detune = inst.detune - 100; - short pitch = ((0x3c-inst.basenote)*100) + inst.detune; - sample->centerRate=si.samplerate*pow(2.0,pitch/(12.0 * 100.0)); - */ + if (getConfInt("sampleImportInstDetune", 0)) { + if(inst.detune > 50) + inst.detune = inst.detune - 100; + short pitch = ((0x3c-inst.basenote)*100) + inst.detune; + sample->centerRate=si.samplerate*pow(2.0,pitch/(12.0 * 100.0)); + } if(inst.loop_count && inst.loops[0].mode >= SF_LOOP_FORWARD) { sample->loop=true; diff --git a/src/engine/platform/abstract.cpp b/src/engine/platform/abstract.cpp index b51cf5966..bb3b40030 100644 --- a/src/engine/platform/abstract.cpp +++ b/src/engine/platform/abstract.cpp @@ -160,7 +160,11 @@ void DivDispatch::notifyInsChange(int ins) { } -void DivDispatch::notifyWaveChange(int ins) { +void DivDispatch::notifyWaveChange(int wave) { + +} + +void DivDispatch::notifySampleChange(int sample) { } diff --git a/src/engine/platform/multipcm.cpp b/src/engine/platform/multipcm.cpp index 1f03199b5..7e1a0ce29 100644 --- a/src/engine/platform/multipcm.cpp +++ b/src/engine/platform/multipcm.cpp @@ -516,6 +516,10 @@ void DivPlatformMultiPCM::notifyInsChange(int ins) { } } +void DivPlatformMultiPCM::notifySampleChange(int sample) { + renderInstruments(); +} + void DivPlatformMultiPCM::notifyInsAddition(int sysID) { renderInstruments(); } @@ -654,8 +658,6 @@ void DivPlatformMultiPCM::renderSamples(int sysID) { memCompo=DivMemoryComposition(); memCompo.name="Sample Memory"; - renderInstruments(); - size_t memPos=0x1800; int sampleCount=parent->song.sampleLen; if (sampleCount>512) { @@ -709,6 +711,7 @@ void DivPlatformMultiPCM::renderSamples(int sysID) { pcmMemLen=memPos+256; memCompo.used=pcmMemLen; } + renderInstruments(); memCompo.capacity=getSampleMemCapacity(0); } diff --git a/src/engine/platform/multipcm.h b/src/engine/platform/multipcm.h index f03c3cefe..36fab35bd 100644 --- a/src/engine/platform/multipcm.h +++ b/src/engine/platform/multipcm.h @@ -120,6 +120,7 @@ class DivPlatformMultiPCM: public DivDispatch { void toggleRegisterDump(bool enable); void setFlags(const DivConfig& flags); void notifyInsChange(int ins); + void notifySampleChange(int sample); void notifyInsAddition(int sysID); void notifyInsDeletion(void* ins); int getPortaFloor(int ch); diff --git a/src/engine/platform/opl.cpp b/src/engine/platform/opl.cpp index f16ad7c2d..1d2c95257 100644 --- a/src/engine/platform/opl.cpp +++ b/src/engine/platform/opl.cpp @@ -2993,6 +2993,12 @@ void DivPlatformOPL::notifyInsChange(int ins) { } } +void DivPlatformOPL::notifySampleChange(int sample) { + if (pcmChanOffs>=0) { + renderInstruments(); + } +} + void DivPlatformOPL::notifyInsDeletion(void* ins) { for (int i=0; i=0) { + const int maxSample=PCM_IN_RAM?128:512; + int sampleCount=parent->song.sampleLen; + if (sampleCount>maxSample) { + sampleCount=maxSample; + } + // instrument table + for (int i=0; isong.sample[i]; + unsigned int insAddr=(i*12)+(PCM_IN_RAM?0x200000:0); + unsigned char bitDepth; + int endPos=CLAMP(s->isLoopable()?s->loopEnd:(s->samples+1),1,0x10000); + int loop=s->isLoopable()?CLAMP(s->loopStart,0,endPos-2):(endPos-2); + switch (s->depth) { + case DIV_SAMPLE_DEPTH_8BIT: + bitDepth=0; + break; + case DIV_SAMPLE_DEPTH_12BIT: + bitDepth=1; + if (!s->isLoopable()) { + endPos++; + loop++; + } + break; + case DIV_SAMPLE_DEPTH_16BIT: + bitDepth=2; + break; + default: + bitDepth=0; + break; + } + pcmMem[insAddr]=(bitDepth<<6)|((sampleOffPCM[i]>>16)&0x3f); + pcmMem[1+insAddr]=(sampleOffPCM[i]>>8)&0xff; + pcmMem[2+insAddr]=(sampleOffPCM[i])&0xff; + pcmMem[3+insAddr]=(loop>>8)&0xff; + pcmMem[4+insAddr]=(loop)&0xff; + pcmMem[5+insAddr]=((~(endPos-1))>>8)&0xff; + pcmMem[6+insAddr]=(~(endPos-1))&0xff; + // on MultiPCM this consists of instrument params, but on OPL4 this is not used + pcmMem[7+insAddr]=0; // LFO, VIB + pcmMem[8+insAddr]=(0xf<<4)|(0xf<<0); // AR, D1R + pcmMem[9+insAddr]=0; // DL, D2R + pcmMem[10+insAddr]=(0xf<<4)|(0xf<<0); // RC, RR + pcmMem[11+insAddr]=0; // AM + } + } +} + void DivPlatformOPL::renderSamples(int sysID) { if (adpcmChan<0 && pcmChanOffs<0) return; if (adpcmChan>=0 && adpcmBMem!=NULL) { @@ -3349,45 +3407,7 @@ void DivPlatformOPL::renderSamples(int sysID) { } pcmMemLen=memPos+256; - // instrument table - for (int i=0; isong.sample[i]; - unsigned int insAddr=(i*12)+(PCM_IN_RAM?0x200000:0); - unsigned char bitDepth; - int endPos=CLAMP(s->isLoopable()?s->loopEnd:(s->samples+1),1,0x10000); - int loop=s->isLoopable()?CLAMP(s->loopStart,0,endPos-2):(endPos-2); - switch (s->depth) { - case DIV_SAMPLE_DEPTH_8BIT: - bitDepth=0; - break; - case DIV_SAMPLE_DEPTH_12BIT: - bitDepth=1; - if (!s->isLoopable()) { - endPos++; - loop++; - } - break; - case DIV_SAMPLE_DEPTH_16BIT: - bitDepth=2; - break; - default: - bitDepth=0; - break; - } - pcmMem[insAddr]=(bitDepth<<6)|((sampleOffPCM[i]>>16)&0x3f); - pcmMem[1+insAddr]=(sampleOffPCM[i]>>8)&0xff; - pcmMem[2+insAddr]=(sampleOffPCM[i])&0xff; - pcmMem[3+insAddr]=(loop>>8)&0xff; - pcmMem[4+insAddr]=(loop)&0xff; - pcmMem[5+insAddr]=((~(endPos-1))>>8)&0xff; - pcmMem[6+insAddr]=(~(endPos-1))&0xff; - // on MultiPCM this consists of instrument params, but on OPL4 this is not used - pcmMem[7+insAddr]=0; // LFO, VIB - pcmMem[8+insAddr]=(0xf<<4)|(0xf<<0); // AR, D1R - pcmMem[9+insAddr]=0; // DL, D2R - pcmMem[10+insAddr]=(0xf<<4)|(0xf<<0); // RC, RR - pcmMem[11+insAddr]=0; // AM - } + renderInstruments(); if (PCM_IN_RAM) { memCompo.entries.push_back(DivMemoryEntry(DIV_MEMORY_RESERVED,"ROM data",0,0,0x200000)); } diff --git a/src/engine/platform/opl.h b/src/engine/platform/opl.h index 7d456a6e2..9ba5dd3fe 100644 --- a/src/engine/platform/opl.h +++ b/src/engine/platform/opl.h @@ -186,6 +186,8 @@ class DivPlatformOPL: public DivDispatch { void acquire_ymfm2(short** buf, size_t len); void acquire_ymfm1(short** buf, size_t len); + void renderInstruments(); + public: void acquire(short** buf, size_t len); int dispatch(DivCommand c); @@ -211,6 +213,7 @@ class DivPlatformOPL: public DivDispatch { void toggleRegisterDump(bool enable); void setFlags(const DivConfig& flags); void notifyInsChange(int ins); + void notifySampleChange(int sample); void notifyInsDeletion(void* ins); int getPortaFloor(int ch); void poke(unsigned int addr, unsigned short val); diff --git a/src/gui/channels.cpp b/src/gui/channels.cpp index 6ac636a03..2e8c4d276 100644 --- a/src/gui/channels.cpp +++ b/src/gui/channels.cpp @@ -50,7 +50,7 @@ void FurnaceGUI::drawChannels() { ImGui::TableNextColumn(); ImGui::Text(_("Osc")); ImGui::TableNextColumn(); - ImGui::Text(_("Swap")); + ImGui::Text("%s", ""); ImGui::TableNextColumn(); ImGui::Text(_("Name")); for (int i=0; igetTotalChannelCount(); i++) { @@ -79,14 +79,17 @@ void FurnaceGUI::drawChannels() { ImGui::Button(ICON_FA_ARROWS "##ChanDrag"); ImGui::EndDragDropSource(); } else if (ImGui::IsItemHovered()) { - ImGui::SetTooltip(_("%s #%d\n(drag to swap channels)"),e->getSystemName(e->sysOfChan[i]),e->dispatchChanOfChan[i]); + ImGui::SetTooltip(_("%s #%d\n(drag to swap channels)\n(shift+drag to copy channel contents)"),e->getSystemName(e->sysOfChan[i]),e->dispatchChanOfChan[i]); } if (ImGui::BeginDragDropTarget()) { const ImGuiPayload* dragItem=ImGui::AcceptDragDropPayload("FUR_CHAN"); if (dragItem!=NULL) { if (dragItem->IsDataType("FUR_CHAN")) { if (chanToMove!=i && chanToMove>=0) { - e->swapChannelsP(chanToMove,i); + if (ImGui::IsKeyDown(ImGuiKey_LeftShift)) + e->copyChannelP(chanToMove,i); + else + e->swapChannelsP(chanToMove,i); MARK_MODIFIED; } chanToMove=-1; diff --git a/src/gui/dataList.cpp b/src/gui/dataList.cpp index 400fd6e6c..f8a38f1d6 100644 --- a/src/gui/dataList.cpp +++ b/src/gui/dataList.cpp @@ -279,6 +279,7 @@ void FurnaceGUI::sampleListItem(int i, int dir, int asset) { curSample=i; samplePos=0; updateSampleTex=true; + notifySampleChange=true; lastAssetType=2; } if (ImGui::IsItemHovered() && !mobileUI) { @@ -309,6 +310,7 @@ void FurnaceGUI::sampleListItem(int i, int dir, int asset) { curSample=i; samplePos=0; updateSampleTex=true; + notifySampleChange=true; lastAssetType=2; ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_TEXT]); if (ImGui::MenuItem(_("edit"))) { diff --git a/src/gui/doAction.cpp b/src/gui/doAction.cpp index 3ef117ed0..a9326016b 100644 --- a/src/gui/doAction.cpp +++ b/src/gui/doAction.cpp @@ -946,6 +946,7 @@ void FurnaceGUI::doAction(int what) { MARK_MODIFIED; } updateSampleTex=true; + notifySampleChange=true; } break; case GUI_ACTION_WAVE_LIST_MOVE_UP: @@ -1003,6 +1004,7 @@ void FurnaceGUI::doAction(int what) { MARK_MODIFIED; } updateSampleTex=true; + notifySampleChange=true; break; case GUI_ACTION_SAMPLE_LIST_DUPLICATE: if (curSample>=0 && curSample<(int)e->song.sample.size()) { @@ -1037,6 +1039,7 @@ void FurnaceGUI::doAction(int what) { MARK_MODIFIED; } updateSampleTex=true; + notifySampleChange=true; } break; case GUI_ACTION_SAMPLE_LIST_OPEN: @@ -1062,6 +1065,7 @@ void FurnaceGUI::doAction(int what) { curSample--; wantScrollListSample=true; updateSampleTex=true; + notifySampleChange=true; MARK_MODIFIED; } break; @@ -1070,6 +1074,7 @@ void FurnaceGUI::doAction(int what) { curSample++; wantScrollListSample=true; updateSampleTex=true; + notifySampleChange=true; MARK_MODIFIED; } break; @@ -1081,6 +1086,7 @@ void FurnaceGUI::doAction(int what) { curSample--; } updateSampleTex=true; + notifySampleChange=true; break; case GUI_ACTION_SAMPLE_LIST_EDIT: sampleEditOpen=true; @@ -1089,11 +1095,13 @@ void FurnaceGUI::doAction(int what) { if (--curSample<0) curSample=0; wantScrollListSample=true; updateSampleTex=true; + notifySampleChange=true; break; case GUI_ACTION_SAMPLE_LIST_DOWN: if (++curSample>=(int)e->song.sample.size()) curSample=((int)e->song.sample.size())-1; wantScrollListSample=true; updateSampleTex=true; + notifySampleChange=true; break; case GUI_ACTION_SAMPLE_LIST_PREVIEW: e->previewSample(curSample); @@ -1183,6 +1191,7 @@ void FurnaceGUI::doAction(int what) { e->lockEngine([this,sample,start,end]() { sample->strip(start,end); updateSampleTex=true; + notifySampleChange=true; e->renderSamples(curSample); }); @@ -1235,6 +1244,7 @@ void FurnaceGUI::doAction(int what) { sampleSelStart=pos; sampleSelEnd=pos+sampleClipboardLen; updateSampleTex=true; + notifySampleChange=true; MARK_MODIFIED; break; } @@ -1266,6 +1276,7 @@ void FurnaceGUI::doAction(int what) { sampleSelEnd=pos+sampleClipboardLen; if (sampleSelEnd>(int)sample->samples) sampleSelEnd=sample->samples; updateSampleTex=true; + notifySampleChange=true; MARK_MODIFIED; break; } @@ -1303,6 +1314,7 @@ void FurnaceGUI::doAction(int what) { sampleSelEnd=pos+sampleClipboardLen; if (sampleSelEnd>(int)sample->samples) sampleSelEnd=sample->samples; updateSampleTex=true; + notifySampleChange=true; MARK_MODIFIED; break; } @@ -1368,6 +1380,7 @@ void FurnaceGUI::doAction(int what) { } updateSampleTex=true; + notifySampleChange=true; e->renderSamples(curSample); }); @@ -1399,6 +1412,7 @@ void FurnaceGUI::doAction(int what) { } updateSampleTex=true; + notifySampleChange=true; e->renderSamples(curSample); }); @@ -1430,6 +1444,7 @@ void FurnaceGUI::doAction(int what) { } updateSampleTex=true; + notifySampleChange=true; e->renderSamples(curSample); }); @@ -1459,6 +1474,7 @@ void FurnaceGUI::doAction(int what) { } updateSampleTex=true; + notifySampleChange=true; e->renderSamples(curSample); }); @@ -1475,6 +1491,7 @@ void FurnaceGUI::doAction(int what) { sample->strip(start,end); updateSampleTex=true; + notifySampleChange=true; e->renderSamples(curSample); }); @@ -1493,6 +1510,7 @@ void FurnaceGUI::doAction(int what) { sample->trim(start,end); updateSampleTex=true; + notifySampleChange=true; e->renderSamples(curSample); }); @@ -1528,6 +1546,7 @@ void FurnaceGUI::doAction(int what) { } updateSampleTex=true; + notifySampleChange=true; e->renderSamples(curSample); }); @@ -1555,6 +1574,7 @@ void FurnaceGUI::doAction(int what) { } updateSampleTex=true; + notifySampleChange=true; e->renderSamples(curSample); }); @@ -1580,6 +1600,7 @@ void FurnaceGUI::doAction(int what) { } updateSampleTex=true; + notifySampleChange=true; e->renderSamples(curSample); }); @@ -1713,6 +1734,7 @@ void FurnaceGUI::doAction(int what) { sample->loopEnd=end; sample->loop=true; updateSampleTex=true; + notifySampleChange=true; e->renderSamples(curSample); }); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 6fb2ac6dc..64de23ef3 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -2914,6 +2914,7 @@ void FurnaceGUI::processDrags(int dragX, int dragY) { for (int i=x; i<=x1; i++) ((signed char*)sampleDragTarget)[i]=val; } updateSampleTex=true; + notifySampleChange=true; } } else { // select if (sampleSelStart<0) { @@ -4020,26 +4021,22 @@ bool FurnaceGUI::loop() { } nextWindow=GUI_WINDOW_WAVE_LIST; MARK_MODIFIED; - } - else if (!samples.empty()) - { + } else if (!samples.empty()) { if (e->song.sampleLen!=sampleCountBefore) { //e->renderSamplesP(); } - if (!e->getWarnings().empty()) - { + if (!e->getWarnings().empty()) { showWarning(e->getWarnings(),GUI_WARN_GENERIC); } int sampleCount=-1; - for (DivSample* s: samples) - { + for (DivSample* s: samples) { sampleCount=e->addSamplePtr(s); } //sampleCount=e->addSamplePtr(droppedSample); - if (sampleCount>=0 && settings.selectAssetOnLoad) - { + if (sampleCount>=0 && settings.selectAssetOnLoad) { curSample=sampleCount; updateSampleTex=true; + notifySampleChange=true; } nextWindow=GUI_WINDOW_SAMPLE_LIST; MARK_MODIFIED; @@ -4278,6 +4275,11 @@ bool FurnaceGUI::loop() { e->notifyWaveChange(curWave); } + if (notifySampleChange) { + notifySampleChange=false; + e->notifySampleChange(curSample); + } + eventTimeEnd=SDL_GetPerformanceCounter(); if (SDL_GetWindowFlags(sdlWin)&SDL_WINDOW_MINIMIZED) { @@ -5526,6 +5528,7 @@ bool FurnaceGUI::loop() { MARK_MODIFIED; }); updateSampleTex=true; + notifySampleChange=true; } else { showError(_("...but you haven't selected a sample!")); delete samples[0]; @@ -7149,6 +7152,7 @@ bool FurnaceGUI::loop() { MARK_MODIFIED; }); updateSampleTex=true; + notifySampleChange=true; } else { showError(_("...but you haven't selected a sample!")); delete s; @@ -8521,6 +8525,7 @@ FurnaceGUI::FurnaceGUI(): sysDupEnd(false), noteInputPoly(true), notifyWaveChange(false), + notifySampleChange(false), wantScrollListIns(false), wantScrollListWave(false), wantScrollListSample(false), diff --git a/src/gui/gui.h b/src/gui/gui.h index bedd40f39..3041f310f 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1708,7 +1708,7 @@ class FurnaceGUI { bool vgmExportDirectStream, displayInsTypeList, displayWaveSizeList; bool portrait, injectBackUp, mobileMenuOpen, warnColorPushed; bool wantCaptureKeyboard, oldWantCaptureKeyboard, displayMacroMenu; - bool displayNew, displayExport, displayPalette, fullScreen, preserveChanPos, sysDupCloneChannels, sysDupEnd, noteInputPoly, notifyWaveChange; + bool displayNew, displayExport, displayPalette, fullScreen, preserveChanPos, sysDupCloneChannels, sysDupEnd, noteInputPoly, notifyWaveChange, notifySampleChange; bool wantScrollListIns, wantScrollListWave, wantScrollListSample; bool displayPendingIns, pendingInsSingle, displayPendingRawSample, snesFilterHex, modTableHex, displayEditString; bool displayPendingSamples, replacePendingSample; @@ -2060,6 +2060,7 @@ class FurnaceGUI { int s3mOPL3; int songNotesWrap; int rackShowLEDs; + int sampleImportInstDetune; String mainFontPath; String headFontPath; String patFontPath; @@ -2313,6 +2314,7 @@ class FurnaceGUI { s3mOPL3(1), songNotesWrap(0), rackShowLEDs(1), + sampleImportInstDetune(0), mainFontPath(""), headFontPath(""), patFontPath(""), diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 6efdc8892..510b9011d 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -3465,6 +3465,7 @@ void FurnaceGUI::insTabSample(DivInstrument* ins) { if (ImGui::InputInt(_("Sample bank slot##BANKSLOT"),&ins->x1_010.bankSlot,1,4)) { PARAMETER if (ins->x1_010.bankSlot<0) ins->x1_010.bankSlot=0; if (ins->x1_010.bankSlot>=7) ins->x1_010.bankSlot=7; + notifySampleChange=true; } } } @@ -3478,6 +3479,7 @@ void FurnaceGUI::insTabSample(DivInstrument* ins) { id=fmt::sprintf("%d: %s",i,e->song.sample[i]->name); if (ImGui::Selectable(id.c_str(),ins->amiga.initSample==i)) { PARAMETER ins->amiga.initSample=i; + notifySampleChange=true; } } ImGui::EndCombo(); diff --git a/src/gui/newSong.cpp b/src/gui/newSong.cpp index 7034f8a01..bb92c81d1 100644 --- a/src/gui/newSong.cpp +++ b/src/gui/newSong.cpp @@ -289,6 +289,7 @@ void FurnaceGUI::drawNewSong() { orderCursor=-1; samplePos=0; updateSampleTex=true; + notifySampleChange=true; selStart=SelectionPoint(); selEnd=SelectionPoint(); cursor=SelectionPoint(); diff --git a/src/gui/presets.cpp b/src/gui/presets.cpp index 972d77e9c..c8d8ca449 100644 --- a/src/gui/presets.cpp +++ b/src/gui/presets.cpp @@ -328,7 +328,8 @@ void FurnaceGUI::initSystemPresets() { ENTRY( "Watara Supervision", { CH(DIV_SYSTEM_SUPERVISION, 1.0f, 0, "") - } + }, + "tickRate=50.81300813008130081301" ); CATEGORY_END; diff --git a/src/gui/sampleEdit.cpp b/src/gui/sampleEdit.cpp index 4e4c11dec..4415130d9 100644 --- a/src/gui/sampleEdit.cpp +++ b/src/gui/sampleEdit.cpp @@ -293,10 +293,11 @@ void FurnaceGUI::drawSampleEdit() { String alignHint=fmt::sprintf(_("NES: loop start must be a multiple of 512 (try with %d)"),tryWith); SAMPLE_WARN(warnLoopStart,alignHint); } - if ((sample->loopEnd>0) && ((sample->loopEnd-8)&127)) { + if ((sample->loopEnd-8)&127) { int tryWith=(sample->loopEnd-8)&(~127); if (tryWith>(int)sample->samples) tryWith-=128; tryWith+=8; // +1 bc of how sample length is treated: https://www.nesdev.org/wiki/APU_DMC + if (tryWith<8) tryWith=8; String alignHint=fmt::sprintf(_("NES: loop end must be a multiple of 128 + 8 (try with %d)"),tryWith); SAMPLE_WARN(warnLoopEnd,alignHint); } @@ -655,6 +656,7 @@ void FurnaceGUI::drawSampleEdit() { sample->loopEnd=sample->samples;*/ } updateSampleTex=true; + notifySampleChange=true; REFRESH_SAMPLE } popWarningColor(); @@ -687,6 +689,7 @@ void FurnaceGUI::drawSampleEdit() { e->renderSamples(curSample); }); updateSampleTex=true; + notifySampleChange=true; MARK_MODIFIED; } } @@ -707,6 +710,7 @@ void FurnaceGUI::drawSampleEdit() { sample->brrEmphasis=be; e->renderSamplesP(curSample); updateSampleTex=true; + notifySampleChange=true; MARK_MODIFIED; } if (ImGui::IsItemHovered()) { @@ -724,6 +728,7 @@ void FurnaceGUI::drawSampleEdit() { sample->brrNoFilter=bf; e->renderSamplesP(curSample); updateSampleTex=true; + notifySampleChange=true; MARK_MODIFIED; } if (ImGui::IsItemHovered()) { @@ -737,6 +742,7 @@ void FurnaceGUI::drawSampleEdit() { sample->dither=di; e->renderSamplesP(curSample); updateSampleTex=true; + notifySampleChange=true; MARK_MODIFIED; } if (ImGui::IsItemHovered()) { @@ -869,6 +875,7 @@ void FurnaceGUI::drawSampleEdit() { sample->loopMode=(DivSampleLoopMode)i; e->renderSamplesP(curSample); updateSampleTex=true; + notifySampleChange=true; MARK_MODIFIED; } } @@ -892,6 +899,7 @@ void FurnaceGUI::drawSampleEdit() { sample->loopStart=sample->loopEnd; } updateSampleTex=true; + notifySampleChange=true; REFRESH_SAMPLE } if (ImGui::IsItemActive()) { @@ -933,6 +941,7 @@ void FurnaceGUI::drawSampleEdit() { sample->loopEnd=sample->samples; } updateSampleTex=true; + notifySampleChange=true; REFRESH_SAMPLE } if (ImGui::IsItemActive()) { @@ -1107,6 +1116,7 @@ void FurnaceGUI::drawSampleEdit() { e->renderSamples(curSample); }); updateSampleTex=true; + notifySampleChange=true; sampleSelStart=-1; sampleSelEnd=-1; MARK_MODIFIED; @@ -1171,6 +1181,7 @@ void FurnaceGUI::drawSampleEdit() { e->renderSamples(curSample); }); updateSampleTex=true; + notifySampleChange=true; sampleSelStart=-1; sampleSelEnd=-1; MARK_MODIFIED; @@ -1238,6 +1249,7 @@ void FurnaceGUI::drawSampleEdit() { } updateSampleTex=true; + notifySampleChange=true; e->renderSamples(curSample); }); @@ -1291,6 +1303,7 @@ void FurnaceGUI::drawSampleEdit() { e->renderSamples(curSample); }); updateSampleTex=true; + notifySampleChange=true; sampleSelStart=pos; sampleSelEnd=pos+silenceSize; MARK_MODIFIED; @@ -1466,6 +1479,7 @@ void FurnaceGUI::drawSampleEdit() { } updateSampleTex=true; + notifySampleChange=true; e->renderSamples(curSample); }); @@ -1545,6 +1559,7 @@ void FurnaceGUI::drawSampleEdit() { } } updateSampleTex=true; + notifySampleChange=true; e->renderSamples(curSample); }); @@ -2507,6 +2522,7 @@ void FurnaceGUI::doUndoSample() { if (sample->undo()==2) { e->renderSamples(curSample); updateSampleTex=true; + notifySampleChange=true; } }); } @@ -2519,6 +2535,7 @@ void FurnaceGUI::doRedoSample() { if (sample->redo()==2) { e->renderSamples(curSample); updateSampleTex=true; + notifySampleChange=true; } }); } diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index 33ec73dd1..908f17d51 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -1161,9 +1161,10 @@ void FurnaceGUI::drawSettings() { settings.newSongBehavior=1; settingsChanged=true; } - if (ImGui::InputText(_("Default author name"), &settings.defaultAuthorName)) settingsChanged=true; ImGui::Unindent(); + if (ImGui::InputText(_("Default author name"), &settings.defaultAuthorName)) settingsChanged=true; + // SUBSECTION START-UP CONFIG_SUBSECTION(_("Start-up")); #ifndef NO_INTRO @@ -1229,6 +1230,14 @@ void FurnaceGUI::drawSettings() { settings.s3mOPL3=s3mOPL3B; settingsChanged=true; } + bool sampleImportInstDetuneB=settings.sampleImportInstDetune; + if (ImGui::Checkbox(_("Load sample fine tuning when importing a sample"), &sampleImportInstDetuneB)) { + settings.sampleImportInstDetune=sampleImportInstDetuneB; + settingsChanged=true; + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip(_("this may result in glitches with some samples.")); + } #ifdef ANDROID // SUBSECTION ANDROID @@ -3843,7 +3852,7 @@ void FurnaceGUI::drawSettings() { settingsChanged=true; } - // SUBSECTION SONG COMMENTS + // SUBSECTION CHIP MANAGER CONFIG_SUBSECTION(_("Chip Manager")); bool rackShowLEDsB=settings.rackShowLEDs; if (ImGui::Checkbox(_("Show channel indicators"), &rackShowLEDsB)) { @@ -4880,6 +4889,7 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { settings.vibrationLength=conf.getInt("vibrationLength",20); settings.s3mOPL3=conf.getInt("s3mOPL3",1); + settings.sampleImportInstDetune=conf.getInt("sampleImportInstDetune",0); settings.backupEnable=conf.getInt("backupEnable",1); settings.backupInterval=conf.getInt("backupInterval",30); @@ -5395,6 +5405,7 @@ void FurnaceGUI::readConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { clampSetting(settings.autoFillSave,0,1); clampSetting(settings.autoMacroStepSize,0,2); clampSetting(settings.s3mOPL3,0,1); + clampSetting(settings.sampleImportInstDetune,0,1); clampSetting(settings.backgroundPlay,0,1); clampSetting(settings.noMaximizeWorkaround,0,1); @@ -5477,6 +5488,7 @@ void FurnaceGUI::writeConfig(DivConfig& conf, FurnaceGUISettingGroups groups) { conf.set("vibrationLength",settings.vibrationLength); conf.set("s3mOPL3",settings.s3mOPL3); + conf.set("sampleImportInstDetune",settings.sampleImportInstDetune); conf.set("backupEnable",settings.backupEnable); conf.set("backupInterval",settings.backupInterval);