sample editor workkkkkkk

This commit is contained in:
tildearrow 2022-03-19 03:42:44 -05:00
parent c59c176de2
commit 689ed3bf65
9 changed files with 221 additions and 7 deletions

View file

@ -19,6 +19,7 @@
#include "dataErrors.h"
#include "song.h"
#include <functional>
#define _USE_MATH_DEFINES
#include "engine.h"
#include "instrument.h"
@ -2275,6 +2276,12 @@ bool DivEngine::switchMaster() {
return true;
}
void DivEngine::synchronized(const std::function<void()>& what) {
isBusy.lock();
what();
isBusy.unlock();
}
TAAudioDesc& DivEngine::getAudioDescWant() {
return want;
}

View file

@ -25,6 +25,7 @@
#include "safeWriter.h"
#include "../audio/taAudio.h"
#include "blip_buf.h"
#include <functional>
#include <thread>
#include <mutex>
#include <map>
@ -244,7 +245,6 @@ class DivEngine {
bool perSystemEffect(int ch, unsigned char effect, unsigned char effectVal);
bool perSystemPostEffect(int ch, unsigned char effect, unsigned char effectVal);
void recalcChans();
void renderSamples();
void reset();
void playSub(bool preserveDrift, int goalRow=0);
@ -587,6 +587,9 @@ class DivEngine {
// get register cheatsheet
const char** getRegisterSheet(int sys);
// UNSAFE render samples - only execute when locked
void renderSamples();
// public render samples
void renderSamplesP();
@ -614,6 +617,9 @@ class DivEngine {
// switch master
bool switchMaster();
// perform secure/sync operation
void synchronized(const std::function<void()>& what);
// get audio desc want
TAAudioDesc& getAudioDescWant();

View file

@ -149,6 +149,35 @@ bool DivSample::init(unsigned int count) {
return true;
}
bool DivSample::resize(unsigned int count) {
if (depth==8) {
if (data8!=NULL) {
signed char* oldData8=data8;
data8=NULL;
initInternal(8,count);
memcpy(data8,oldData8,MIN(count,samples));
delete[] oldData8;
} else {
initInternal(8,count);
}
samples=count;
return true;
} else if (depth==16) {
if (data16!=NULL) {
short* oldData16=data16;
data16=NULL;
initInternal(16,count);
memcpy(data16,oldData16,sizeof(short)*MIN(count,samples));
delete[] oldData16;
} else {
initInternal(16,count);
}
samples=count;
return true;
}
return false;
}
void DivSample::render() {
// step 1: convert to 16-bit if needed
if (depth!=16) {

View file

@ -76,6 +76,14 @@ struct DivSample {
*/
bool init(unsigned int count);
/**
* resize sample data. make sure the sample has been initialized before doing so.
* @warning do not attempt to resize a sample outside of a synchronized block!
* @param count number of samples.
* @return whether it was successful.
*/
bool resize(unsigned int count);
/**
* initialize the rest of sample formats for this sample.
*/

View file

@ -7096,7 +7096,15 @@ FurnaceGUI::FurnaceGUI():
randomMode(false),
oldOrdersLen(0),
sampleZoom(1.0),
samplePos(0) {
samplePos(0),
resizeSize(1024),
resampleTarget(32000),
resampleStrat(5),
amplifyVol(100.0),
sampleSelStart(-1),
sampleSelEnd(-1),
sampleDragActive(false),
sampleDragMode(false) {
// octave 1
/*

View file

@ -738,6 +738,12 @@ class FurnaceGUI {
// sample editor specific
double sampleZoom;
int samplePos;
int resizeSize;
double resampleTarget;
int resampleStrat;
float amplifyVol;
int sampleSelStart, sampleSelEnd;
bool sampleDragActive, sampleDragMode;
// visualizer
float keyHit[DIV_MAX_CHANS];

View file

@ -113,3 +113,12 @@ const char* sampleDepths[17]={
NULL,
"16-bit PCM"
};
const char* resampleStrats[]={
"none",
"linear",
"cubic spline",
"blep synthesis",
"sinc",
"best possible"
};

View file

@ -25,3 +25,4 @@ extern const char* noteNamesG[180];
extern const char* pitchLabel[11];
extern const char* insTypes[];
extern const char* sampleDepths[17];
extern const char* resampleStrats[];

View file

@ -50,7 +50,10 @@ void FurnaceGUI::drawSampleEdit() {
if (ImGui::BeginTable("SampleProps",4,ImGuiTableFlags_SizingStretchSame)) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
if (ImGui::BeginCombo("Type",sampleType.c_str())) {
ImGui::Text("Type");
ImGui::SameLine();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::BeginCombo("##SampleType",sampleType.c_str())) {
for (int i=0; i<17; i++) {
if (sampleDepths[i]==NULL) continue;
if (ImGui::Selectable(sampleDepths[i])) {
@ -66,13 +69,19 @@ void FurnaceGUI::drawSampleEdit() {
}
ImGui::TableNextColumn();
if (ImGui::InputInt("Rate (Hz)",&sample->rate,10,200)) {
ImGui::Text("Rate (Hz)");
ImGui::SameLine();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::InputInt("##SampleRate",&sample->rate,10,200)) {
if (sample->rate<100) sample->rate=100;
if (sample->rate>96000) sample->rate=96000;
}
ImGui::TableNextColumn();
if (ImGui::InputInt("Pitch of C-4 (Hz)",&sample->centerRate,10,200)) {
ImGui::Text("C-4 (Hz)");
ImGui::SameLine();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::InputInt("##SampleCenter",&sample->centerRate,10,200)) {
if (sample->centerRate<100) sample->centerRate=100;
if (sample->centerRate>65535) sample->centerRate=65535;
}
@ -89,6 +98,7 @@ void FurnaceGUI::drawSampleEdit() {
}
if (doLoop) {
ImGui::SameLine();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::InputInt("##LoopPosition",&sample->loopStart,1,10)) {
if (sample->loopStart<0 || sample->loopStart>=(int)sample->samples) {
sample->loopStart=0;
@ -123,6 +133,133 @@ void FurnaceGUI::drawSampleEdit() {
}*/
ImGui::Separator();
ImGui::Button(ICON_FA_I_CURSOR "##SSelect");
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Edit mode: Select");
}
ImGui::SameLine();
ImGui::Button(ICON_FA_PENCIL "##SDraw");
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Edit mode: Draw");
}
ImGui::SameLine();
ImGui::Dummy(ImVec2(4.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 (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")) {
e->synchronized([this,sample]() {
sample->resize(resizeSize);
e->renderSamples();
});
updateSampleTex=true;
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 (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);
ImGui::Button("Resample");
ImGui::EndPopup();
} else {
resampleTarget=sample->rate;
}
ImGui::SameLine();
ImGui::Dummy(ImVec2(4.0*dpiScale,dpiScale));
ImGui::SameLine();
ImGui::Button(ICON_FA_VOLUME_UP "##SAmplify");
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Amplify");
}
if (ImGui::BeginPopupContextItem("SAmplifyOpt",ImGuiPopupFlags_MouseButtonLeft)) {
ImGui::Text("Volume");
if (ImGui::InputFloat("##SRVolume",&amplifyVol,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));
ImGui::Button("Apply");
ImGui::EndPopup();
}
ImGui::SameLine();
ImGui::Button(ICON_FA_ARROWS_V "##SNormalize");
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Normalize");
}
ImGui::SameLine();
ImGui::Button(ICON_FA_ERASER "##SSilence");
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Apply silence");
}
ImGui::SameLine();
ImGui::Dummy(ImVec2(4.0*dpiScale,dpiScale));
ImGui::SameLine();
ImGui::Button(ICON_FA_BACKWARD "##SReverse");
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Reverse");
}
ImGui::SameLine();
ImGui::Button(ICON_FA_SORT_AMOUNT_ASC "##SInvert");
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Invert");
}
ImGui::SameLine();
ImGui::Button(ICON_FA_LEVEL_DOWN "##SSign");
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Signed/unsigned exchange");
}
ImGui::SameLine();
ImGui::Button(ICON_FA_INDUSTRY "##SFilter");
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Apply filter");
}
ImGui::Separator();
ImVec2 avail=ImGui::GetContentRegionAvail();
avail.y-=ImGui::GetFontSize()+ImGui::GetStyle().ItemSpacing.y;
int availX=avail.x;
@ -193,7 +330,10 @@ void FurnaceGUI::drawSampleEdit() {
updateSampleTex=false;
}
ImGui::Image(sampleTex,avail);
ImGui::ImageButton(sampleTex,avail,ImVec2(0,0),ImVec2(1,1),0);
if (ImGui::IsItemClicked()) {
printf("drawing\n");
}
ImGui::Text("A workaround! Pretty cool huh?");
}