GUI: possibly improved sample zooming
sorry I dropped the compact mode because I am making the toolbar dynamic soon...
This commit is contained in:
parent
ca204e6d69
commit
e21040169f
|
@ -5836,6 +5836,7 @@ FurnaceGUI::FurnaceGUI():
|
||||||
oldOrdersLen(0),
|
oldOrdersLen(0),
|
||||||
sampleZoom(1.0),
|
sampleZoom(1.0),
|
||||||
prevSampleZoom(1.0),
|
prevSampleZoom(1.0),
|
||||||
|
minSampleZoom(1.0),
|
||||||
samplePos(0),
|
samplePos(0),
|
||||||
resizeSize(1024),
|
resizeSize(1024),
|
||||||
silenceSize(1024),
|
silenceSize(1024),
|
||||||
|
|
|
@ -1583,6 +1583,7 @@ class FurnaceGUI {
|
||||||
// sample editor specific
|
// sample editor specific
|
||||||
double sampleZoom;
|
double sampleZoom;
|
||||||
double prevSampleZoom;
|
double prevSampleZoom;
|
||||||
|
double minSampleZoom;
|
||||||
int samplePos;
|
int samplePos;
|
||||||
int resizeSize, silenceSize;
|
int resizeSize, silenceSize;
|
||||||
double resampleTarget;
|
double resampleTarget;
|
||||||
|
|
|
@ -97,7 +97,34 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
loopType=sampleLoopModes[sample->loopMode];
|
loopType=sampleLoopModes[sample->loopMode];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!settings.sampleLayout) {
|
|
||||||
|
String sampleIndex=fmt::sprintf("%d",curSample);
|
||||||
|
ImGui::SetNextItemWidth(72.0f*dpiScale);
|
||||||
|
if (ImGui::BeginCombo("##SampleSelect",sampleIndex.c_str())) {
|
||||||
|
String name;
|
||||||
|
for (size_t i=0; i<e->song.sample.size(); i++) {
|
||||||
|
name=fmt::sprintf("%d: %s##_SMPS%d",i,e->song.sample[i]->name,i);
|
||||||
|
if (ImGui::Selectable(name.c_str(),curSample==(int)i)) {
|
||||||
|
curSample=i;
|
||||||
|
sample=e->song.sample[curSample];
|
||||||
|
updateSampleTex=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
if (ImGui::Button(ICON_FA_FOLDER_OPEN "##SELoad")) {
|
||||||
|
doAction(GUI_ACTION_SAMPLE_LIST_OPEN_REPLACE);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button(ICON_FA_FLOPPY_O "##SESave")) {
|
||||||
|
doAction(GUI_ACTION_SAMPLE_LIST_SAVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
ImGui::Text("Name");
|
ImGui::Text("Name");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
|
@ -654,625 +681,42 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
double zoomPercent=100.0/sampleZoom;
|
double zoomPercent=100.0/sampleZoom;
|
||||||
|
bool checkZoomLimit=false;
|
||||||
ImGui::Text("Zoom");
|
ImGui::Text("Zoom");
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetNextItemWidth(150.0f*dpiScale);
|
ImGui::SetNextItemWidth(150.0f*dpiScale);
|
||||||
if (ImGui::InputDouble("##SZoom",&zoomPercent,5.0,20.0,"%g%%")) {
|
if (ImGui::InputDouble("##SZoom",&zoomPercent,zoomPercent/8.0,20.0,"%g%%")) {
|
||||||
if (zoomPercent>10000.0) zoomPercent=10000.0;
|
if (zoomPercent>10000.0) zoomPercent=10000.0;
|
||||||
if (zoomPercent<1.0) zoomPercent=1.0;
|
if (zoomPercent<0.01) zoomPercent=0.01;
|
||||||
sampleZoom=100.0/zoomPercent;
|
sampleZoom=100.0/zoomPercent;
|
||||||
if (sampleZoom<0.01) sampleZoom=0.01;
|
|
||||||
sampleZoomAuto=false;
|
sampleZoomAuto=false;
|
||||||
|
checkZoomLimit=true;
|
||||||
updateSampleTex=true;
|
updateSampleTex=true;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (sampleZoomAuto) {
|
if (sampleZoomAuto) {
|
||||||
|
ImGui::BeginDisabled(minSampleZoom<1.0);
|
||||||
if (ImGui::Button("100%")) {
|
if (ImGui::Button("100%")) {
|
||||||
sampleZoom=1.0;
|
sampleZoom=1.0;
|
||||||
sampleZoomAuto=false;
|
sampleZoomAuto=false;
|
||||||
updateSampleTex=true;
|
updateSampleTex=true;
|
||||||
|
checkZoomLimit=true;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (ImGui::Button("Auto")) {
|
|
||||||
sampleZoomAuto=true;
|
|
||||||
updateSampleTex=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ImGui::Text("Name");
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
|
||||||
if (ImGui::InputText("##SampleName",&sample->name)) {
|
|
||||||
MARK_MODIFIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::BeginTable("SampleProps",2,ImGuiTableFlags_SizingStretchSame)) {
|
|
||||||
ImGui::TableNextRow();
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("Type");
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
|
||||||
if (ImGui::BeginCombo("##SampleType",sampleType.c_str())) {
|
|
||||||
for (int i=0; i<DIV_SAMPLE_DEPTH_MAX; i++) {
|
|
||||||
if (sampleDepths[i]==NULL) continue;
|
|
||||||
if (ImGui::Selectable(sampleDepths[i])) {
|
|
||||||
sample->prepareUndo(true);
|
|
||||||
e->lockEngine([sample]() {
|
|
||||||
sample->render();
|
|
||||||
});
|
|
||||||
sample->depth=(DivSampleDepth)i;
|
|
||||||
e->renderSamplesP();
|
|
||||||
updateSampleTex=true;
|
|
||||||
MARK_MODIFIED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndCombo();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("C-4 (Hz)");
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
|
||||||
if (ImGui::InputInt("##SampleCenter",&sample->centerRate,10,200)) { MARK_MODIFIED
|
|
||||||
if (sample->centerRate<100) sample->centerRate=100;
|
|
||||||
if (sample->centerRate>65535) sample->centerRate=65535;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::TableNextRow();
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("Compat Rate");
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
|
||||||
if (ImGui::InputInt("##SampleRate",&sample->rate,10,200)) { MARK_MODIFIED
|
|
||||||
if (sample->rate<100) sample->rate=100;
|
|
||||||
if (sample->rate>96000) sample->rate=96000;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
bool doLoop=(sample->isLoopable());
|
|
||||||
if (ImGui::Checkbox("Loop",&doLoop)) { MARK_MODIFIED
|
|
||||||
if (doLoop) {
|
|
||||||
sample->loop=true;
|
|
||||||
sample->loopStart=0;
|
|
||||||
sample->loopEnd=sample->samples;
|
|
||||||
} else {
|
|
||||||
sample->loop=false;
|
|
||||||
sample->loopStart=-1;
|
|
||||||
sample->loopEnd=sample->samples;
|
|
||||||
}
|
|
||||||
updateSampleTex=true;
|
|
||||||
if (e->getSampleFormatMask()&(1U<<DIV_SAMPLE_DEPTH_BRR)) {
|
|
||||||
e->renderSamplesP();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered() && sample->depth==DIV_SAMPLE_DEPTH_BRR) {
|
|
||||||
ImGui::SetTooltip("changing the loop in a BRR sample may result in glitches!");
|
|
||||||
}
|
|
||||||
if (doLoop || keepLoopAlive) {
|
|
||||||
keepLoopAlive=false;
|
|
||||||
ImGui::TableNextRow();
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("Loop Mode");
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
|
||||||
if (ImGui::BeginCombo("##SampleLoopMode",loopType.c_str())) {
|
|
||||||
for (int i=0; i<DIV_SAMPLE_LOOP_MAX; i++) {
|
|
||||||
if (sampleLoopModes[i]==NULL) continue;
|
|
||||||
if (ImGui::Selectable(sampleLoopModes[i])) {
|
|
||||||
sample->prepareUndo(true);
|
|
||||||
sample->loopMode=(DivSampleLoopMode)i;
|
|
||||||
e->renderSamplesP();
|
|
||||||
updateSampleTex=true;
|
|
||||||
MARK_MODIFIED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndCombo();
|
|
||||||
}
|
|
||||||
ImGui::TableNextRow();
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("Loop Start");
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
|
||||||
if (ImGui::InputInt("##LoopStartPosition",&sample->loopStart,1,16)) { MARK_MODIFIED
|
|
||||||
if (sample->loopStart<0) {
|
|
||||||
sample->loopStart=0;
|
|
||||||
}
|
|
||||||
if (sample->loopStart>sample->loopEnd) {
|
|
||||||
sample->loopStart=sample->loopEnd;
|
|
||||||
}
|
|
||||||
if (e->getSampleFormatMask()&(1U<<DIV_SAMPLE_DEPTH_BRR)) {
|
|
||||||
e->renderSamplesP();
|
|
||||||
}
|
|
||||||
updateSampleTex=true;
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemActive()) {
|
|
||||||
keepLoopAlive=true;
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered() && sample->depth==DIV_SAMPLE_DEPTH_BRR) {
|
|
||||||
ImGui::SetTooltip("changing the loop in a BRR sample may result in glitches!");
|
|
||||||
}
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("Loop End");
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
|
||||||
if (ImGui::InputInt("##LoopEndPosition",&sample->loopEnd,1,16)) { MARK_MODIFIED
|
|
||||||
if (sample->loopEnd<sample->loopStart) {
|
|
||||||
sample->loopEnd=sample->loopStart;
|
|
||||||
}
|
|
||||||
if (sample->loopEnd>=(int)sample->samples) {
|
|
||||||
sample->loopEnd=sample->samples;
|
|
||||||
}
|
|
||||||
if (e->getSampleFormatMask()&(1U<<DIV_SAMPLE_DEPTH_BRR)) {
|
|
||||||
e->renderSamplesP();
|
|
||||||
}
|
|
||||||
updateSampleTex=true;
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemActive()) {
|
|
||||||
keepLoopAlive=true;
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered() && sample->depth==DIV_SAMPLE_DEPTH_BRR) {
|
|
||||||
ImGui::SetTooltip("changing the loop in a BRR sample may result in glitches!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (ImGui::Button("Apply")) {
|
|
||||||
e->renderSamplesP();
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
*/
|
|
||||||
ImGui::Separator();
|
|
||||||
|
|
||||||
pushToggleColors(!sampleDragMode);
|
|
||||||
if (ImGui::Button(ICON_FA_I_CURSOR "##SSelect")) {
|
|
||||||
sampleDragMode=false;
|
|
||||||
}
|
|
||||||
popToggleColors();
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Edit mode: Select");
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
pushToggleColors(sampleDragMode);
|
|
||||||
if (ImGui::Button(ICON_FA_PENCIL "##SDraw")) {
|
|
||||||
sampleDragMode=true;
|
|
||||||
}
|
|
||||||
popToggleColors();
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Edit mode: Draw");
|
|
||||||
}
|
|
||||||
ImGui::BeginDisabled(sample->depth!=DIV_SAMPLE_DEPTH_8BIT && sample->depth!=DIV_SAMPLE_DEPTH_16BIT);
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::Dummy(ImVec2(7.0*dpiScale,dpiScale));
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::Button(ICON_FA_ARROWS_H "##SResize");
|
|
||||||
if (ImGui::IsItemClicked()) {
|
|
||||||
resizeSize=sample->samples;
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Resize");
|
|
||||||
}
|
|
||||||
if (openSampleResizeOpt) {
|
|
||||||
openSampleResizeOpt=false;
|
|
||||||
ImGui::OpenPopup("SResizeOpt");
|
|
||||||
}
|
|
||||||
if (ImGui::BeginPopupContextItem("SResizeOpt",ImGuiPopupFlags_MouseButtonLeft)) {
|
|
||||||
if (ImGui::InputInt("Samples",&resizeSize,1,64)) {
|
|
||||||
if (resizeSize<0) resizeSize=0;
|
|
||||||
if (resizeSize>16777215) resizeSize=16777215;
|
|
||||||
}
|
|
||||||
if (ImGui::Button("Resize")) {
|
|
||||||
sample->prepareUndo(true);
|
|
||||||
e->lockEngine([this,sample]() {
|
|
||||||
if (!sample->resize(resizeSize)) {
|
|
||||||
showError("couldn't resize! make sure your sample is 8 or 16-bit.");
|
|
||||||
}
|
|
||||||
e->renderSamples();
|
|
||||||
});
|
|
||||||
updateSampleTex=true;
|
|
||||||
sampleSelStart=-1;
|
|
||||||
sampleSelEnd=-1;
|
|
||||||
MARK_MODIFIED;
|
|
||||||
ImGui::CloseCurrentPopup();
|
|
||||||
}
|
|
||||||
ImGui::EndPopup();
|
|
||||||
} else {
|
|
||||||
resizeSize=sample->samples;
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::Button(ICON_FA_EXPAND "##SResample");
|
|
||||||
if (ImGui::IsItemClicked()) {
|
|
||||||
resampleTarget=sample->rate;
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Resample");
|
|
||||||
}
|
|
||||||
if (openSampleResampleOpt) {
|
|
||||||
openSampleResampleOpt=false;
|
|
||||||
ImGui::OpenPopup("SResampleOpt");
|
|
||||||
}
|
|
||||||
if (ImGui::BeginPopupContextItem("SResampleOpt",ImGuiPopupFlags_MouseButtonLeft)) {
|
|
||||||
ImGui::Text("Rate");
|
|
||||||
if (ImGui::InputDouble("##SRRate",&resampleTarget,1.0,50.0,"%g")) {
|
|
||||||
if (resampleTarget<0) resampleTarget=0;
|
|
||||||
if (resampleTarget>96000) resampleTarget=96000;
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("0.5x")) {
|
|
||||||
resampleTarget*=0.5;
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("==")) {
|
|
||||||
resampleTarget=sample->rate;
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button("2.0x")) {
|
|
||||||
resampleTarget*=2.0;
|
|
||||||
}
|
|
||||||
double factor=resampleTarget/(double)sample->rate;
|
|
||||||
if (ImGui::InputDouble("Factor",&factor,0.125,0.5,"%g")) {
|
|
||||||
resampleTarget=(double)sample->rate*factor;
|
|
||||||
if (resampleTarget<0) resampleTarget=0;
|
|
||||||
if (resampleTarget>96000) resampleTarget=96000;
|
|
||||||
}
|
|
||||||
ImGui::Combo("Filter",&resampleStrat,resampleStrats,6);
|
|
||||||
if (ImGui::Button("Resample")) {
|
|
||||||
sample->prepareUndo(true);
|
|
||||||
e->lockEngine([this,sample]() {
|
|
||||||
if (!sample->resample(resampleTarget,resampleStrat)) {
|
|
||||||
showError("couldn't resample! make sure your sample is 8 or 16-bit.");
|
|
||||||
}
|
|
||||||
e->renderSamples();
|
|
||||||
});
|
|
||||||
updateSampleTex=true;
|
|
||||||
sampleSelStart=-1;
|
|
||||||
sampleSelEnd=-1;
|
|
||||||
MARK_MODIFIED;
|
|
||||||
ImGui::CloseCurrentPopup();
|
|
||||||
}
|
|
||||||
ImGui::EndPopup();
|
|
||||||
} else {
|
|
||||||
resampleTarget=sample->rate;
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::Dummy(ImVec2(0.5*dpiScale,dpiScale));
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::Button(ICON_FA_INDUSTRY "##SFilter");
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Apply filter");
|
|
||||||
}
|
|
||||||
if (openSampleFilterOpt) {
|
|
||||||
openSampleFilterOpt=false;
|
|
||||||
ImGui::OpenPopup("SFilterOpt");
|
|
||||||
}
|
|
||||||
if (ImGui::BeginPopupContextItem("SFilterOpt",ImGuiPopupFlags_MouseButtonLeft)) {
|
|
||||||
float lowP=sampleFilterL*100.0f;
|
|
||||||
float bandP=sampleFilterB*100.0f;
|
|
||||||
float highP=sampleFilterH*100.0f;
|
|
||||||
float resP=sampleFilterRes*100.0f;
|
|
||||||
ImGui::Text("Cutoff:");
|
|
||||||
if (CWSliderFloat("From",&sampleFilterCutStart,0.0f,sample->rate*0.5,"%.0fHz")) {
|
|
||||||
if (sampleFilterCutStart<0.0) sampleFilterCutStart=0.0;
|
|
||||||
if (sampleFilterCutStart>sample->rate*0.5) sampleFilterCutStart=sample->rate*0.5;
|
|
||||||
}
|
|
||||||
if (CWSliderFloat("To",&sampleFilterCutEnd,0.0f,sample->rate*0.5,"%.0fHz")) {
|
|
||||||
if (sampleFilterCutEnd<0.0) sampleFilterCutEnd=0.0;
|
|
||||||
if (sampleFilterCutEnd>sample->rate*0.5) sampleFilterCutEnd=sample->rate*0.5;
|
|
||||||
}
|
|
||||||
ImGui::Separator();
|
|
||||||
if (CWSliderFloat("Resonance",&resP,0.0f,99.0f,"%.1f%%")) {
|
|
||||||
sampleFilterRes=resP/100.0f;
|
|
||||||
if (sampleFilterRes<0.0f) sampleFilterRes=0.0f;
|
|
||||||
if (sampleFilterRes>0.99f) sampleFilterRes=0.99f;
|
|
||||||
}
|
|
||||||
ImGui::Text("Power");
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::RadioButton("1x",sampleFilterPower==1)) {
|
|
||||||
sampleFilterPower=1;
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::RadioButton("2x",sampleFilterPower==2)) {
|
|
||||||
sampleFilterPower=2;
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::RadioButton("3x",sampleFilterPower==3)) {
|
|
||||||
sampleFilterPower=3;
|
|
||||||
}
|
|
||||||
ImGui::Separator();
|
|
||||||
if (CWSliderFloat("Low-pass",&lowP,0.0f,100.0f,"%.1f%%")) {
|
|
||||||
sampleFilterL=lowP/100.0f;
|
|
||||||
if (sampleFilterL<0.0f) sampleFilterL=0.0f;
|
|
||||||
if (sampleFilterL>1.0f) sampleFilterL=1.0f;
|
|
||||||
}
|
|
||||||
if (CWSliderFloat("Band-pass",&bandP,0.0f,100.0f,"%.1f%%")) {
|
|
||||||
sampleFilterB=bandP/100.0f;
|
|
||||||
if (sampleFilterB<0.0f) sampleFilterB=0.0f;
|
|
||||||
if (sampleFilterB>1.0f) sampleFilterB=1.0f;
|
|
||||||
}
|
|
||||||
if (CWSliderFloat("High-pass",&highP,0.0f,100.0f,"%.1f%%")) {
|
|
||||||
sampleFilterH=highP/100.0f;
|
|
||||||
if (sampleFilterH<0.0f) sampleFilterH=0.0f;
|
|
||||||
if (sampleFilterH>1.0f) sampleFilterH=1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::Button("Apply")) {
|
|
||||||
sample->prepareUndo(true);
|
|
||||||
e->lockEngine([this,sample]() {
|
|
||||||
SAMPLE_OP_BEGIN;
|
|
||||||
float res=1.0-pow(sampleFilterRes,0.5f);
|
|
||||||
float low=0;
|
|
||||||
float band=0;
|
|
||||||
float high=0;
|
|
||||||
|
|
||||||
double power=(sampleFilterCutStart>sampleFilterCutEnd)?0.5:2.0;
|
|
||||||
|
|
||||||
if (sample->depth==DIV_SAMPLE_DEPTH_16BIT) {
|
|
||||||
for (unsigned int i=start; i<end; i++) {
|
|
||||||
double freq=sampleFilterCutStart+(sampleFilterCutEnd-sampleFilterCutStart)*pow(double(i-start)/double(end-start),power);
|
|
||||||
double cut=sin((freq/double(sample->rate))*M_PI);
|
|
||||||
|
|
||||||
for (int j=0; j<sampleFilterPower; j++) {
|
|
||||||
low=low+cut*band;
|
|
||||||
high=float(sample->data16[i])-low-(res*band);
|
|
||||||
band=cut*high+band;
|
|
||||||
}
|
|
||||||
|
|
||||||
float val=low*sampleFilterL+band*sampleFilterB+high*sampleFilterH;
|
|
||||||
if (val<-32768) val=-32768;
|
|
||||||
if (val>32767) val=32767;
|
|
||||||
sample->data16[i]=val;
|
|
||||||
}
|
|
||||||
} else if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
|
||||||
for (unsigned int i=start; i<end; i++) {
|
|
||||||
double freq=sampleFilterCutStart+(sampleFilterCutEnd-sampleFilterCutStart)*pow(double(i-start)/double(end-start),power);
|
|
||||||
double cut=sin((freq/double(sample->rate))*M_PI);
|
|
||||||
|
|
||||||
for (int j=0; j<sampleFilterPower; j++) {
|
|
||||||
low=low+cut*band;
|
|
||||||
high=float(sample->data8[i])-low-(res*band);
|
|
||||||
band=cut*high+band;
|
|
||||||
}
|
|
||||||
|
|
||||||
float val=low*sampleFilterL+band*sampleFilterB+high*sampleFilterH;
|
|
||||||
if (val<-128) val=-128;
|
|
||||||
if (val>127) val=127;
|
|
||||||
sample->data8[i]=val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateSampleTex=true;
|
|
||||||
|
|
||||||
e->renderSamples();
|
|
||||||
});
|
|
||||||
MARK_MODIFIED;
|
|
||||||
ImGui::CloseCurrentPopup();
|
|
||||||
}
|
|
||||||
ImGui::EndPopup();
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::Dummy(ImVec2(0.5*dpiScale,dpiScale));
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
|
|
||||||
ImGui::Button(ICON_FA_VOLUME_UP "##SAmplify");
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Amplify");
|
|
||||||
}
|
|
||||||
if (openSampleAmplifyOpt) {
|
|
||||||
openSampleAmplifyOpt=false;
|
|
||||||
ImGui::OpenPopup("SAmplifyOpt");
|
|
||||||
}
|
|
||||||
if (ImGui::BeginPopupContextItem("SAmplifyOpt",ImGuiPopupFlags_MouseButtonLeft)) {
|
|
||||||
ImGui::Text("Volume");
|
|
||||||
if (ImGui::InputFloat("##SRVolume",&lifyVol,10.0,50.0,"%g%%")) {
|
|
||||||
if (amplifyVol<0) amplifyVol=0;
|
|
||||||
if (amplifyVol>10000) amplifyVol=10000;
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::Text("(%.1fdB)",20.0*log10(amplifyVol/100.0f));
|
|
||||||
if (ImGui::Button("Apply")) {
|
|
||||||
sample->prepareUndo(true);
|
|
||||||
e->lockEngine([this,sample]() {
|
|
||||||
SAMPLE_OP_BEGIN;
|
|
||||||
float vol=amplifyVol/100.0f;
|
|
||||||
|
|
||||||
if (sample->depth==DIV_SAMPLE_DEPTH_16BIT) {
|
|
||||||
for (unsigned int i=start; i<end; i++) {
|
|
||||||
float val=sample->data16[i]*vol;
|
|
||||||
if (val<-32768) val=-32768;
|
|
||||||
if (val>32767) val=32767;
|
|
||||||
sample->data16[i]=val;
|
|
||||||
}
|
|
||||||
} else if (sample->depth==DIV_SAMPLE_DEPTH_8BIT) {
|
|
||||||
for (unsigned int i=start; i<end; i++) {
|
|
||||||
float val=sample->data8[i]*vol;
|
|
||||||
if (val<-128) val=-128;
|
|
||||||
if (val>127) val=127;
|
|
||||||
sample->data8[i]=val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateSampleTex=true;
|
|
||||||
|
|
||||||
e->renderSamples();
|
|
||||||
});
|
|
||||||
MARK_MODIFIED;
|
|
||||||
ImGui::CloseCurrentPopup();
|
|
||||||
}
|
|
||||||
ImGui::EndPopup();
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button(ICON_FA_ARROWS_V "##SNormalize")) {
|
|
||||||
doAction(GUI_ACTION_SAMPLE_NORMALIZE);
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Normalize");
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button(ICON_FA_ARROW_UP "##SFadeIn")) {
|
|
||||||
doAction(GUI_ACTION_SAMPLE_FADE_IN);
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Fade in");
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button(ICON_FA_ARROW_DOWN "##SFadeOut")) {
|
|
||||||
doAction(GUI_ACTION_SAMPLE_FADE_OUT);
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Fade out");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::Button(ICON_FA_UNDO "##SUndo")) {
|
|
||||||
doUndoSample();
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Undo");
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button(ICON_FA_REPEAT "##SRedo")) {
|
|
||||||
doRedoSample();
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Redo");
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::Dummy(ImVec2(7.0*dpiScale,dpiScale));
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button(ICON_FA_BACKWARD "##SReverse")) {
|
|
||||||
doAction(GUI_ACTION_SAMPLE_REVERSE);
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Reverse");
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button(ICON_FA_SORT_AMOUNT_ASC "##SInvert")) {
|
|
||||||
doAction(GUI_ACTION_SAMPLE_INVERT);
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Invert");
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::Dummy(ImVec2(0.5*dpiScale,dpiScale));
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button(ICON_FA_LEVEL_DOWN "##SSign")) {
|
|
||||||
doAction(GUI_ACTION_SAMPLE_SIGN);
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Signed/unsigned exchange");
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::Dummy(ImVec2(0.5*dpiScale,dpiScale));
|
|
||||||
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("Go")) {
|
|
||||||
int pos=(sampleSelStart==-1 || sampleSelStart==sampleSelEnd)?sample->samples:sampleSelStart;
|
|
||||||
sample->prepareUndo(true);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Apply silence");
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button(ICON_FA_TIMES "##SDelete")) {
|
|
||||||
doAction(GUI_ACTION_SAMPLE_DELETE);
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Delete");
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button(ICON_FA_CROP "##STrim")) {
|
|
||||||
doAction(GUI_ACTION_SAMPLE_TRIM);
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Trim");
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
if (ImGui::Button(ICON_FA_PLAY "##PreviewSample")) {
|
|
||||||
e->previewSample(curSample);
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Preview sample");
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button(ICON_FA_STOP "##StopSample")) {
|
|
||||||
e->stopSamplePreview();
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Stop sample preview");
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::Button(ICON_FA_UPLOAD "##MakeIns")) {
|
|
||||||
doAction(GUI_ACTION_SAMPLE_MAKE_INS);
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetTooltip("Create instrument from sample");
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
double zoomPercent=100.0/sampleZoom;
|
|
||||||
ImGui::Text("Zoom");
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::SetNextItemWidth(150.0f*dpiScale);
|
|
||||||
if (ImGui::InputDouble("##SZoom",&zoomPercent,5.0,20.0,"%g%%")) {
|
|
||||||
if (zoomPercent>10000.0) zoomPercent=10000.0;
|
|
||||||
if (zoomPercent<1.0) zoomPercent=1.0;
|
|
||||||
sampleZoom=100.0/zoomPercent;
|
|
||||||
if (sampleZoom<0.01) sampleZoom=0.01;
|
|
||||||
sampleZoomAuto=false;
|
|
||||||
updateSampleTex=true;
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (sampleZoomAuto) {
|
|
||||||
if (ImGui::Button("100%")) {
|
|
||||||
sampleZoom=1.0;
|
|
||||||
sampleZoomAuto=false;
|
|
||||||
updateSampleTex=true;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (ImGui::Button("Auto")) {
|
if (ImGui::Button("Auto")) {
|
||||||
sampleZoomAuto=true;
|
sampleZoomAuto=true;
|
||||||
updateSampleTex=true;
|
updateSampleTex=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
ImVec2 avail=ImGui::GetContentRegionAvail(); // graph size determined here
|
ImVec2 avail=ImGui::GetContentRegionAvail(); // graph size determined here
|
||||||
if (ImGui::GetContentRegionAvail().y>(ImGui::GetContentRegionAvail().x*0.5f)) {
|
// don't do this. reason: mobile.
|
||||||
|
/*if (ImGui::GetContentRegionAvail().y>(ImGui::GetContentRegionAvail().x*0.5f)) {
|
||||||
avail=ImVec2(ImGui::GetContentRegionAvail().x,ImGui::GetContentRegionAvail().x*0.5f);
|
avail=ImVec2(ImGui::GetContentRegionAvail().x,ImGui::GetContentRegionAvail().x*0.5f);
|
||||||
}
|
}*/
|
||||||
avail.y-=ImGui::GetFontSize()+ImGui::GetStyle().ItemSpacing.y+ImGui::GetStyle().ScrollbarSize;
|
avail.y-=ImGui::GetFontSize()+ImGui::GetStyle().ItemSpacing.y+ImGui::GetStyle().ScrollbarSize;
|
||||||
if (avail.y<1.0) { // Prevents crash
|
if (avail.y<1.0) { // Prevents crash
|
||||||
avail.y=1.0;
|
avail.y=1.0;
|
||||||
|
@ -1281,12 +725,24 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
int availX=avail.x;
|
int availX=avail.x;
|
||||||
int availY=avail.y;
|
int availY=avail.y;
|
||||||
|
|
||||||
|
minSampleZoom=(double)sample->samples/avail.x;
|
||||||
|
|
||||||
|
if (checkZoomLimit) {
|
||||||
|
logV("sample: %f min: %f",sampleZoom,minSampleZoom);
|
||||||
|
int bounds=((int)sample->samples-round(avail.x*sampleZoom));
|
||||||
|
if (bounds<0) bounds=0;
|
||||||
|
if (samplePos>bounds) samplePos=bounds;
|
||||||
|
if (sampleZoom>minSampleZoom) {
|
||||||
|
sampleZoomAuto=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (sampleZoomAuto) {
|
if (sampleZoomAuto) {
|
||||||
samplePos=0;
|
samplePos=0;
|
||||||
if (sample->samples<1 || avail.x<=0) {
|
if (sample->samples<1 || avail.x<=0) {
|
||||||
sampleZoom=1.0;
|
sampleZoom=1.0;
|
||||||
} else {
|
} else {
|
||||||
sampleZoom=(double)sample->samples/avail.x;
|
sampleZoom=minSampleZoom;
|
||||||
}
|
}
|
||||||
if (sampleZoom!=prevSampleZoom) {
|
if (sampleZoom!=prevSampleZoom) {
|
||||||
prevSampleZoom=sampleZoom;
|
prevSampleZoom=sampleZoom;
|
||||||
|
@ -1496,6 +952,9 @@ void FurnaceGUI::drawSampleEdit() {
|
||||||
if (bounds<0) bounds=0;
|
if (bounds<0) bounds=0;
|
||||||
if (samplePos>bounds) samplePos=bounds;
|
if (samplePos>bounds) samplePos=bounds;
|
||||||
updateSampleTex=true;
|
updateSampleTex=true;
|
||||||
|
if (sampleZoom>minSampleZoom) {
|
||||||
|
sampleZoomAuto=true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (wheelY!=0) {
|
if (wheelY!=0) {
|
||||||
if (!sampleZoomAuto) {
|
if (!sampleZoomAuto) {
|
||||||
|
|
|
@ -1540,11 +1540,6 @@ void FurnaceGUI::drawSettings() {
|
||||||
settings.waveLayout=waveLayoutB;
|
settings.waveLayout=waveLayoutB;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sampleLayoutB=settings.sampleLayout;
|
|
||||||
if (ImGui::Checkbox("Use compact sample editor",&sampleLayoutB)) {
|
|
||||||
settings.sampleLayout=sampleLayoutB;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool oldMacroVSliderB=settings.oldMacroVSlider;
|
bool oldMacroVSliderB=settings.oldMacroVSlider;
|
||||||
if (ImGui::Checkbox("Use classic macro editor vertical slider",&oldMacroVSliderB)) {
|
if (ImGui::Checkbox("Use classic macro editor vertical slider",&oldMacroVSliderB)) {
|
||||||
settings.oldMacroVSlider=oldMacroVSliderB;
|
settings.oldMacroVSlider=oldMacroVSliderB;
|
||||||
|
|
Loading…
Reference in New Issue