From 7ebc63a5144547498c69201cca8b55a432b06865 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 22 Mar 2022 17:01:06 -0500 Subject: [PATCH] GUI: implement sample paste --- src/engine/sample.cpp | 8 +++- src/gui/doAction.cpp | 88 +++++++++++++++++++++++++++++++++++++++--- src/gui/gui.cpp | 2 + src/gui/gui.h | 5 ++- src/gui/sampleEdit.cpp | 30 ++++++++++++++ src/gui/settings.cpp | 7 +++- 6 files changed, 129 insertions(+), 11 deletions(-) diff --git a/src/engine/sample.cpp b/src/engine/sample.cpp index 33532d43..19768fcf 100644 --- a/src/engine/sample.cpp +++ b/src/engine/sample.cpp @@ -258,7 +258,6 @@ bool DivSample::trim(unsigned int begin, unsigned int end) { return false; } -// TODO: for clipboard bool DivSample::insert(unsigned int pos, unsigned int length) { unsigned int count=samples+length; if (depth==8) { @@ -283,7 +282,12 @@ bool DivSample::insert(unsigned int pos, unsigned int length) { short* oldData16=data16; data16=NULL; initInternal(16,count); - memcpy(data16,oldData16,sizeof(short)*count); + if (pos>0) { + memcpy(data16,oldData16,sizeof(short)*pos); + } + if (count-pos-length>0) { + memcpy(&(data16[pos+length]),&(oldData16[pos]),sizeof(short)*(count-pos-length)); + } delete[] oldData16; } else { initInternal(16,count); diff --git a/src/gui/doAction.cpp b/src/gui/doAction.cpp index 51dad892..c89c957c 100644 --- a/src/gui/doAction.cpp +++ b/src/gui/doAction.cpp @@ -599,7 +599,7 @@ void FurnaceGUI::doAction(int what) { } sampleClipboard=new short[end-start]; sampleClipboardLen=end-start; - memcpy(sampleClipboard,&(sample->data16[start]),end-start); + memcpy(sampleClipboard,&(sample->data16[start]),sizeof(short)*(end-start)); e->lockEngine([this,sample,start,end]() { sample->strip(start,end); @@ -625,18 +625,92 @@ void FurnaceGUI::doAction(int what) { } sampleClipboard=new short[end-start]; sampleClipboardLen=end-start; - memcpy(sampleClipboard,&(sample->data16[start]),end-start); + memcpy(sampleClipboard,&(sample->data16[start]),sizeof(short)*(end-start)); break; } - case GUI_ACTION_SAMPLE_PASTE: // TODO!!! + case GUI_ACTION_SAMPLE_PASTE: { if (curSample<0 || curSample>=(int)e->song.sample.size()) break; + if (sampleClipboard==NULL || sampleClipboardLen<1) break; + DivSample* sample=e->song.sample[curSample]; + int pos=(sampleSelStart==-1 || sampleSelStart==sampleSelEnd)?sample->samples:sampleSelStart; + + e->lockEngine([this,sample,pos]() { + if (!sample->insert(pos,sampleClipboardLen)) { + showError("couldn't paste! make sure your sample is 8 or 16-bit."); + } else { + if (sample->depth==8) { + for (size_t i=0; idata8[pos+i]=sampleClipboard[i]>>8; + } + } else { + memcpy(&(sample->data16[pos]),sampleClipboard,sizeof(short)*sampleClipboardLen); + } + } + e->renderSamples(); + }); + sampleSelStart=pos; + sampleSelEnd=pos+sampleClipboardLen; + MARK_MODIFIED; break; - case GUI_ACTION_SAMPLE_PASTE_REPLACE: + } + case GUI_ACTION_SAMPLE_PASTE_REPLACE: { if (curSample<0 || curSample>=(int)e->song.sample.size()) break; + if (sampleClipboard==NULL || sampleClipboardLen<1) break; + DivSample* sample=e->song.sample[curSample]; + int pos=(sampleSelStart==-1 || sampleSelStart==sampleSelEnd)?0:sampleSelStart; + + e->lockEngine([this,sample,pos]() { + if (sample->depth==8) { + for (size_t i=0; i=sample->samples) break; + sample->data8[pos+i]=sampleClipboard[i]>>8; + } + } else { + for (size_t i=0; i=sample->samples) break; + sample->data16[pos+i]=sampleClipboard[i]; + } + } + e->renderSamples(); + }); + sampleSelStart=pos; + sampleSelEnd=pos+sampleClipboardLen; + if (sampleSelEnd>(int)sample->samples) sampleSelEnd=sample->samples; + MARK_MODIFIED; break; - case GUI_ACTION_SAMPLE_PASTE_MIX: + } + case GUI_ACTION_SAMPLE_PASTE_MIX: { if (curSample<0 || curSample>=(int)e->song.sample.size()) break; + if (sampleClipboard==NULL || sampleClipboardLen<1) break; + DivSample* sample=e->song.sample[curSample]; + int pos=(sampleSelStart==-1 || sampleSelStart==sampleSelEnd)?0:sampleSelStart; + + e->lockEngine([this,sample,pos]() { + if (sample->depth==8) { + for (size_t i=0; i=sample->samples) break; + int val=sample->data8[pos+i]+(sampleClipboard[i]>>8); + if (val>127) val=127; + if (val<-128) val=-128; + sample->data8[pos+i]=val; + } + } else { + for (size_t i=0; i=sample->samples) break; + int val=sample->data16[pos+i]+sampleClipboard[i]; + if (val>32767) val=32767; + if (val<-32768) val=-32768; + sample->data16[pos+i]=val; + } + } + e->renderSamples(); + }); + sampleSelStart=pos; + sampleSelEnd=pos+sampleClipboardLen; + if (sampleSelEnd>(int)sample->samples) sampleSelEnd=sample->samples; + MARK_MODIFIED; break; + } case GUI_ACTION_SAMPLE_SELECT_ALL: { if (curSample<0 || curSample>=(int)e->song.sample.size()) break; DivSample* sample=e->song.sample[curSample]; @@ -761,6 +835,10 @@ void FurnaceGUI::doAction(int what) { MARK_MODIFIED; break; } + case GUI_ACTION_SAMPLE_INSERT: + if (curSample<0 || curSample>=(int)e->song.sample.size()) break; + openSampleSilenceOpt=true; + break; case GUI_ACTION_SAMPLE_SILENCE: { if (curSample<0 || curSample>=(int)e->song.sample.size()) break; DivSample* sample=e->song.sample[curSample]; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 11d8875b..fedf53d1 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -2838,6 +2838,7 @@ FurnaceGUI::FurnaceGUI(): prevSampleZoom(1.0), samplePos(0), resizeSize(1024), + silenceSize(1024), resampleTarget(32000), resampleStrat(5), amplifyVol(100.0), @@ -2863,6 +2864,7 @@ FurnaceGUI::FurnaceGUI(): openSampleResizeOpt(false), openSampleResampleOpt(false), openSampleAmplifyOpt(false), + openSampleSilenceOpt(false), openSampleFilterOpt(false) { // value keys valueKeys[SDLK_0]=0; diff --git a/src/gui/gui.h b/src/gui/gui.h index aa661b3a..f92efd95 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -380,6 +380,7 @@ enum FurnaceGUIActions { GUI_ACTION_SAMPLE_FADE_IN, GUI_ACTION_SAMPLE_FADE_OUT, GUI_ACTION_SAMPLE_SILENCE, + GUI_ACTION_SAMPLE_INSERT, GUI_ACTION_SAMPLE_DELETE, GUI_ACTION_SAMPLE_TRIM, GUI_ACTION_SAMPLE_REVERSE, @@ -796,7 +797,7 @@ class FurnaceGUI { double sampleZoom; double prevSampleZoom; int samplePos; - int resizeSize; + int resizeSize, silenceSize; double resampleTarget; int resampleStrat; float amplifyVol; @@ -810,7 +811,7 @@ class FurnaceGUI { unsigned char sampleFilterPower; short* sampleClipboard; size_t sampleClipboardLen; - bool openSampleResizeOpt, openSampleResampleOpt, openSampleAmplifyOpt, openSampleFilterOpt; + bool openSampleResizeOpt, openSampleResampleOpt, openSampleAmplifyOpt, openSampleSilenceOpt, openSampleFilterOpt; // visualizer float keyHit[DIV_MAX_CHANS]; diff --git a/src/gui/sampleEdit.cpp b/src/gui/sampleEdit.cpp index 28e0f3d5..81bab448 100644 --- a/src/gui/sampleEdit.cpp +++ b/src/gui/sampleEdit.cpp @@ -303,6 +303,36 @@ void FurnaceGUI::drawSampleEdit() { ImGui::SetTooltip("Fade out"); } ImGui::SameLine(); + ImGui::Button(ICON_FA_ADJUST "##SInsertSilence"); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Insert silence"); + } + if (openSampleSilenceOpt) { + openSampleSilenceOpt=false; + ImGui::OpenPopup("SSilenceOpt"); + } + if (ImGui::BeginPopupContextItem("SSilenceOpt",ImGuiPopupFlags_MouseButtonLeft)) { + if (ImGui::InputInt("Samples",&silenceSize,1,64)) { + if (silenceSize<0) silenceSize=0; + if (silenceSize>16777215) silenceSize=16777215; + } + if (ImGui::Button("Resize")) { + int pos=(sampleSelStart==-1 || sampleSelStart==sampleSelEnd)?sample->samples:sampleSelStart; + e->lockEngine([this,sample,pos]() { + if (!sample->insert(pos,silenceSize)) { + showError("couldn't insert! make sure your sample is 8 or 16-bit."); + } + e->renderSamples(); + }); + updateSampleTex=true; + sampleSelStart=pos; + sampleSelEnd=pos+silenceSize; + MARK_MODIFIED; + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } + ImGui::SameLine(); if (ImGui::Button(ICON_FA_ERASER "##SSilence")) { doAction(GUI_ACTION_SAMPLE_SILENCE); } diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index 9a1a9eee..9f1a8f5b 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -883,6 +883,7 @@ void FurnaceGUI::drawSettings() { UI_KEYBIND_CONFIG(GUI_ACTION_SAMPLE_NORMALIZE,"Normalize"); UI_KEYBIND_CONFIG(GUI_ACTION_SAMPLE_FADE_IN,"Fade in"); UI_KEYBIND_CONFIG(GUI_ACTION_SAMPLE_FADE_OUT,"Fade out"); + UI_KEYBIND_CONFIG(GUI_ACTION_SAMPLE_INSERT,"Insert silence"); UI_KEYBIND_CONFIG(GUI_ACTION_SAMPLE_SILENCE,"Apply silence"); UI_KEYBIND_CONFIG(GUI_ACTION_SAMPLE_DELETE,"Delete"); UI_KEYBIND_CONFIG(GUI_ACTION_SAMPLE_TRIM,"Trim"); @@ -1158,8 +1159,8 @@ void FurnaceGUI::syncSettings() { LOAD_KEYBIND(GUI_ACTION_SAMPLE_CUT,FURKMOD_CMD|SDLK_x); LOAD_KEYBIND(GUI_ACTION_SAMPLE_COPY,FURKMOD_CMD|SDLK_c); LOAD_KEYBIND(GUI_ACTION_SAMPLE_PASTE,FURKMOD_CMD|SDLK_v); - LOAD_KEYBIND(GUI_ACTION_SAMPLE_PASTE_REPLACE,FURKMOD_CMD|FURKMOD_SHIFT|SDLK_x); - LOAD_KEYBIND(GUI_ACTION_SAMPLE_PASTE_MIX,FURKMOD_CMD|FURKMOD_ALT|SDLK_x); + LOAD_KEYBIND(GUI_ACTION_SAMPLE_PASTE_REPLACE,FURKMOD_CMD|FURKMOD_SHIFT|SDLK_v); + LOAD_KEYBIND(GUI_ACTION_SAMPLE_PASTE_MIX,FURKMOD_CMD|FURKMOD_ALT|SDLK_v); LOAD_KEYBIND(GUI_ACTION_SAMPLE_SELECT_ALL,FURKMOD_CMD|SDLK_a); LOAD_KEYBIND(GUI_ACTION_SAMPLE_RESIZE,FURKMOD_CMD|SDLK_r); LOAD_KEYBIND(GUI_ACTION_SAMPLE_RESAMPLE,FURKMOD_CMD|SDLK_e); @@ -1167,6 +1168,7 @@ void FurnaceGUI::syncSettings() { LOAD_KEYBIND(GUI_ACTION_SAMPLE_NORMALIZE,FURKMOD_CMD|SDLK_n); LOAD_KEYBIND(GUI_ACTION_SAMPLE_FADE_IN,FURKMOD_CMD|SDLK_i); LOAD_KEYBIND(GUI_ACTION_SAMPLE_FADE_OUT,FURKMOD_CMD|SDLK_o); + LOAD_KEYBIND(GUI_ACTION_SAMPLE_INSERT,SDLK_INSERT); LOAD_KEYBIND(GUI_ACTION_SAMPLE_SILENCE,FURKMOD_SHIFT|SDLK_DELETE); LOAD_KEYBIND(GUI_ACTION_SAMPLE_DELETE,SDLK_DELETE); LOAD_KEYBIND(GUI_ACTION_SAMPLE_TRIM,FURKMOD_CMD|SDLK_DELETE); @@ -1479,6 +1481,7 @@ void FurnaceGUI::commitSettings() { SAVE_KEYBIND(GUI_ACTION_SAMPLE_NORMALIZE); SAVE_KEYBIND(GUI_ACTION_SAMPLE_FADE_IN); SAVE_KEYBIND(GUI_ACTION_SAMPLE_FADE_OUT); + SAVE_KEYBIND(GUI_ACTION_SAMPLE_INSERT); SAVE_KEYBIND(GUI_ACTION_SAMPLE_SILENCE); SAVE_KEYBIND(GUI_ACTION_SAMPLE_DELETE); SAVE_KEYBIND(GUI_ACTION_SAMPLE_TRIM);