diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 5b0386fb4..1be5e74e4 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -6226,19 +6226,32 @@ FurnaceGUI::FurnaceGUI(): waveGenTL[1]=0.0f; waveGenTL[2]=0.0f; waveGenTL[3]=1.0f; + fmWaveform[0]=0; + fmWaveform[1]=0; + fmWaveform[2]=0; + fmWaveform[3]=0; waveGenMult[0]=1; waveGenMult[1]=1; waveGenMult[2]=1; waveGenMult[3]=1; memset(waveGenFB,0,sizeof(int)*4); - memset(waveGenFMCon1,0,sizeof(bool)*4); - memset(waveGenFMCon2,0,sizeof(bool)*3); - memset(waveGenFMCon3,0,sizeof(bool)*2); + memset(waveGenFMCon0,0,sizeof(bool)*5); + memset(waveGenFMCon1,0,sizeof(bool)*5); + memset(waveGenFMCon2,0,sizeof(bool)*5); + memset(waveGenFMCon3, 0, sizeof(bool) * 5); + memset(waveGenFMCon4,0,sizeof(bool)*5); waveGenAmp[0]=1.0f; - waveGenFMCon1[0]=true; - waveGenFMCon2[0]=true; - waveGenFMCon3[0]=true; + waveGenFMCon0[0]=false; + waveGenFMCon1[0]= true; + waveGenFMCon2[1]= true; + waveGenFMCon3[2] = true; + waveGenFMCon4[0]= false; + + waveGenFMCon0[4] = false; + waveGenFMCon1[4] = false; + waveGenFMCon2[4] = false; + waveGenFMCon3[4] = true; memset(keyHit,0,sizeof(float)*DIV_MAX_CHANS); memset(keyHit1,0,sizeof(float)*DIV_MAX_CHANS); diff --git a/src/gui/gui.h b/src/gui/gui.h index ca4333343..048544e94 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1765,13 +1765,16 @@ class FurnaceGUI { float waveGenAmp[16]; float waveGenPhase[16]; float waveGenTL[4]; + int fmWaveform[4]; int waveGenMult[4]; int waveGenFB[4]; int waveGenScaleX, waveGenScaleY, waveGenOffsetX, waveGenOffsetY, waveGenSmooth; float waveGenAmplify; - bool waveGenFMCon1[4]; - bool waveGenFMCon2[3]; - bool waveGenFMCon3[2]; + bool waveGenFMCon0[5]; + bool waveGenFMCon1[5]; + bool waveGenFMCon2[5]; + bool waveGenFMCon3[5]; + bool waveGenFMCon4[5]; bool waveGenFM; void drawSSGEnv(unsigned char type, const ImVec2& size); diff --git a/src/gui/waveEdit.cpp b/src/gui/waveEdit.cpp index cecc3635e..8922c9fb2 100644 --- a/src/gui/waveEdit.cpp +++ b/src/gui/waveEdit.cpp @@ -40,6 +40,209 @@ const char* waveInterpolations[4]={ "Cubic" }; +double sinus(double x) { + return sin(x); +} +double rectSin(double x) { + return sin(x) > 0 ? sin(x) : 0; +} +double absSin(double x) { + return abs(sin(x)); +} + +double square(double x) { + return fmod(x, (2 * M_PI)) >= M_PI ? -1 : 1; +} +double rectSquare(double x) { + return square(x) > 0 ? square(x) : 0; +} + +double quartSin(double x) { + //if (x < M_PI / 2 || (x >= M_PI && x < (M_PI + M_PI / 2))) + // return absSin(x); + //return 0; + return absSin(x) * rectSquare(2 * x); +} +double squiSin(double x) { + return sin(x) >= 0 ? sin(2 * x) : 0; +} +double squiAbsSin(double x) { + return abs(squiSin(x)); +} + + + + + +double saw(double x) { + return atan(tan(x / 2)) / (M_PI / 2); +} +double rectSaw(double x) { + return saw(x) > 0 ? saw(x) : 0; +} +double absSaw(double x) { + return saw(x) < 0 ? saw(x) + 1 : saw(x); +} + + +double cubSaw(double x) { + return pow(saw(x), 3); +} +double rectCubSaw(double x) { + return pow(rectSaw(x), 3); +} +double absCubSaw(double x) { + return pow(absSaw(x), 3); +} + + +double cubSine(double x) { + return pow(sin(x), 3); +} +double rectCubSin(double x) { + return pow(rectSin(x), 3); +} +double absCubSin(double x) { + return pow(absSin(x), 3); +} +double quartCubSin(double x) { + return pow(quartSin(x), 3); +} +double squishCubSin(double x) { + return pow(squiSin(x), 3); +} +double squishAbsCubSin(double x) { + return pow(squiAbsSin(x), 3); +} + + +double triangle(double x) { + return asin(sin(x)) / (M_PI / 2); +} +double rectTri(double x) { + return triangle(x) > 0 ? triangle(x) : 0; +} +double absTri(double x) { + return abs(triangle(x)); +} +double quartTri(double x) { + //if (x < M_PI / 2 || (x >= M_PI && x < (M_PI + M_PI / 2))) + // return absTri(x); + //return 0; + return absTri(x) * rectSquare(2 * x); +} +double squiTri(double x) { + return sin(x) >= 0 ? triangle(2 * x) : 0; +} +double absSquiTri(double x) { + return abs(squiTri(x)); +} + + +double cubTriangle(double x) { + return pow(triangle(x), 3); +} +double cubRectTri(double x) { + return pow(rectTri(x), 3); +} +double cubAbsTri(double x) { + return pow(absTri(x), 3); +} +double cubQuartTri(double x) { + return pow(quartTri(x), 3); +} +double cubSquiTri(double x) { + return pow(squiTri(x), 3); +} +double absCubSquiTri(double x) { + return abs(cubSquiTri(x)); +} + + +typedef double (*WaveFunc) (double a); + +WaveFunc waveFuncs[] = { + sinus, + rectSin, + absSin, + quartSin, + squiSin, + squiAbsSin, + + square, + rectSquare, + + saw, + rectSaw, + absSaw, + + cubSaw, + rectCubSaw, + absCubSaw, + + cubSine, + rectCubSin, + absCubSin, + quartCubSin, + squishCubSin, + squishAbsCubSin, + + triangle, + rectTri, + absTri, + quartTri, + squiTri, + absSquiTri, + + cubTriangle, + cubRectTri, + cubAbsTri, + cubQuartTri, + cubSquiTri, + absCubSquiTri +}; + +const char* fmWaveforms[] = { + "Sine", + "Rect. Sine", + "Abs. Sine", + "Quart. Sine", + "Squish. Sine", + "Abs. Squish. Sine", + + "Square", + "rectSquare", + + "Saw", + "Rect. Saw", + "Abs. Saw", + + "Cubed Saw", + "Rect. Cubed Saw", + "Abs. Cubed Saw", + + "Cubed Sine", + "Rect. Cubed Sine", + "Abs. Cubed Sine", + "Quart. Cubed Sine", + "Squish. Cubed Sine", + "Squish. Abs. Cub. Sine", + + "Triangle", + "Rect. Triangle", + "Abs. Triangle", + "Quart. Triangle", + "Squish. Triangle", + "Abs. Squish. Triangle", + + "Cubed Triangle", + "Rect. Cubed Triangle", + "Abs. Cubed Triangle", + "Quart. Cubed Triangle", + "Squish. Cubed Triangle", + "Squish. Abs. Cub. Triangle", +}; + const float multFactors[17]={ M_PI, 2*M_PI, @@ -60,6 +263,8 @@ const float multFactors[17]={ 32*M_PI, }; + + void FurnaceGUI::doGenerateWave() { float finalResult[256]; if (curWave<0 || curWave>=(int)e->song.wave.size()) return; @@ -78,28 +283,63 @@ void FurnaceGUI::doGenerateWave() { float s2fb1=0; float s3fb0=0; float s3fb1=0; + + float s0 = 0; + float s1 = 0; + float s2 = 0; + float s3 = 1; + for (int i=0; ilen; i++) { float pos=(float)i/(float)wave->len; - float s0=sin((pos+(waveGenFB[0]?((s0fb0+s0fb1)*pow(2.0f,waveGenFB[0]-8)):0.0f))*multFactors[waveGenMult[0]])*waveGenTL[0]; + + s0 = waveFuncs[fmWaveform[0]]((pos + + (waveGenFB[0] ? ((s0fb0 + s0fb1) * pow(2.0f, waveGenFB[0] - 8)) : 0.0f) + + (waveGenFMCon0[3] ? s3 : 0.0f) + + (waveGenFMCon0[2] ? s2 : 0.0f) + + (waveGenFMCon0[1] ? s1 : 0.0f) + + (waveGenFMCon0[0] ? s0 : 0.0f))* multFactors[waveGenMult[0]]) * waveGenTL[0]; + s0fb0=s0fb1; s0fb1=s0; - float s1=sin((pos+(waveGenFB[1]?((s1fb0+s1fb1)*pow(2.0f,waveGenFB[1]-8)):0.0f)+(waveGenFMCon1[0]?s0:0.0f))*multFactors[waveGenMult[1]])*waveGenTL[1]; + + s1 = waveFuncs[fmWaveform[1]]((pos + + (waveGenFB[1] ? ((s1fb0 + s1fb1) * pow(2.0f, waveGenFB[1] - 8)) : 0.0f) + + (waveGenFMCon1[3] ? s3 : 0.0f) + + (waveGenFMCon1[2] ? s2 : 0.0f) + + (waveGenFMCon1[1] ? s1 : 0.0f) + + (waveGenFMCon1[0] ? s0 : 0.0f))* multFactors[waveGenMult[1]]) * waveGenTL[1]; + s1fb0=s1fb1; s1fb1=s1; + - float s2=sin((pos+(waveGenFB[2]?((s2fb0+s2fb1)*pow(2.0f,waveGenFB[2]-8)):0.0f)+(waveGenFMCon1[1]?s0:0.0f)+(waveGenFMCon2[0]?s1:0.0f))*multFactors[waveGenMult[2]])*waveGenTL[2]; + s2 = waveFuncs[fmWaveform[2]]((pos + + (waveGenFB[2] ? ((s2fb0 + s2fb1) * pow(2.0f, waveGenFB[2] - 8)) : 0.0f) + + (waveGenFMCon2[3] ? s3 : 0.0f) + + (waveGenFMCon2[2] ? s2 : 0.0f) + + (waveGenFMCon2[1] ? s1 : 0.0f) + + (waveGenFMCon2[0] ? s0 : 0.0f))* multFactors[waveGenMult[2]]) * waveGenTL[2]; + s2fb0=s2fb1; s2fb1=s2; - float s3=sin((pos+(waveGenFB[3]?((s3fb0+s3fb1)*pow(2.0f,waveGenFB[3]-8)):0.0f)+(waveGenFMCon1[2]?s0:0.0f)+(waveGenFMCon2[1]?s1:0.0f)+(waveGenFMCon3[0]?s2:0.0f))*multFactors[waveGenMult[3]])*waveGenTL[3]; + + s3 = waveFuncs[fmWaveform[3]]((pos + + (waveGenFB[3] ? ((s3fb0 + s3fb1) * pow(2.0f, waveGenFB[3] - 8)) : 0.0f) + + (waveGenFMCon3[3] ? s3 : 0.0f) + + (waveGenFMCon3[2] ? s2 : 0.0f) + + (waveGenFMCon3[1] ? s1 : 0.0f) + + (waveGenFMCon3[0] ? s0 : 0.0f)) * multFactors[waveGenMult[3]])* waveGenTL[3]; + s3fb0=s3fb1; s3fb1=s3; - if (waveGenFMCon1[3]) finalResult[i]+=s0; - if (waveGenFMCon2[2]) finalResult[i]+=s1; - if (waveGenFMCon3[1]) finalResult[i]+=s2; - finalResult[i]+=s3; + if (waveGenFMCon0[4]) finalResult[i]+=s0; + if (waveGenFMCon1[4]) finalResult[i]+=s1; + if (waveGenFMCon2[4]) finalResult[i]+=s2; + if (waveGenFMCon3[4]) finalResult[i]+=s3; + //finalResult[i]+=s3; } } else { switch (waveGenBaseShape) { @@ -165,9 +405,15 @@ void FurnaceGUI::doGenerateWave() { MARK_MODIFIED; } + + #define CENTER_TEXT(text) \ ImGui::SetCursorPosX(ImGui::GetCursorPosX()+0.5*(ImGui::GetContentRegionAvail().x-ImGui::CalcTextSize(text).x)); + +//int lengthArray() + + void FurnaceGUI::drawWaveEdit() { if (nextWindow==GUI_WINDOW_WAVE_EDIT) { waveEditOpen=true; @@ -441,7 +687,7 @@ void FurnaceGUI::drawWaveEdit() { ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed,ImGui::CalcTextSize("Op").x); ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.5); ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.25); - ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthStretch,0.25); + ImGui::TableSetupColumn("c3", ImGuiTableColumnFlags_WidthStretch, 0.25); ImGui::TableNextRow(ImGuiTableRowFlags_Headers); ImGui::TableNextColumn(); @@ -480,84 +726,239 @@ void FurnaceGUI::drawWaveEdit() { if (CWSliderInt("##WGFB",&waveGenFB[i],0,7)) { doGenerateWave(); } + ImGui::PopID(); } ImGui::EndTable(); } + + + if (ImGui::BeginTable("WGFMWAVE", 2)) { + ImGui::TableSetupColumn("c0", ImGuiTableColumnFlags_WidthFixed, ImGui::CalcTextSize("Op").x); + ImGui::TableSetupColumn("c1", ImGuiTableColumnFlags_WidthStretch, 1); + + ImGui::TableNextRow(ImGuiTableRowFlags_Headers); + ImGui::TableNextColumn(); + ImGui::Text("Op"); + ImGui::TableNextColumn(); + ImGui::Text("Waveform"); + + for (int i = 0; i < 4; i++) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("%d", i + 1); + + ImGui::TableNextColumn(); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); + ImGui::PushID(i); + if (CWSliderInt("##WGWAVEFORM", &fmWaveform[i], 0, _countof(fmWaveforms)-1, fmWaveforms[fmWaveform[i]])) { + doGenerateWave(); + } + ImGui::PopID(); + } + + ImGui::EndTable(); + } + + + CENTER_TEXT("Connection Diagram"); ImGui::Text("Connection Diagram"); - if (ImGui::BeginTable("WGFMCon",5)) { - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text(">>"); - ImGui::TableNextColumn(); - ImGui::Text("2"); - ImGui::TableNextColumn(); - ImGui::Text("3"); - ImGui::TableNextColumn(); - ImGui::Text("4"); - ImGui::TableNextColumn(); - ImGui::Text("Out"); + //if (ImGui::BeginTable("WGFMCon",5)) { + // ImGui::TableNextRow(); + // ImGui::TableNextColumn(); + // ImGui::Text(">>"); + // ImGui::TableNextColumn(); + // ImGui::Text("2"); + // ImGui::TableNextColumn(); + // ImGui::Text("3"); + // ImGui::TableNextColumn(); + // ImGui::Text("4"); + // ImGui::TableNextColumn(); + // ImGui::Text("Out"); - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("1"); - ImGui::TableNextColumn(); - if (ImGui::Checkbox("##Con12",&waveGenFMCon1[0])) { - doGenerateWave(); - } - ImGui::TableNextColumn(); - if (ImGui::Checkbox("##Con13",&waveGenFMCon1[1])) { - doGenerateWave(); - } - ImGui::TableNextColumn(); - if (ImGui::Checkbox("##Con14",&waveGenFMCon1[2])) { - doGenerateWave(); - } - ImGui::TableNextColumn(); - if (ImGui::Checkbox("##Con1O",&waveGenFMCon1[3])) { - doGenerateWave(); - } + // ImGui::TableNextRow(); + // ImGui::TableNextColumn(); + // ImGui::Text("1"); + // ImGui::TableNextColumn(); + // if (ImGui::Checkbox("##Con12",&waveGenFMCon1[0])) { + // doGenerateWave(); + // } + // ImGui::TableNextColumn(); + // if (ImGui::Checkbox("##Con13",&waveGenFMCon1[1])) { + // doGenerateWave(); + // } + // ImGui::TableNextColumn(); + // if (ImGui::Checkbox("##Con14",&waveGenFMCon1[2])) { + // doGenerateWave(); + // } + // ImGui::TableNextColumn(); + // if (ImGui::Checkbox("##Con1O",&waveGenFMCon1[3])) { + // doGenerateWave(); + // } - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("2"); - ImGui::TableNextColumn(); - // blank - ImGui::TableNextColumn(); - if (ImGui::Checkbox("##Con23",&waveGenFMCon2[0])) { - doGenerateWave(); - } - ImGui::TableNextColumn(); - if (ImGui::Checkbox("##Con24",&waveGenFMCon2[1])) { - doGenerateWave(); - } - ImGui::TableNextColumn(); - if (ImGui::Checkbox("##Con2O",&waveGenFMCon2[2])) { - doGenerateWave(); - } + // ImGui::TableNextRow(); + // ImGui::TableNextColumn(); + // ImGui::Text("2"); + // ImGui::TableNextColumn(); + // // blank + // ImGui::TableNextColumn(); + // if (ImGui::Checkbox("##Con23",&waveGenFMCon2[0])) { + // doGenerateWave(); + // } + // ImGui::TableNextColumn(); + // if (ImGui::Checkbox("##Con24",&waveGenFMCon2[1])) { + // doGenerateWave(); + // } + // ImGui::TableNextColumn(); + // if (ImGui::Checkbox("##Con2O",&waveGenFMCon2[2])) { + // doGenerateWave(); + // } - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("3"); - ImGui::TableNextColumn(); - // blank - ImGui::TableNextColumn(); - // blank - ImGui::TableNextColumn(); - if (ImGui::Checkbox("##Con34",&waveGenFMCon3[0])) { - doGenerateWave(); - } - ImGui::TableNextColumn(); - if (ImGui::Checkbox("##Con3O",&waveGenFMCon3[1])) { - doGenerateWave(); - } + // ImGui::TableNextRow(); + // ImGui::TableNextColumn(); + // ImGui::Text("3"); + // ImGui::TableNextColumn(); + // // blank + // ImGui::TableNextColumn(); + // // blank + // ImGui::TableNextColumn(); + // if (ImGui::Checkbox("##Con34",&waveGenFMCon3[0])) { + // doGenerateWave(); + // } + // ImGui::TableNextColumn(); + // if (ImGui::Checkbox("##Con3O",&waveGenFMCon3[1])) { + // doGenerateWave(); + // } - ImGui::EndTable(); + // ImGui::EndTable(); + //} + + + + if (ImGui::BeginTable("WGFMCon", 6)) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text(">>"); + ImGui::TableNextColumn(); + ImGui::Text("1"); + ImGui::TableNextColumn(); + ImGui::Text("2"); + ImGui::TableNextColumn(); + ImGui::Text("3"); + ImGui::TableNextColumn(); + ImGui::Text("4"); + ImGui::TableNextColumn(); + //ImGui::Text("4"); + //ImGui::TableNextColumn(); + ImGui::Text("Out"); + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("1"); + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##ConO1", &waveGenFMCon0[0])) { + doGenerateWave(); + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##ConO2", &waveGenFMCon0[1])) { + doGenerateWave(); + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##ConO3", &waveGenFMCon0[2])) { + doGenerateWave(); + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##ConO4", &waveGenFMCon0[3])) { + doGenerateWave(); + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##ConOO", &waveGenFMCon0[4])) { + doGenerateWave(); + } + + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("2"); + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##Con11", &waveGenFMCon1[0])) { + doGenerateWave(); + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##Con12", &waveGenFMCon1[1])) { + doGenerateWave(); + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##Con13", &waveGenFMCon1[2])) { + doGenerateWave(); + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##Con14", &waveGenFMCon1[3])) { + doGenerateWave(); + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##Con1O", &waveGenFMCon1[4])) { + doGenerateWave(); + } + + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("3"); + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##Con21", &waveGenFMCon2[0])) { + doGenerateWave(); + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##Con22", &waveGenFMCon2[1])) { + doGenerateWave(); + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##Con23", &waveGenFMCon2[2])) { + doGenerateWave(); + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##Con24", &waveGenFMCon2[3])) { + doGenerateWave(); + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##Con2O", &waveGenFMCon2[4])) { + doGenerateWave(); + } + + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("4"); + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##Con31", &waveGenFMCon3[0])) { + doGenerateWave(); + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##Con32", &waveGenFMCon3[1])) { + doGenerateWave(); + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##Con33", &waveGenFMCon3[2])) { + doGenerateWave(); + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##Con34", &waveGenFMCon3[3])) { + doGenerateWave(); + } + ImGui::TableNextColumn(); + if (ImGui::Checkbox("##Con3O", &waveGenFMCon3[4])) { + doGenerateWave(); + } + + ImGui::EndTable(); } + + ImGui::EndTabItem(); } if (ImGui::BeginTabItem("WaveTools")) {