Skip to content

Commit

Permalink
Merge pull request #1622 from LeviathaninWaves/crossfade-loop-points
Browse files Browse the repository at this point in the history
Crossfade loop points
  • Loading branch information
tildearrow authored Dec 5, 2023
2 parents 6ac348b + 02bc89f commit afa15bc
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 3 deletions.
4 changes: 4 additions & 0 deletions src/gui/doAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1336,6 +1336,10 @@ void FurnaceGUI::doAction(int what) {
MARK_MODIFIED;
break;
}
case GUI_ACTION_SAMPLE_CROSSFADE_LOOP:
if (curSample<0 || curSample>=(int)e->song.sample.size()) break;
openSampleCrossFadeOpt=true;
break;
case GUI_ACTION_SAMPLE_FILTER:
if (curSample<0 || curSample>=(int)e->song.sample.size()) break;
openSampleFilterOpt=true;
Expand Down
3 changes: 3 additions & 0 deletions src/gui/gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7570,6 +7570,8 @@ FurnaceGUI::FurnaceGUI():
sampleFilterRes(0.25f),
sampleFilterCutStart(16000.0f),
sampleFilterCutEnd(100.0f),
sampleCrossFadeLoopLength(0),
sampleCrossFadeLoopLaw(50),
sampleFilterPower(1),
sampleClipboard(NULL),
sampleClipboardLen(0),
Expand All @@ -7578,6 +7580,7 @@ FurnaceGUI::FurnaceGUI():
openSampleAmplifyOpt(false),
openSampleSilenceOpt(false),
openSampleFilterOpt(false),
openSampleCrossFadeOpt(false),
selectedPortSet(0x1fff),
selectedSubPort(-1),
hoveredPortSet(0x1fff),
Expand Down
4 changes: 3 additions & 1 deletion src/gui/gui.h
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,7 @@ enum FurnaceGUIActions {
GUI_ACTION_SAMPLE_INVERT,
GUI_ACTION_SAMPLE_SIGN,
GUI_ACTION_SAMPLE_FILTER,
GUI_ACTION_SAMPLE_CROSSFADE_LOOP,
GUI_ACTION_SAMPLE_PREVIEW,
GUI_ACTION_SAMPLE_STOP_PREVIEW,
GUI_ACTION_SAMPLE_ZOOM_IN,
Expand Down Expand Up @@ -2104,10 +2105,11 @@ class FurnaceGUI {
ImVec2 sampleDragAreaSize;
unsigned int sampleDragLen;
float sampleFilterL, sampleFilterB, sampleFilterH, sampleFilterRes, sampleFilterCutStart, sampleFilterCutEnd;
int sampleCrossFadeLoopLength, sampleCrossFadeLoopLaw;
unsigned char sampleFilterPower;
short* sampleClipboard;
size_t sampleClipboardLen;
bool openSampleResizeOpt, openSampleResampleOpt, openSampleAmplifyOpt, openSampleSilenceOpt, openSampleFilterOpt;
bool openSampleResizeOpt, openSampleResampleOpt, openSampleAmplifyOpt, openSampleSilenceOpt, openSampleFilterOpt, openSampleCrossFadeOpt;

// mixer
// 0xxx: output
Expand Down
1 change: 1 addition & 0 deletions src/gui/guiConst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,7 @@ const FurnaceGUIActionDef guiActions[GUI_ACTION_MAX]={
D("SAMPLE_INVERT", "Invert", FURKMOD_CMD|FURKMOD_SHIFT|SDLK_t),
D("SAMPLE_SIGN", "Signed/unsigned exchange", FURKMOD_CMD|SDLK_u),
D("SAMPLE_FILTER", "Apply filter", FURKMOD_CMD|SDLK_f),
D("SAMPLE_CROSSFADE_LOOP", "Crossfade loop points", NOT_AN_ACTION),
D("SAMPLE_PREVIEW", "Preview sample", 0),
D("SAMPLE_STOP_PREVIEW", "Stop sample preview", 0),
D("SAMPLE_ZOOM_IN", "Zoom in", FURKMOD_CMD|SDLK_EQUALS),
Expand Down
68 changes: 68 additions & 0 deletions src/gui/sampleEdit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1226,6 +1226,74 @@ void FurnaceGUI::drawSampleEdit() {
ImGui::SameLine();
ImGui::Dummy(ImVec2(4.0*dpiScale,dpiScale));
sameLineMaybe();
ImGui::Button(ICON_FUR_CROSSFADE "##CrossFade");
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Crossfade loop points");
}
if (openSampleCrossFadeOpt) {
openSampleCrossFadeOpt=false;
ImGui::OpenPopup("SCrossFadeOpt");
}
if (ImGui::BeginPopupContextItem("SCrossFadeOpt",ImGuiPopupFlags_MouseButtonLeft)) {
if (sampleCrossFadeLoopLength>sample->loopStart) sampleCrossFadeLoopLength=sample->loopStart;
if (sampleCrossFadeLoopLength>(sample->loopEnd-sample->loopStart)) sampleCrossFadeLoopLength=sample->loopEnd-sample->loopStart;
if (ImGui::SliderInt("Number of samples",&sampleCrossFadeLoopLength,0,100000)) {
if (sampleCrossFadeLoopLength<0) sampleCrossFadeLoopLength=0;
if (sampleCrossFadeLoopLength>sample->loopStart) sampleCrossFadeLoopLength=sample->loopStart;
if (sampleCrossFadeLoopLength>(sample->loopEnd-sample->loopStart)) sampleCrossFadeLoopLength=sample->loopEnd-sample->loopStart;
if (sampleCrossFadeLoopLength>100000) sampleCrossFadeLoopLength=100000;
}
if (ImGui::SliderInt("Linear <-> Equal power",&sampleCrossFadeLoopLaw,0,100)) {
if (sampleCrossFadeLoopLaw<0) sampleCrossFadeLoopLaw=0;
if (sampleCrossFadeLoopLaw>100) sampleCrossFadeLoopLaw=100;
}
if (ImGui::Button("Apply")) {
if (sampleCrossFadeLoopLength>sample->loopStart) {
showError("Crossfade: length would go out of bounds. Aborted...");
ImGui::CloseCurrentPopup();
} else if (sampleCrossFadeLoopLength>(sample->loopEnd-sample->loopStart)) {
showError("Crossfade: length would overflow loopStart. Try a smaller random value.");
ImGui::CloseCurrentPopup();
} else {
sample->prepareUndo(true);
e->lockEngine([this,sample] {
SAMPLE_OP_BEGIN;
double l=1.0/(double)sampleCrossFadeLoopLength;
double evar=1.0-sampleCrossFadeLoopLaw/200.0;
if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
unsigned int crossFadeInput=sample->loopStart-sampleCrossFadeLoopLength;
unsigned int crossFadeOutput=sample->loopEnd-sampleCrossFadeLoopLength;
for (int i=0; i<sampleCrossFadeLoopLength; i++) {
double f1=pow(i*l,evar);
double f2=pow((sampleCrossFadeLoopLength-i)*l,evar);
signed char out=(signed char)(((double)sample->data8[crossFadeInput])*f1+((double)sample->data8[crossFadeOutput])*f2);
sample->data8[crossFadeOutput]=out;
crossFadeInput++;
crossFadeOutput++;
}
} else if (sample->depth==DIV_SAMPLE_DEPTH_16BIT) {
unsigned int crossFadeInput=sample->loopStart-sampleCrossFadeLoopLength;
unsigned int crossFadeOutput=sample->loopEnd-sampleCrossFadeLoopLength;
for (int i=0; i<sampleCrossFadeLoopLength; i++) {
double f1=std::pow(i*l,evar);
double f2=std::pow((sampleCrossFadeLoopLength-i)*l,evar);
short out=(short)(((double)sample->data16[crossFadeInput])*f1+((double)sample->data16[crossFadeOutput])*f2);
sample->data16[crossFadeOutput]=out;
crossFadeInput++;
crossFadeOutput++;
}
}
updateSampleTex=true;

e->renderSamples(curSample);
});
MARK_MODIFIED;
ImGui::CloseCurrentPopup();
}
}
ImGui::EndPopup();
}
ImGui::SameLine();
if (ImGui::Button(ICON_FA_PLAY "##PreviewSample")) {
e->previewSample(curSample);
}
Expand Down
5 changes: 3 additions & 2 deletions src/icon/furIcons.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// not auto-generated. update every time you change icons.ttf!

#define ICON_MIN_FUR 0xe0f0
#define ICON_MAX_FUR 0xe158
#define ICON_MAX_FUR 0xe159

// test
#define ICON_FUR_TEST0 u8"\ue0f0"
Expand Down Expand Up @@ -105,4 +105,5 @@
#define ICON_FUR_INC_LINEAR u8"\ue14b"
#define ICON_FUR_INC_BENT u8"\ue14c"
#define ICON_FUR_VOL_DIRECT u8"\ue14d"
#define ICON_FUR_ADSR u8"\ue14e"
#define ICON_FUR_ADSR u8"\ue14e"
#define ICON_FUR_CROSSFADE u8"\ue159"

0 comments on commit afa15bc

Please sign in to comment.