commit b60341887c74ce57b11d3621bc4f2057008fd812
parent b9de1058b50ed44df3b6b8d540f208081ed65776
Author: Matt Demanett <matt@demanett.net>
Date: Thu, 19 Apr 2018 01:20:12 -0400
Oscillator fixes; add FM depth input to XCO.
Diffstat:
13 files changed, 98 insertions(+), 68 deletions(-)
diff --git a/res-src/Additator-src.svg b/res-src/Additator-src.svg
@@ -139,15 +139,15 @@
<symbol id="knobguide-partials" viewBox="0 0 70px 70px">
<g transform="translate(35 35)">
<text font-size="6.0pt" transform="rotate(-240) translate(25.5 0) rotate(240) translate(-2.5 2.5)">1</text>
- <polyline points="0,0 3,0" stroke-width="0.3" stroke="#333" transform="rotate(-210) translate(21 0)" />
- <text font-size="6.0pt" transform="rotate(-180) translate(25 0) rotate(180) translate(-7 2.5)">20</text>
- <polyline points="0,0 3,0" stroke-width="0.3" stroke="#333" transform="rotate(-150) translate(21 0)" />
- <text font-size="6.0pt" transform="rotate(-120) translate(25 0) rotate(120) translate(-7 2.5)">40</text>
- <polyline points="0,0 3,0" stroke-width="0.3" stroke="#333" transform="rotate(-90) translate(21 0)" />
- <text font-size="6.0pt" transform="rotate(-60) translate(25 0) rotate(60) translate(-3 2.5)">60</text>
- <polyline points="0,0 3,0" stroke-width="0.3" stroke="#333" transform="rotate(-30) translate(21 0)" />
- <text font-size="6.0pt" transform="rotate(0) translate(25 0) rotate(0) translate(-2.5 2.5)">80</text>
- <polyline points="0,0 3,0" stroke-width="0.3" stroke="#333" transform="rotate(30) translate(21 0)" />
+ <polyline points="0,0 3,0" stroke-width="0.3" stroke="#333" transform="rotate(-212.73) translate(21 0)" />
+ <text font-size="6.0pt" transform="rotate(-182.42) translate(25 0) rotate(182.42) translate(-7 2.8)">20</text>
+ <polyline points="0,0 3,0" stroke-width="0.3" stroke="#333" transform="rotate(-152.12) translate(21 0)" />
+ <text font-size="6.0pt" transform="rotate(-121.82) translate(25 0) rotate(121.82) translate(-7 2.5)">40</text>
+ <polyline points="0,0 3,0" stroke-width="0.3" stroke="#333" transform="rotate(-91.52) translate(21 0)" />
+ <text font-size="6.0pt" transform="rotate(-61.21) translate(25 0) rotate(61.21) translate(-3 2.5)">60</text>
+ <polyline points="0,0 3,0" stroke-width="0.3" stroke="#333" transform="rotate(-30.91) translate(21 0)" />
+ <text font-size="6.0pt" transform="rotate(-0.61) translate(25 0) rotate(0.61) translate(-2.5 2.8)">80</text>
+ <polyline points="0,0 3,0" stroke-width="0.3" stroke="#333" transform="rotate(29.7) translate(21 0)" />
<text font-size="6.0pt" transform="rotate(60) translate(25.5 0) rotate(-60) translate(-2 2.5)">100</text>
</g>
</symbol>
@@ -277,7 +277,7 @@
<g transform="translate(144 60)">
<!-- <polyline points="0,19 68,19" stroke="#0f0" stroke-width="1" fill="none" /> -->
- <!-- <polyline points="39,-20 39,50" stroke="#0f0" stroke-width="1" fill="none" /> -->
+ <!-- <polyline points="40,-20 40,50" stroke="#0f0" stroke-width="1" fill="none" /> -->
<text font-size="8pt" letter-spacing="2px" transform="translate(4 50) rotate(270)">PARTIALS</text>
<use id="PARTIALS_PARAM" xlink:href="#knob" transform="translate(21 0)" />
<use xlink:href="#knobguide-partials" transform="translate(5 -16)" />
@@ -357,8 +357,8 @@
<g transform="translate(10 0)">
<g transform="translate(3 0)">
- <use id="PITCH_INPUT" xlink:href="#input" transform="translate(3 5)" />
- <text font-size="6pt" letter-spacing="1px" transform="translate(1 40)">V/OCT</text>
+ <use id="SYNC_INPUT" xlink:href="#input" transform="translate(3 5)" />
+ <text font-size="6pt" letter-spacing="1px" transform="translate(3 40)">SYNC</text>
</g>
<g transform="translate(37 0)">
<use id="PARTIALS_INPUT" xlink:href="#input" transform="translate(3 5)" />
@@ -366,7 +366,7 @@
</g>
<g transform="translate(71 0)">
<use id="WIDTH_INPUT" xlink:href="#input" transform="translate(3 5)" />
- <text font-size="6pt" letter-spacing="1px" transform="translate(0 40)">WIDTH</text>
+ <text font-size="6pt" letter-spacing="1px" transform="translate(0.5 40)">WIDTH</text>
</g>
<g transform="translate(105 0)">
<use id="ODD_SKEW_INPUT" xlink:href="#input" transform="translate(3 5)" />
@@ -380,8 +380,8 @@
<g transform="translate(10 44)">
<g transform="translate(3 0)">
- <use id="SYNC_INPUT" xlink:href="#input" transform="translate(3 5)" />
- <text font-size="6pt" letter-spacing="1px" transform="translate(3 40)">SYNC</text>
+ <use id="PITCH_INPUT" xlink:href="#input" transform="translate(3 5)" />
+ <text font-size="6pt" letter-spacing="1px" transform="translate(1 40)">V/OCT</text>
</g>
<g transform="translate(37 0)">
<use id="GAIN_INPUT" xlink:href="#input" transform="translate(3 5)" />
diff --git a/res-src/XCO-src.svg b/res-src/XCO-src.svg
@@ -258,22 +258,28 @@
<g transform="translate(4 0)">
<!-- <polyline points="-50,0 100,0" stroke="#0f0" stroke-width="1" fill="none" transform="translate(0 19)" /> -->
<text font-size="8pt" letter-spacing="2px" transform="translate(9 27) rotate(270)">FM</text>
- <use id="FM_PARAM" xlink:href="#knob" transform="translate(20 0)" />
+ <use id="FM_DEPTH_PARAM" xlink:href="#knob" transform="translate(20 0)" />
</g>
<!-- <rect width="90" height="10" fill="#0f0" transform="translate(0 26)" /> -->
- <g transform="translate(6 52)">
- <g transform="translate(0 0)">
- <!-- <rect width="62" height="47" stroke="#0f0" fill="none" transform="translate(0 0)" /> -->
- <!-- <polyline points="0,23.5 100,23.5" stroke="#0f0" stroke-width="1" fill="none" /> -->
- <!-- <polyline points="15,23.5 15,-123.5" stroke="#0f0" stroke-width="1" fill="none" /> -->
- <rect width="30" height="47" rx="5" fill="#fafafa" />
- <use id="FM_INPUT" xlink:href="#input" transform="translate(3 5)" />
- <text font-size="6pt" letter-spacing="1px" transform="translate(9 40)">FM</text>
+ <g transform="translate(-19 52)">
+ <rect width="71" height="47" rx="5" fill="#fafafa" transform="translate(10 0)" />
+ <g transform="translate(10 0)">
+ <!-- <rect width="30" height="47" rx="5" fill="#fafafa" /> -->
+ <use id="FM_INPUT" xlink:href="#input" transform="translate(7 5)" />
+ <text font-size="6pt" letter-spacing="1px" transform="translate(11 40)">FM</text>
</g>
- <g transform="translate(47 9)">
- <text font-size="5pt" letter-spacing="2px" transform="translate(-1 -1)">EXP</text>
- <use id="FM_TYPE_PARAM" xlink:href="#switch" transform="translate(0 2)" />
- <text font-size="5pt" letter-spacing="2px" transform="translate(0 34)">LIN</text>
+ <g transform="translate(47 0)">
+ <!-- <rect width="30" height="47" rx="5" fill="#fafafa" /> -->
+ <use id="FM_DEPTH_INPUT" xlink:href="#input" transform="translate(3 5)" />
+ <text font-size="6pt" letter-spacing="1px" transform="translate(0 40)">DEPTH</text>
+ </g>
+ <g transform="translate(82 0)">
+ <!-- <rect width="30" height="47" rx="5" fill="#00c" /> -->
+ <g transform="translate(8 9)">
+ <text font-size="5pt" letter-spacing="2px" transform="translate(-1 -1)">EXP</text>
+ <use id="FM_TYPE_PARAM" xlink:href="#switch" transform="translate(0 2)" />
+ <text font-size="5pt" letter-spacing="2px" transform="translate(0 34)">LIN</text>
+ </g>
</g>
</g>
</g>
@@ -282,7 +288,7 @@
<!-- <rect width="90" height="18" fill="#0f0" transform="translate(0 175)" /> -->
<!-- <rect width="90" height="18" fill="#0f0" transform="translate(0 295)" /> -->
- <rect width="191" height="47" rx="5" fill="#bbb" transform="translate(99 313)" />
+ <rect width="193" height="47" rx="5" fill="#bbb" transform="translate(97 313)" />
<g transform="translate(140 30)">
<rect width="30" height="330" rx="5" fill="#fafafa" />
@@ -443,16 +449,16 @@
<!-- <rect width="30" height="10" fill="#0f0" transform="translate(0 303)" /> -->
<g transform="translate(0 313)">
- <rect width="70" height="47" rx="5" fill="#fafafa" transform="translate(10 0)" />
+ <rect width="71" height="47" rx="5" fill="#fafafa" transform="translate(10 0)" />
<g transform="translate(10 0)">
<!-- <rect width="30" height="47" rx="5" fill="#fafafa" /> -->
- <use id="PITCH_INPUT" xlink:href="#input" transform="translate(4 5)" />
- <text font-size="6pt" letter-spacing="1px" transform="translate(2 40)">V/OCT</text>
+ <use id="PITCH_INPUT" xlink:href="#input" transform="translate(7 5)" />
+ <text font-size="6pt" letter-spacing="1px" transform="translate(5 40)">V/OCT</text>
</g>
- <g transform="translate(50 0)">
+ <g transform="translate(47 0)">
<!-- <rect width="30" height="47" rx="5" fill="#fafafa" /> -->
- <use id="SYNC_INPUT" xlink:href="#input" transform="translate(2 5)" />
- <text font-size="6pt" letter-spacing="2px" transform="translate(0 40)">SYNC</text>
+ <use id="SYNC_INPUT" xlink:href="#input" transform="translate(3 5)" />
+ <text font-size="6pt" letter-spacing="1px" transform="translate(3 40)">SYNC</text>
</g>
<g transform="translate(100 0)">
<!-- <rect width="30" height="47" rx="5" fill="#bbb" transform="translate(0 0)" /> -->
diff --git a/res/Additator.svg b/res/Additator.svg
Binary files differ.
diff --git a/res/XCO.svg b/res/XCO.svg
Binary files differ.
diff --git a/res/knob_38px.svg b/res/knob_38px.svg
Binary files differ.
diff --git a/src/Additator.cpp b/src/Additator.cpp
@@ -178,9 +178,13 @@ struct AdditatorWidget : ModuleWidget {
// end generated by svg_widgets.rb
addParam(ParamWidget::create<Knob68>(frequencyParamPosition, module, Additator::FREQUENCY_PARAM, -3.0, 6.0, 0.0));
- addParam(ParamWidget::create<Knob38>(partialsParamPosition, module, Additator::PARTIALS_PARAM, 1.0, module->maxPartials, module->maxPartials / 10.0f));
+ {
+ auto w = ParamWidget::create<Knob38>(partialsParamPosition, module, Additator::PARTIALS_PARAM, 1.0, module->maxPartials, module->maxPartials / 5.0);
+ dynamic_cast<Knob*>(w)->snap = true;
+ addParam(w);
+ }
addParam(ParamWidget::create<Knob16>(fineParamPosition, module, Additator::FINE_PARAM, -1.0, 1.0, 0.0));
- addParam(ParamWidget::create<Knob26>(widthParamPosition, module, Additator::WIDTH_PARAM, 0.0, module->maxWidth, module->maxWidth / 2.0f));
+ addParam(ParamWidget::create<Knob26>(widthParamPosition, module, Additator::WIDTH_PARAM, 0.0, module->maxWidth, module->maxWidth / 2.0));
addParam(ParamWidget::create<Knob26>(oddSkewParamPosition, module, Additator::ODD_SKEW_PARAM, -module->maxSkew, module->maxSkew, 0.0));
addParam(ParamWidget::create<Knob26>(evenSkewParamPosition, module, Additator::EVEN_SKEW_PARAM, -module->maxSkew, module->maxSkew, 0.0));
addParam(ParamWidget::create<Knob26>(
@@ -189,7 +193,7 @@ struct AdditatorWidget : ModuleWidget {
Additator::GAIN_PARAM,
module->minAmplitudeNormalization,
module->maxAmplitudeNormalization,
- (module->maxAmplitudeNormalization - module->minAmplitudeNormalization) / 2.0f + module->minAmplitudeNormalization
+ (module->maxAmplitudeNormalization - module->minAmplitudeNormalization) / 2.0 + module->minAmplitudeNormalization
));
addParam(ParamWidget::create<Knob26>(
decayParamPosition,
@@ -197,7 +201,7 @@ struct AdditatorWidget : ModuleWidget {
Additator::DECAY_PARAM,
module->minDecay,
module->maxDecay,
- (module->maxDecay - module->minDecay) / 2.0f + module->minDecay
+ (module->maxDecay - module->minDecay) / 2.0 + module->minDecay
));
addParam(ParamWidget::create<Knob26>(balanceParamPosition, module, Additator::BALANCE_PARAM, -1.0, 1.0, 0.0));
addParam(ParamWidget::create<Knob26>(
@@ -206,7 +210,7 @@ struct AdditatorWidget : ModuleWidget {
Additator::FILTER_PARAM,
module->minFilter,
module->maxFilter,
- (module->maxFilter - module->minFilter) / 2.0f + module->minFilter
+ (module->maxFilter - module->minFilter) / 2.0 + module->minFilter
));
addParam(ParamWidget::create<StatefulButton9>(phaseParamPosition, module, Additator::PHASE_PARAM, 1.0, 2.0, 1.0));
diff --git a/src/Additator.hpp b/src/Additator.hpp
@@ -82,7 +82,10 @@ struct Additator : Module {
SineBankOscillator _oscillator;
SchmittTrigger _syncTrigger;
- Additator() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
+ Additator()
+ : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS)
+ , _oscillator(1000.0f, 100.0f, maxPartials)
+ {
onReset();
onSampleRateChange();
}
diff --git a/src/EightFO.cpp b/src/EightFO.cpp
@@ -58,6 +58,7 @@ void EightFO::step() {
pw = (pw + 1.0f) / 2.0f;
pw *= 1.0f - 2.0f * _square.minPulseWidth;
_square.setPulseWidth(pw);
+ _sampleSteps = 1;
}
else {
float sample = abs(params[SAMPLE_PWM_PARAM].value);
@@ -66,6 +67,7 @@ void EightFO::step() {
}
float maxSampleSteps = (_phasor._sampleRate / _phasor._frequency) / 4.0f;
_sampleSteps = clamp((int)(sample * maxSampleSteps), 1, (int)maxSampleSteps);
+ _square.setPulseWidth(SquareOscillator::defaultPulseWidth);
}
_offset = params[OFFSET_PARAM].value;
@@ -93,11 +95,15 @@ void EightFO::step() {
}
_phasor.advancePhase();
- bool useSample = true;
- ++_sampleStep;
- if (_sampleStep >= _sampleSteps) {
- _sampleStep = 0;
- useSample = false;
+ bool useSample = false;
+ if (_sampleSteps > 1) {
+ ++_sampleStep;
+ if (_sampleStep >= _sampleSteps) {
+ _sampleStep = 0;
+ }
+ else {
+ useSample = true;
+ }
}
updateOutput(useSample, outputs[PHASE7_OUTPUT], _phase7Offset, _phase7Sample, _phase7Active);
updateOutput(useSample, outputs[PHASE6_OUTPUT], _phase6Offset, _phase6Sample, _phase6Active);
@@ -223,7 +229,7 @@ struct EightFOWidget : ModuleWidget {
k->snap = true;
k->minAngle = 0.0;
k->maxAngle = M_PI;
- k->speed = 2.0;
+ k->speed = 3.0;
addParam(w);
}
addParam(ParamWidget::create<StatefulButton9>(slowParamPosition, module, EightFO::SLOW_PARAM, 0.0, 1.0, 0.0));
diff --git a/src/FMOp.cpp b/src/FMOp.cpp
@@ -107,7 +107,7 @@ void FMOp::step() {
float offset = 0.0f;
if (feedback > 0.001f) {
- offset = feedback * _feedbackDelayedSample;
+ offset = feedback * 2.0f * _feedbackDelayedSample;
}
if (inputs[FM_INPUT].active) {
offset += inputs[FM_INPUT].value * _depth * 2.0f;
diff --git a/src/LFO.cpp b/src/LFO.cpp
@@ -78,17 +78,21 @@ void LFO::step() {
}
_phasor.advancePhase();
- bool useSample = true;
- ++_sampleStep;
- if (_sampleStep >= _sampleSteps) {
- _sampleStep = 0;
- useSample = false;
+ bool useSample = false;
+ if (_sampleSteps > 1) {
+ ++_sampleStep;
+ if (_sampleStep >= _sampleSteps) {
+ _sampleStep = 0;
+ }
+ else {
+ useSample = true;
+ }
}
updateOutput(_sine, useSample, false, outputs[SINE_OUTPUT], _sineSample, _sineActive);
updateOutput(_triangle, useSample, false, outputs[TRIANGLE_OUTPUT], _triangleSample, _triangleActive);
updateOutput(_ramp, useSample, false, outputs[RAMP_UP_OUTPUT], _rampUpSample, _rampUpActive);
updateOutput(_ramp, useSample, true, outputs[RAMP_DOWN_OUTPUT], _rampDownSample, _rampDownActive);
- updateOutput(_square, useSample, false, outputs[SQUARE_OUTPUT], _squareSample, _squareActive);
+ updateOutput(_square, false, false, outputs[SQUARE_OUTPUT], _squareSample, _squareActive);
}
void LFO::updateOutput(Phasor& wave, bool useSample, bool invert, Output& output, float& sample, bool& active) {
@@ -97,7 +101,7 @@ void LFO::updateOutput(Phasor& wave, bool useSample, bool invert, Output& output
output.value = sample;
}
else {
- sample = wave.nextFromPhasor(_phasor) * amplitude * _scale + _offset;
+ sample = wave.nextFromPhasor(_phasor) * amplitude * _scale + (invert ? -_offset : _offset);
if (invert) {
sample = -sample;
}
diff --git a/src/XCO.cpp b/src/XCO.cpp
@@ -70,7 +70,10 @@ void XCO::step() {
_sineFeedback *= clamp(inputs[SINE_FEEDBACK_INPUT].value / 10.0f, 0.0f, 1.0f);
}
- _fmDepth = params[FM_PARAM].value;
+ _fmDepth = params[FM_DEPTH_PARAM].value;
+ if (inputs[FM_DEPTH_INPUT].active) {
+ _fmDepth *= clamp(inputs[FM_DEPTH_INPUT].value / 10.0f, 0.0f, 1.0f);
+ }
_squarePhaseOffset = phaseOffset(params[SQUARE_PHASE_PARAM], inputs[SQUARE_PHASE_INPUT]);
_sawPhaseOffset = phaseOffset(params[SAW_PHASE_PARAM], inputs[SAW_PHASE_INPUT]);
@@ -170,23 +173,23 @@ void XCO::step() {
}
if (squareNormal) {
- squareOut += mix * amplitude * _squareMix * _square.nextFromPhasor(_phasor, _squarePhaseOffset + phaseOffset);
+ squareOut += mix * amplitude * _square.nextFromPhasor(_phasor, _squarePhaseOffset + phaseOffset);
}
if (sawNormal) {
- sawOut += mix * amplitude * _sawMix * _saw.nextFromPhasor(_phasor, _sawPhaseOffset + phaseOffset);
+ sawOut += mix * amplitude * _saw.nextFromPhasor(_phasor, _sawPhaseOffset + phaseOffset);
}
if (triangleNormal) {
- triangleOut += mix * amplitude * _triangleMix * _triangle.nextFromPhasor(_phasor, _trianglePhaseOffset + phaseOffset);
+ triangleOut += mix * amplitude * _triangle.nextFromPhasor(_phasor, _trianglePhaseOffset + phaseOffset);
}
if (sineNormal) {
- sineOut += amplitude * _sineMix * _sine.nextFromPhasor(_phasor, sineFeedbackOffset + _sinePhaseOffset + phaseOffset);
+ sineOut += amplitude * _sine.nextFromPhasor(_phasor, sineFeedbackOffset + _sinePhaseOffset + phaseOffset);
}
outputs[SQUARE_OUTPUT].value = squareOut;
outputs[SAW_OUTPUT].value = sawOut;
outputs[TRIANGLE_OUTPUT].value = triangleOut;
outputs[SINE_OUTPUT].value = _sineFeedbackDelayedSample = sineOut;
- outputs[MIX_OUTPUT].value = squareOut + sawOut + triangleOut + sineOut;
+ outputs[MIX_OUTPUT].value = _squareMix * squareOut + _sawMix * sawOut + _triangleMix * triangleOut + _sineMix * sineOut;
}
Phasor::phase_delta_t XCO::phaseOffset(Param& param, Input& input) {
@@ -246,7 +249,7 @@ struct XCOWidget : ModuleWidget {
auto fineParamPosition = Vec(47.0, 153.0);
auto slowParamPosition = Vec(121.0, 157.2);
auto fmParamPosition = Vec(55.0, 194.0);
- auto fmTypeParamPosition = Vec(83.5, 256.5);
+ auto fmTypeParamPosition = Vec(101.5, 256.5);
auto squarePwParamPosition = Vec(147.0, 60.0);
auto squarePhaseParamPosition = Vec(147.0, 148.0);
auto squareMixParamPosition = Vec(147.0, 237.0);
@@ -260,7 +263,8 @@ struct XCOWidget : ModuleWidget {
auto sinePhaseParamPosition = Vec(267.0, 148.0);
auto sineMixParamPosition = Vec(267.0, 237.0);
- auto fmInputPosition = Vec(40.0, 251.0);
+ auto fmInputPosition = Vec(29.0, 251.0);
+ auto fmDepthInputPosition = Vec(62.0, 251.0);
auto squarePwInputPosition = Vec(143.0, 95.0);
auto squarePhaseInputPosition = Vec(143.0, 183.0);
auto squareMixInputPosition = Vec(143.0, 272.0);
@@ -273,8 +277,8 @@ struct XCOWidget : ModuleWidget {
auto sineFeedbackInputPosition = Vec(263.0, 95.0);
auto sinePhaseInputPosition = Vec(263.0, 183.0);
auto sineMixInputPosition = Vec(263.0, 272.0);
- auto pitchInputPosition = Vec(14.0, 318.0);
- auto syncInputPosition = Vec(52.0, 318.0);
+ auto pitchInputPosition = Vec(17.0, 318.0);
+ auto syncInputPosition = Vec(50.0, 318.0);
auto squareOutputPosition = Vec(143.0, 318.0);
auto sawOutputPosition = Vec(183.0, 318.0);
@@ -288,7 +292,7 @@ struct XCOWidget : ModuleWidget {
addParam(ParamWidget::create<Knob68>(frequencyParamPosition, module, XCO::FREQUENCY_PARAM, -3.0, 6.0, 0.0));
addParam(ParamWidget::create<Knob16>(fineParamPosition, module, XCO::FINE_PARAM, -1.0, 1.0, 0.0));
addParam(ParamWidget::create<StatefulButton9>(slowParamPosition, module, XCO::SLOW_PARAM, 0.0, 1.0, 0.0));
- addParam(ParamWidget::create<Knob38>(fmParamPosition, module, XCO::FM_PARAM, 0.0, 1.0, 0.0));
+ addParam(ParamWidget::create<Knob38>(fmParamPosition, module, XCO::FM_DEPTH_PARAM, 0.0, 1.0, 0.0));
addParam(ParamWidget::create<SliderSwitch2State14>(fmTypeParamPosition, module, XCO::FM_TYPE_PARAM, 0.0, 1.0, 1.0));
addParam(ParamWidget::create<Knob16>(squarePwParamPosition, module, XCO::SQUARE_PW_PARAM, -0.97, 0.97, 0.0));
addParam(ParamWidget::create<Knob16>(squarePhaseParamPosition, module, XCO::SQUARE_PHASE_PARAM, -1.0, 1.0, 0.0));
@@ -304,6 +308,7 @@ struct XCOWidget : ModuleWidget {
addParam(ParamWidget::create<Knob16>(sineMixParamPosition, module, XCO::SINE_MIX_PARAM, 0.0, 1.0, 1.0));
addInput(Port::create<Port24>(fmInputPosition, Port::INPUT, module, XCO::FM_INPUT));
+ addInput(Port::create<Port24>(fmDepthInputPosition, Port::INPUT, module, XCO::FM_DEPTH_INPUT));
addInput(Port::create<Port24>(squarePwInputPosition, Port::INPUT, module, XCO::SQUARE_PW_INPUT));
addInput(Port::create<Port24>(squarePhaseInputPosition, Port::INPUT, module, XCO::SQUARE_PHASE_INPUT));
addInput(Port::create<Port24>(squareMixInputPosition, Port::INPUT, module, XCO::SQUARE_MIX_INPUT));
diff --git a/src/XCO.hpp b/src/XCO.hpp
@@ -15,7 +15,7 @@ struct XCO : Module {
FREQUENCY_PARAM,
FINE_PARAM,
SLOW_PARAM,
- FM_PARAM,
+ FM_DEPTH_PARAM,
FM_TYPE_PARAM,
SQUARE_PW_PARAM,
SQUARE_PHASE_PARAM,
@@ -34,6 +34,7 @@ struct XCO : Module {
enum InputsIds {
FM_INPUT,
+ FM_DEPTH_INPUT,
SQUARE_PW_INPUT,
SQUARE_PHASE_INPUT,
SQUARE_MIX_INPUT,
diff --git a/src/dsp/oscillator.hpp b/src/dsp/oscillator.hpp
@@ -216,8 +216,9 @@ struct BandLimitedSawOscillator : SaturatingSawOscillator {
struct SquareOscillator : Phasor {
const float minPulseWidth = 0.03f;
const float maxPulseWidth = 1.0f - minPulseWidth;
+ static constexpr float defaultPulseWidth = 0.5f;
float _pulseWidthInput;
- phase_t _pulseWidth = maxPhase / 2;
+ phase_t _pulseWidth = maxPhase * defaultPulseWidth;
bool positive = true;
SquareOscillator(