GUI: implement sample paste

This commit is contained in:
tildearrow 2022-03-22 17:01:06 -05:00
parent a199c102ce
commit 7ebc63a514
6 changed files with 129 additions and 11 deletions

View File

@ -258,7 +258,6 @@ bool DivSample::trim(unsigned int begin, unsigned int end) {
return false; return false;
} }
// TODO: for clipboard
bool DivSample::insert(unsigned int pos, unsigned int length) { bool DivSample::insert(unsigned int pos, unsigned int length) {
unsigned int count=samples+length; unsigned int count=samples+length;
if (depth==8) { if (depth==8) {
@ -283,7 +282,12 @@ bool DivSample::insert(unsigned int pos, unsigned int length) {
short* oldData16=data16; short* oldData16=data16;
data16=NULL; data16=NULL;
initInternal(16,count); 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; delete[] oldData16;
} else { } else {
initInternal(16,count); initInternal(16,count);

View File

@ -599,7 +599,7 @@ void FurnaceGUI::doAction(int what) {
} }
sampleClipboard=new short[end-start]; sampleClipboard=new short[end-start];
sampleClipboardLen=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]() { e->lockEngine([this,sample,start,end]() {
sample->strip(start,end); sample->strip(start,end);
@ -625,18 +625,92 @@ void FurnaceGUI::doAction(int what) {
} }
sampleClipboard=new short[end-start]; sampleClipboard=new short[end-start];
sampleClipboardLen=end-start; sampleClipboardLen=end-start;
memcpy(sampleClipboard,&(sample->data16[start]),end-start); memcpy(sampleClipboard,&(sample->data16[start]),sizeof(short)*(end-start));
break; break;
} }
case GUI_ACTION_SAMPLE_PASTE: // TODO!!! case GUI_ACTION_SAMPLE_PASTE: {
if (curSample<0 || curSample>=(int)e->song.sample.size()) break; 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; i<sampleClipboardLen; i++) {
sample->data8[pos+i]=sampleClipboard[i]>>8;
}
} else {
memcpy(&(sample->data16[pos]),sampleClipboard,sizeof(short)*sampleClipboardLen);
}
}
e->renderSamples();
});
sampleSelStart=pos;
sampleSelEnd=pos+sampleClipboardLen;
MARK_MODIFIED;
break; break;
case GUI_ACTION_SAMPLE_PASTE_REPLACE: }
case GUI_ACTION_SAMPLE_PASTE_REPLACE: {
if (curSample<0 || curSample>=(int)e->song.sample.size()) break; 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<sampleClipboardLen; i++) {
if (pos+i>=sample->samples) break;
sample->data8[pos+i]=sampleClipboard[i]>>8;
}
} else {
for (size_t i=0; i<sampleClipboardLen; i++) {
if (pos+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; break;
case GUI_ACTION_SAMPLE_PASTE_MIX: }
case GUI_ACTION_SAMPLE_PASTE_MIX: {
if (curSample<0 || curSample>=(int)e->song.sample.size()) break; 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<sampleClipboardLen; i++) {
if (pos+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<sampleClipboardLen; i++) {
if (pos+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; break;
}
case GUI_ACTION_SAMPLE_SELECT_ALL: { case GUI_ACTION_SAMPLE_SELECT_ALL: {
if (curSample<0 || curSample>=(int)e->song.sample.size()) break; if (curSample<0 || curSample>=(int)e->song.sample.size()) break;
DivSample* sample=e->song.sample[curSample]; DivSample* sample=e->song.sample[curSample];
@ -761,6 +835,10 @@ void FurnaceGUI::doAction(int what) {
MARK_MODIFIED; MARK_MODIFIED;
break; break;
} }
case GUI_ACTION_SAMPLE_INSERT:
if (curSample<0 || curSample>=(int)e->song.sample.size()) break;
openSampleSilenceOpt=true;
break;
case GUI_ACTION_SAMPLE_SILENCE: { case GUI_ACTION_SAMPLE_SILENCE: {
if (curSample<0 || curSample>=(int)e->song.sample.size()) break; if (curSample<0 || curSample>=(int)e->song.sample.size()) break;
DivSample* sample=e->song.sample[curSample]; DivSample* sample=e->song.sample[curSample];

View File

@ -2838,6 +2838,7 @@ FurnaceGUI::FurnaceGUI():
prevSampleZoom(1.0), prevSampleZoom(1.0),
samplePos(0), samplePos(0),
resizeSize(1024), resizeSize(1024),
silenceSize(1024),
resampleTarget(32000), resampleTarget(32000),
resampleStrat(5), resampleStrat(5),
amplifyVol(100.0), amplifyVol(100.0),
@ -2863,6 +2864,7 @@ FurnaceGUI::FurnaceGUI():
openSampleResizeOpt(false), openSampleResizeOpt(false),
openSampleResampleOpt(false), openSampleResampleOpt(false),
openSampleAmplifyOpt(false), openSampleAmplifyOpt(false),
openSampleSilenceOpt(false),
openSampleFilterOpt(false) { openSampleFilterOpt(false) {
// value keys // value keys
valueKeys[SDLK_0]=0; valueKeys[SDLK_0]=0;

View File

@ -380,6 +380,7 @@ enum FurnaceGUIActions {
GUI_ACTION_SAMPLE_FADE_IN, GUI_ACTION_SAMPLE_FADE_IN,
GUI_ACTION_SAMPLE_FADE_OUT, GUI_ACTION_SAMPLE_FADE_OUT,
GUI_ACTION_SAMPLE_SILENCE, GUI_ACTION_SAMPLE_SILENCE,
GUI_ACTION_SAMPLE_INSERT,
GUI_ACTION_SAMPLE_DELETE, GUI_ACTION_SAMPLE_DELETE,
GUI_ACTION_SAMPLE_TRIM, GUI_ACTION_SAMPLE_TRIM,
GUI_ACTION_SAMPLE_REVERSE, GUI_ACTION_SAMPLE_REVERSE,
@ -796,7 +797,7 @@ class FurnaceGUI {
double sampleZoom; double sampleZoom;
double prevSampleZoom; double prevSampleZoom;
int samplePos; int samplePos;
int resizeSize; int resizeSize, silenceSize;
double resampleTarget; double resampleTarget;
int resampleStrat; int resampleStrat;
float amplifyVol; float amplifyVol;
@ -810,7 +811,7 @@ class FurnaceGUI {
unsigned char sampleFilterPower; unsigned char sampleFilterPower;
short* sampleClipboard; short* sampleClipboard;
size_t sampleClipboardLen; size_t sampleClipboardLen;
bool openSampleResizeOpt, openSampleResampleOpt, openSampleAmplifyOpt, openSampleFilterOpt; bool openSampleResizeOpt, openSampleResampleOpt, openSampleAmplifyOpt, openSampleSilenceOpt, openSampleFilterOpt;
// visualizer // visualizer
float keyHit[DIV_MAX_CHANS]; float keyHit[DIV_MAX_CHANS];

View File

@ -303,6 +303,36 @@ void FurnaceGUI::drawSampleEdit() {
ImGui::SetTooltip("Fade out"); ImGui::SetTooltip("Fade out");
} }
ImGui::SameLine(); 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")) { if (ImGui::Button(ICON_FA_ERASER "##SSilence")) {
doAction(GUI_ACTION_SAMPLE_SILENCE); doAction(GUI_ACTION_SAMPLE_SILENCE);
} }

View File

@ -883,6 +883,7 @@ void FurnaceGUI::drawSettings() {
UI_KEYBIND_CONFIG(GUI_ACTION_SAMPLE_NORMALIZE,"Normalize"); 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_IN,"Fade in");
UI_KEYBIND_CONFIG(GUI_ACTION_SAMPLE_FADE_OUT,"Fade out"); 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_SILENCE,"Apply silence");
UI_KEYBIND_CONFIG(GUI_ACTION_SAMPLE_DELETE,"Delete"); UI_KEYBIND_CONFIG(GUI_ACTION_SAMPLE_DELETE,"Delete");
UI_KEYBIND_CONFIG(GUI_ACTION_SAMPLE_TRIM,"Trim"); 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_CUT,FURKMOD_CMD|SDLK_x);
LOAD_KEYBIND(GUI_ACTION_SAMPLE_COPY,FURKMOD_CMD|SDLK_c); 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,FURKMOD_CMD|SDLK_v);
LOAD_KEYBIND(GUI_ACTION_SAMPLE_PASTE_REPLACE,FURKMOD_CMD|FURKMOD_SHIFT|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_x); 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_SELECT_ALL,FURKMOD_CMD|SDLK_a);
LOAD_KEYBIND(GUI_ACTION_SAMPLE_RESIZE,FURKMOD_CMD|SDLK_r); LOAD_KEYBIND(GUI_ACTION_SAMPLE_RESIZE,FURKMOD_CMD|SDLK_r);
LOAD_KEYBIND(GUI_ACTION_SAMPLE_RESAMPLE,FURKMOD_CMD|SDLK_e); 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_NORMALIZE,FURKMOD_CMD|SDLK_n);
LOAD_KEYBIND(GUI_ACTION_SAMPLE_FADE_IN,FURKMOD_CMD|SDLK_i); 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_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_SILENCE,FURKMOD_SHIFT|SDLK_DELETE);
LOAD_KEYBIND(GUI_ACTION_SAMPLE_DELETE,SDLK_DELETE); LOAD_KEYBIND(GUI_ACTION_SAMPLE_DELETE,SDLK_DELETE);
LOAD_KEYBIND(GUI_ACTION_SAMPLE_TRIM,FURKMOD_CMD|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_NORMALIZE);
SAVE_KEYBIND(GUI_ACTION_SAMPLE_FADE_IN); SAVE_KEYBIND(GUI_ACTION_SAMPLE_FADE_IN);
SAVE_KEYBIND(GUI_ACTION_SAMPLE_FADE_OUT); SAVE_KEYBIND(GUI_ACTION_SAMPLE_FADE_OUT);
SAVE_KEYBIND(GUI_ACTION_SAMPLE_INSERT);
SAVE_KEYBIND(GUI_ACTION_SAMPLE_SILENCE); SAVE_KEYBIND(GUI_ACTION_SAMPLE_SILENCE);
SAVE_KEYBIND(GUI_ACTION_SAMPLE_DELETE); SAVE_KEYBIND(GUI_ACTION_SAMPLE_DELETE);
SAVE_KEYBIND(GUI_ACTION_SAMPLE_TRIM); SAVE_KEYBIND(GUI_ACTION_SAMPLE_TRIM);