diff --git a/TODO.md b/TODO.md index 0975e2363..02b3990ec 100644 --- a/TODO.md +++ b/TODO.md @@ -20,5 +20,4 @@ - add ability to move selection by dragging - Apply button in settings - find and replace -- finish wave synth - add mono/poly note preview button diff --git a/src/engine/waveSynth.cpp b/src/engine/waveSynth.cpp index ce2e754cf..0dbe852d6 100644 --- a/src/engine/waveSynth.cpp +++ b/src/engine/waveSynth.cpp @@ -29,11 +29,13 @@ bool DivWaveSynth::activeChanged() { return false; } -bool DivWaveSynth::tick() { - if (--subDivCounter>0) return false; - +bool DivWaveSynth::tick(bool skipSubDiv) { bool updated=first; first=false; + if (--subDivCounter>0 && !skipSubDiv) { + return updated; + } + subDivCounter=e->tickMult; if (!state.enabled) return updated; if (width<1) return false; @@ -67,7 +69,7 @@ bool DivWaveSynth::tick() { case DIV_WS_AVERAGE: for (int i=0; i<=state.speed; i++) { int pos1=(pos+1>=width)?0:(pos+1); - output[pos]=(output[pos]*state.param1+output[pos1]*(256-state.param1))>>8; + output[pos]=(128+output[pos]*(256-state.param1)+output[pos1]*state.param1)>>8; if (output[pos]<0) output[pos]=0; if (output[pos]>height) output[pos]=height; if (++pos>=width) pos=0; @@ -157,6 +159,19 @@ bool DivWaveSynth::tick() { updated=true; break; case DIV_WS_SLIDE: + for (int i=0; i<=state.speed; i++) { + int newPos=(pos+stage)%(width*2); + if (newPos>=width) { + output[pos]=wave2[newPos-width]; + } else { + output[pos]=wave1[newPos]; + } + if (++pos>=width) { + pos=0; + if (++stage>=width*2) stage=0; + } + } + updated=true; break; case DIV_WS_MIX: for (int i=0; i<=state.speed; i++) { @@ -170,6 +185,16 @@ bool DivWaveSynth::tick() { updated=true; break; case DIV_WS_PHASE_MOD: + for (int i=0; i<=state.speed; i++) { + int mod=(wave2[pos]*(state.param2-stage))>>8; + output[pos]=wave1[(pos+mod)%width]; + if (++pos>=width) { + pos=0; + stage+=state.param1; + if (stage>state.param2) stage=state.param2; + } + } + updated=true; break; } divCounter=state.rateDivider; @@ -245,11 +270,12 @@ void DivWaveSynth::init(DivInstrument* which, int w, int h, bool insChanged) { pos=0; stage=0; stageDir=false; - divCounter=1+state.rateDivider; + divCounter=0; subDivCounter=0; - first=true; changeWave1(state.wave1); changeWave2(state.wave2); + tick(true); + first=true; } } diff --git a/src/engine/waveSynth.h b/src/engine/waveSynth.h index 29c07e812..8709b0846 100644 --- a/src/engine/waveSynth.h +++ b/src/engine/waveSynth.h @@ -46,7 +46,7 @@ class DivWaveSynth { * tick this DivWaveSynth. * @return whether the wave has changed. */ - bool tick(); + bool tick(bool skipSubDiv=false); /** * set the wave width. * @param value the width. diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index a06335a86..3133b7c6a 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -2825,7 +2825,7 @@ void FurnaceGUI::drawInsEdit() { wavePreview2[i]=wave2->data[i]; } } - if (ins->ws.enabled) wavePreview.tick(); + if (ins->ws.enabled) wavePreview.tick(true); for (int i=0; idata[i]>wavePreviewHeight) { wavePreview3[i]=wavePreviewHeight; @@ -2895,6 +2895,12 @@ void FurnaceGUI::drawInsEdit() { wavePreviewInit=true; } + if (ins->ws.effect==DIV_WS_PHASE_MOD) { + if (ImGui::InputScalar("Power",ImGuiDataType_U8,&ins->ws.param2,&_ONE,&_SEVEN)) { + wavePreviewInit=true; + } + } + if (ImGui::Checkbox("Global",&ins->ws.global)) { wavePreviewInit=true; }