mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-27 06:53:01 +00:00
GUI: wave generator, part 2
This commit is contained in:
parent
7d5f5a91c6
commit
693d457fff
3 changed files with 116 additions and 8 deletions
|
@ -4718,9 +4718,9 @@ FurnaceGUI::FurnaceGUI():
|
|||
#endif
|
||||
hasACED(false),
|
||||
waveGenBaseShape(0),
|
||||
waveGenDuty(0.0f),
|
||||
waveGenPower(0.0f),
|
||||
waveGenInvertPoint(0.0f),
|
||||
waveGenDuty(0.5f),
|
||||
waveGenPower(1),
|
||||
waveGenInvertPoint(1.0f),
|
||||
waveGenFM(false) {
|
||||
// value keys
|
||||
valueKeys[SDLK_0]=0;
|
||||
|
|
|
@ -1468,7 +1468,9 @@ class FurnaceGUI {
|
|||
|
||||
// wave generator
|
||||
int waveGenBaseShape;
|
||||
float waveGenDuty, waveGenPower, waveGenInvertPoint;
|
||||
float waveGenDuty;
|
||||
int waveGenPower;
|
||||
float waveGenInvertPoint;
|
||||
float waveGenAmp[16];
|
||||
float waveGenPhase[16];
|
||||
float waveGenTL[4];
|
||||
|
|
|
@ -39,34 +39,67 @@ void FurnaceGUI::doGenerateWave() {
|
|||
DivWavetable* wave=e->song.wave[curWave];
|
||||
memset(finalResult,0,sizeof(float)*256);
|
||||
|
||||
if (wave->len<2) return;
|
||||
|
||||
if (waveGenFM) {
|
||||
|
||||
} else {
|
||||
switch (waveGenBaseShape) {
|
||||
case 0: // sine
|
||||
for (int i=0; i<wave->len; i++) {
|
||||
finalResult[i]=0.5*(1.0+sin(i*2.0*M_PI/(double)wave->len));
|
||||
for (int j=0; j<16; j++) {
|
||||
float pos=fmod((waveGenPhase[j]*wave->len)+(i*(j+1)),wave->len);
|
||||
float partial=sin((0.5+pos)*2.0*M_PI/(double)wave->len);
|
||||
partial=pow(partial,waveGenPower);
|
||||
partial*=waveGenAmp[j];
|
||||
finalResult[i]+=partial;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1: // triangle
|
||||
for (int i=0; i<wave->len; i++) {
|
||||
finalResult[i]=2.0*(0.5-fabs(0.5-(i/(double)(wave->len-1))));
|
||||
for (int j=0; j<16; j++) {
|
||||
float pos=fmod((waveGenPhase[j]*wave->len)+(i*(j+1)),wave->len);
|
||||
float partial=4.0*(0.5-fabs(0.5-(pos/(double)(wave->len-1))))-1.0;
|
||||
partial=pow(partial,waveGenPower);
|
||||
partial*=waveGenAmp[j];
|
||||
finalResult[i]+=partial;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2: // saw
|
||||
for (int i=0; i<wave->len; i++) {
|
||||
finalResult[i]=i/(double)(wave->len-1);
|
||||
for (int j=0; j<16; j++) {
|
||||
float pos=fmod((waveGenPhase[j]*wave->len)+(i*(j+1)),wave->len);
|
||||
float partial=((2*pos)/(double)(wave->len-1))-1.0;
|
||||
partial=pow(partial,waveGenPower);
|
||||
partial*=waveGenAmp[j];
|
||||
finalResult[i]+=partial;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3: // pulse
|
||||
for (int i=0; i<wave->len; i++) {
|
||||
finalResult[i]=(i>=(wave->len/2))?1:0;
|
||||
for (int j=0; j<16; j++) {
|
||||
float pos=fmod((waveGenPhase[j]*wave->len)+(i*(j+1)),wave->len);
|
||||
float partial=(pos>=(waveGenDuty*wave->len))?1:-1;
|
||||
partial=pow(partial,waveGenPower);
|
||||
partial*=waveGenAmp[j];
|
||||
finalResult[i]+=partial;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=waveGenInvertPoint*wave->len; i<wave->len; i++) {
|
||||
finalResult[i]=-finalResult[i];
|
||||
}
|
||||
|
||||
for (int i=0; i<wave->len; i++) {
|
||||
finalResult[i]=(1.0+finalResult[i])*0.5;
|
||||
if (finalResult[i]<0.0f) finalResult[i]=0.0f;
|
||||
if (finalResult[i]>1.0f) finalResult[i]=1.0f;
|
||||
wave->data[i]=round(finalResult[i]*wave->max);
|
||||
}
|
||||
}
|
||||
|
@ -202,6 +235,79 @@ void FurnaceGUI::drawWaveEdit() {
|
|||
if (waveGenBaseShape>3) waveGenBaseShape=3;
|
||||
doGenerateWave();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTable("WGShapeProps",2)) {
|
||||
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Duty");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (CWSliderFloat("##WGDuty",&waveGenDuty,0.0f,1.0f)) {
|
||||
doGenerateWave();
|
||||
}
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("Exponent");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (CWSliderInt("##WGExp",&waveGenPower,1,8)) {
|
||||
doGenerateWave();
|
||||
}
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("XOR Point");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (CWSliderFloat("##WGXOR",&waveGenInvertPoint,0.0f,1.0f)) {
|
||||
doGenerateWave();
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
if (ImGui::TreeNode("Amplitude/Phase")) {
|
||||
if (ImGui::BeginTable("WGShapeProps",3)) {
|
||||
ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed);
|
||||
ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthStretch,0.6f);
|
||||
ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch,0.4f);
|
||||
|
||||
for (int i=0; i<16; i++) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%d",i+1);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::PushID(140+i);
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (CWSliderFloat("##WGAmp",&waveGenAmp[i],-1.0f,1.0f)) {
|
||||
doGenerateWave();
|
||||
}
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Middle)) {
|
||||
waveGenAmp[i]=0.0f;
|
||||
doGenerateWave();
|
||||
}
|
||||
ImGui::PopID();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::PushID(140+i);
|
||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||
if (CWSliderFloat("##WGPhase",&waveGenPhase[i],0.0f,1.0f)) {
|
||||
doGenerateWave();
|
||||
}
|
||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Middle)) {
|
||||
waveGenPhase[i]=0.0f;
|
||||
doGenerateWave();
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("FM")) {
|
||||
|
|
Loading…
Reference in a new issue