Browse Source

Merge branch 'v2-redesign' of github.com:VCVRack/Fundamental into v2-redesign

tags/v2.0.1
Andrew Belt 3 years ago
parent
commit
a34cea5cbe
9 changed files with 1354 additions and 2914 deletions
  1. +905
    -2472
      res/Random.svg
  2. +200
    -199
      res/Viz.svg
  3. +6
    -49
      src/LFO.cpp
  4. +97
    -18
      src/Random.cpp
  5. +6
    -5
      src/SEQ3.cpp
  6. +28
    -30
      src/Scope.cpp
  7. +41
    -38
      src/Viz.cpp
  8. +67
    -101
      src/WTLFO.cpp
  9. +4
    -2
      src/Wavetable.hpp

+ 905
- 2472
res/Random.svg
File diff suppressed because it is too large
View File


+ 200
- 199
res/Viz.svg View File

@@ -1,6 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->

<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
@@ -9,243 +7,246 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="15.239719mm"
height="128.49931mm"
viewBox="0 0 15.23972 128.49931"
width="45"
height="380"
viewBox="0 0 45 380"
version="1.1"
id="svg55291"
inkscape:version="0.92.4 5da689c313, 2019-01-14"
sodipodi:docname="Viz.svg">
<defs
id="defs55285" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="-61.964416"
inkscape:cy="199.87911"
inkscape:document-units="mm"
inkscape:current-layer="layer3"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:snap-bbox="true"
inkscape:snap-bbox-midpoints="true"
inkscape:snap-nodes="false"
inkscape:window-width="1600"
inkscape:window-height="882"
inkscape:window-x="0"
inkscape:window-y="18"
inkscape:window-maximized="0"
inkscape:snap-page="true"
inkscape:bbox-nodes="true" />
id="svg154"
sodipodi:docname="VIZ.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)">
<metadata
id="metadata55288">
id="metadata158">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="716"
inkscape:window-height="480"
id="namedview156"
showgrid="false"
inkscape:zoom="0.62105263"
inkscape:cx="22.5"
inkscape:cy="190"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg154" />
<defs
id="defs7">
<linearGradient
id="a7c85910-efa2-49be-b51d-63d3f80a4577"
x1="22.5"
x2="22.5"
y2="380"
gradientUnits="userSpaceOnUse">
<stop
offset="0"
stop-color="#ebebeb"
id="stop2" />
<stop
offset="1"
stop-color="#e1e1e1"
id="stop4" />
</linearGradient>
</defs>
<g
inkscape:label="Layer 1"
id="b13fbb94-2523-43f1-8b7b-76c02900e16c"
data-name="FND BG">
<rect
width="45"
height="380"
fill="url(#a7c85910-efa2-49be-b51d-63d3f80a4577)"
id="rect9" />
</g>
<g
id="b87e7f95-1233-4dde-a5c0-e29fb2f84614"
data-name="FND GRAPH">
<g
id="g20">
<circle
cx="23.00165"
cy="355.83101"
r="1.18571"
fill="#1f1f1f"
id="circle12" />
<path
d="M14.35927,359.753a.91214.91214,0,0,1-.8158-.50418l-2.96428-5.92857a.91209.91209,0,0,1,1.6316-.8158l2.14848,4.297,2.14848-4.297a.91209.91209,0,0,1,1.6316.8158l-2.96428,5.92857A.91211.91211,0,0,1,14.35927,359.753Z"
fill="#1f1f1f"
id="path14" />
<path
d="M30.64073,359.753a.91211.91211,0,0,1-.8158-.50418l-2.96428-5.92857a.91209.91209,0,0,1,1.6316-.8158l2.14848,4.297,2.14848-4.297a.91209.91209,0,0,1,1.6316.8158l-2.96428,5.92857A.91214.91214,0,0,1,30.64073,359.753Z"
fill="#1f1f1f"
id="path16" />
<path
d="M22.94242,359.753a3.87637,3.87637,0,1,1,2.32653-6.97719.91209.91209,0,1,1-1.09557,1.45854,2.034,2.034,0,0,0-1.231-.40991,2.0522,2.0522,0,1,0,0,4.10439,2.034,2.034,0,0,0,1.231-.40991.91209.91209,0,1,1,1.09557,1.45854A3.8448,3.8448,0,0,1,22.94242,359.753Z"
fill="#1f1f1f"
id="path18" />
</g>
</g>
<g
id="b148c7a9-98ae-44fd-9639-16f535c2406c"
data-name="FND TXT">
<g
id="g31">
<path
d="M13.52246,314.58691a.41321.41321,0,0,1,.41992-.41992h1.4502a1.5914,1.5914,0,0,1,1.80176,1.58545v.01318c0,1.064-.85352,1.61915-1.89649,1.61915h-.94238v1.1455a.41652.41652,0,0,1-.833,0Zm1.80176,2.0459c.63086,0,1.02344-.35205,1.02344-.84668v-.01367c0-.55566-.39942-.84668-1.02344-.84668h-.96875v1.707Z"
fill="#1f1f1f"
id="path23" />
<path
d="M18.06348,316.55176v-.01367a2.47974,2.47974,0,0,1,4.959-.01368v.01368a2.47973,2.47973,0,0,1-4.959.01367Zm4.085,0v-.01367a1.624,1.624,0,0,0-1.61231-1.68653,1.60217,1.60217,0,0,0-1.59863,1.67285v.01368a1.61919,1.61919,0,0,0,1.6123,1.68017A1.5965,1.5965,0,0,0,22.14844,316.55176Z"
fill="#1f1f1f"
id="path25" />
<path
d="M24.24023,314.54639a.41652.41652,0,0,1,.833,0v3.604H27.2207a.3794.3794,0,1,1,0,.75879H24.66016a.41322.41322,0,0,1-.41993-.41992Z"
fill="#1f1f1f"
id="path27" />
<path
d="M29.31152,317.06641l-1.63281-2.24219a.51886.51886,0,0,1-.09473-.29151.40608.40608,0,0,1,.41993-.3999.48091.48091,0,0,1,.40722.251l1.32032,1.90381,1.34179-1.91065a.47823.47823,0,0,1,.39942-.25049.39566.39566,0,0,1,.40722.40625.50945.50945,0,0,1-.11523.29834l-1.61914,2.21534v1.48388a.417.417,0,0,1-.834,0Z"
fill="#1f1f1f"
id="path29" />
</g>
<g
id="g39">
<path
d="M14.93555,27.66064,12.0957,20.86621a1.19766,1.19766,0,0,1-.11328-.46289.94554.94554,0,0,1,.96387-.95068,1.00032,1.00032,0,0,1,.97559.67529l2.19042,5.668,2.21387-5.73047a.99864.99864,0,0,1,.92578-.61279.92914.92914,0,0,1,.95117.92578,1.12318,1.12318,0,0,1-.0996.42529l-2.86524,6.85693a1.13167,1.13167,0,0,1-1.08887.76319h-.125A1.13165,1.13165,0,0,1,14.93555,27.66064Z"
id="path33" />
<path
d="M21.64355,20.416a.96338.96338,0,1,1,1.92676,0v6.98144a.96338.96338,0,1,1-1.92676,0Z"
id="path35" />
<path
d="M25.30469,27.43555v-.03809a1.35575,1.35575,0,0,1,.35058-.90039l4.542-5.28027H26.30566a.84906.84906,0,0,1-.85058-.83838.86.86,0,0,1,.85058-.85108h5.59278a.86018.86018,0,0,1,.85156.85108v.0376a1.38072,1.38072,0,0,1-.35059.90087l-4.542,5.27979h4.041a.86017.86017,0,0,1,.85156.85107.84928.84928,0,0,1-.85156.83838H26.15625A.86039.86039,0,0,1,25.30469,27.43555Z"
id="path37" />
</g>
</g>
<g
id="b7f3c585-bc80-4700-89be-f9c3dbe33dbd"
data-name="components"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-56.676971,-41.503207)">
style="display:none">
<circle
id="b316d787-fbe9-48b7-af86-7b559295a9a0"
data-name="Poly#PJ301MPort"
cx="22.500031"
cy="334"
r="5"
style="fill:#00ff00" />
<rect
id="ec9dac3c-8600-4714-ac89-1ca8235b202d"
data-name="Screen"
x="0.0094299996"
y="38.5"
width="44.99057"
height="263.81198"
style="fill:#ffff00" />
<path
id="a738cb83-2bec-4c75-ad4b-f3faa67405e3"
data-name="Viz01#RedLight"
d="m 32.06413,50.35079 a 2.9572,2.9572 0 1 0 2.95678,2.95761 2.95726,2.95726 0 0 0 -2.95678,-2.95761"
inkscape:connector-curvature="0"
style="fill:#e6e6e6;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277778"
d="M 56.769292,41.596914 H 71.82299 V 169.91019 H 56.769292 Z m 0,0"
id="path29725" />
style="fill:#ff00ff" />
<path
id="be0c28f2-d866-4418-8214-6c352f6b1a6d"
data-name="Viz02#RedLight"
d="M 32.06413,65.993 A 2.9572,2.9572 0 1 0 35.02091,68.95061 2.95726,2.95726 0 0 0 32.06413,65.993"
inkscape:connector-curvature="0"
style="fill:#ababab;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277778"
d="M 71.91669,41.503207 H 56.676971 V 170.00252 H 71.91669 Z M 71.72929,169.81649 H 56.863026 V 41.69062 H 71.72929 Z m 0,0"
id="path29727" />
style="fill:#ff00ff" />
<path
id="e85e0c58-aa6b-4289-af1c-3011309e1e2d"
data-name="Viz03#RedLight"
d="m 32.06413,81.63517 a 2.9572,2.9572 0 1 0 2.95678,2.95761 2.95725,2.95725 0 0 0 -2.95678,-2.95761"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277778"
d="M 71.91669,158.86384 H 56.676971 V 70.738287 H 71.91669 Z m 0,0"
id="path41613" />
style="fill:#ff00ff" />
<path
id="bd060286-7cf5-4364-a6f0-f97535566d3b"
data-name="Viz04#RedLight"
d="m 32.06413,97.27736 a 2.9572,2.9572 0 1 0 2.95678,2.95761 2.95725,2.95725 0 0 0 -2.95678,-2.95761"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277778"
d="m 61.03021,56.442517 c 0,0.08268 0.0662,0.148827 0.15434,0.148827 0.0827,0 0.14884,-0.06615 0.14884,-0.148827 v -0.418923 h 0.34724 c 0.38037,0 0.68904,-0.203952 0.68904,-0.589803 v -0.0055 c 0,-0.347267 -0.25357,-0.578778 -0.65595,-0.578778 h -0.52917 c -0.0882,0 -0.15434,0.06615 -0.15434,0.154341 z m 0.30318,-0.694531 v -0.617361 h 0.35278 c 0.23149,0 0.37483,0.104729 0.37483,0.30868 0,0.1819 -0.14334,0.308681 -0.37483,0.308681 z m 0,0"
id="path52181" />
style="fill:#ff00ff" />
<path
id="a2a5d779-761f-40c8-8b34-165ba96232ef"
data-name="Viz05#RedLight"
d="m 32.06413,112.91955 a 2.9572,2.9572 0 1 0 2.95678,2.95761 2.95725,2.95725 0 0 0 -2.95678,-2.95761"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277778"
d="m 63.58436,56.607882 c 0.52917,0 0.90399,-0.4079 0.90399,-0.892969 v -0.0055 c 0,-0.48507 -0.36928,-0.887455 -0.89845,-0.887455 -0.52917,0 -0.90953,0.407899 -0.90953,0.892969 v 0.0055 c 0,0.485069 0.37482,0.887458 0.90399,0.887458 z m 0.006,-0.281122 c -0.341771,0 -0.58981,-0.275607 -0.58981,-0.611847 v -0.0055 c 0,-0.33624 0.24253,-0.606337 0.58427,-0.606337 0.34177,0 0.58981,0.275608 0.58981,0.611851 v 0.0055 c 0,0.336243 -0.24254,0.606337 -0.58427,0.606337 z m 0,0"
id="path52177" />
style="fill:#ff00ff" />
<path
id="f1d5e052-5737-49c1-b5d8-86c945792406"
data-name="Viz06#RedLight"
d="m 32.06413,128.56173 a 2.9572,2.9572 0 1 0 2.95678,2.95762 2.95727,2.95727 0 0 0 -2.95678,-2.95762"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277778"
d="m 64.92781,56.425979 c 0,0.0882 0.0661,0.15434 0.15434,0.15434 h 0.93154 c 0.0772,0 0.14334,-0.06063 0.14334,-0.137802 0,-0.07717 -0.0662,-0.137805 -0.14334,-0.137805 h -0.7827 v -1.317403 c 0,-0.08268 -0.0662,-0.14883 -0.14884,-0.14883 -0.0882,0 -0.15434,0.06615 -0.15434,0.14883 z m 0,0"
id="path52173" />
style="fill:#ff00ff" />
<path
id="b1d22013-9978-4d5e-b9ab-b78b3ef18f74"
data-name="Viz07#RedLight"
d="m 32.06413,144.20392 a 2.9572,2.9572 0 1 0 2.95678,2.95762 2.95727,2.95727 0 0 0 -2.95678,-2.95762"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277778"
d="m 66.77524,56.442517 c 0,0.08268 0.0661,0.148827 0.14883,0.148827 0.0882,0 0.15434,-0.06615 0.15434,-0.148827 v -0.540191 l 0.58981,-0.810288 c 0.0219,-0.02755 0.0386,-0.06615 0.0386,-0.104729 0,-0.08268 -0.0551,-0.14883 -0.1488,-0.14883 -0.0606,0 -0.10474,0.03306 -0.14333,0.08819 l -0.49058,0.700046 -0.47956,-0.694532 c -0.0386,-0.05512 -0.0827,-0.09371 -0.14884,-0.09371 -0.0882,0 -0.15434,0.06615 -0.15434,0.14883 0,0.03858 0.0166,0.07166 0.0386,0.104729 l 0.59532,0.815799 z m 0,0"
id="path52169" />
style="fill:#ff00ff" />
<path
id="b4aa208f-29f3-4f29-8b76-cf6911e754e7"
data-name="Viz08#RedLight"
d="m 32.06413,159.84611 a 2.9572,2.9572 0 1 0 2.95678,2.95762 2.95727,2.95727 0 0 0 -2.95678,-2.95762"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277778"
d="m 62.10576,51.11244 h 0.0441 c 0.17639,0 0.29764,-0.09371 0.36378,-0.253559 l 0.97014,-2.320616 c 0.0166,-0.03858 0.0332,-0.09371 0.0332,-0.143316 0,-0.181901 -0.14333,-0.314193 -0.31972,-0.314193 -0.15434,0 -0.27008,0.09922 -0.31418,0.20395 l -0.74965,1.940278 -0.73865,-1.91823 c -0.0496,-0.132291 -0.15984,-0.225998 -0.33073,-0.225998 -0.18189,0 -0.32519,0.137804 -0.32519,0.319705 0,0.05512 0.0166,0.104731 0.0386,0.159852 l 0.95913,2.298568 c 0.0662,0.159853 0.19293,0.253559 0.36932,0.253559 z m 0,0"
id="path52149" />
style="fill:#ff00ff" />
<path
id="fb234c65-d014-4d90-b008-a118c103c162"
data-name="Viz09#RedLight"
d="m 32.06413,175.4883 a 2.9572,2.9572 0 1 0 2.95678,2.95762 2.95727,2.95727 0 0 0 -2.95678,-2.95762"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277778"
d="m 64.00674,50.765175 c 0,0.181901 0.14333,0.330729 0.32523,0.330729 0.18189,0 0.32522,-0.148828 0.32522,-0.330729 v -2.359202 c 0,-0.181901 -0.14333,-0.325217 -0.32522,-0.325217 -0.1819,0 -0.32523,0.143316 -0.32523,0.325217 z m 0,0"
id="path52153" />
style="fill:#ff00ff" />
<path
id="bcc91c36-0d79-434c-8b71-a61a285ec8b2"
data-name="Viz10#RedLight"
d="m 32.06413,191.13049 a 2.9572,2.9572 0 1 0 2.95678,2.95761 2.95726,2.95726 0 0 0 -2.95678,-2.95761"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.35277778"
d="m 65.53363,51.068343 h 1.94579 c 0.15434,0 0.28663,-0.12678 0.28663,-0.28112 0,-0.159852 -0.13229,-0.292144 -0.28663,-0.292144 H 66.1069 l 1.5379,-1.785938 c 0.0771,-0.09371 0.12125,-0.187413 0.12125,-0.303168 v -0.01103 c 0,-0.159853 -0.13229,-0.292144 -0.28663,-0.292144 h -1.89619 c -0.15433,0 -0.28663,0.132291 -0.28663,0.292144 0,0.15434 0.1323,0.28112 0.28663,0.28112 h 1.31742 L 65.36275,50.462 c -0.0772,0.08819 -0.11575,0.192926 -0.11575,0.303169 v 0.01653 c 0,0.15434 0.13229,0.286632 0.28663,0.286632 z m 0,0"
id="path52145" />
style="fill:#ff00ff" />
<path
id="ff26f033-6c49-4097-9c80-513ecb0d37ae"
data-name="Viz11#RedLight"
d="m 32.06413,206.77268 a 2.9572,2.9572 0 1 0 2.95678,2.95761 2.95726,2.95726 0 0 0 -2.95678,-2.95761"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277778"
d="m 64.86667,161.97821 c 0,0.22048 -0.17917,0.401 -0.40104,0.401 -0.22048,0 -0.401,-0.18052 -0.401,-0.401 0,-0.22187 0.18052,-0.40101 0.401,-0.40101 0.22187,0 0.40104,0.17914 0.40104,0.40101"
id="path41767" />
style="fill:#ff00ff" />
<path
id="b167d49e-5d45-4a75-9619-ee0b949dffba"
data-name="Viz12#RedLight"
d="m 32.06413,222.41487 a 2.9572,2.9572 0 1 0 2.95678,2.95761 2.95726,2.95726 0 0 0 -2.95678,-2.95761"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277778"
d="m 61.54421,163.30388 c -0.11712,0 -0.22461,-0.0661 -0.277,-0.17088 l -1.00182,-2.00367 c -0.0758,-0.15296 -0.0152,-0.33762 0.1378,-0.41478 0.15296,-0.0758 0.3376,-0.0138 0.41342,0.1378 l 0.7276,1.45383 0.72623,-1.45383 c 0.0758,-0.15159 0.26046,-0.2136 0.41342,-0.1378 0.15293,0.0772 0.21357,0.26182 0.13779,0.41478 L 61.8198,163.133 c -0.0524,0.10473 -0.15984,0.17088 -0.27559,0.17088"
id="path41769" />
style="fill:#ff00ff" />
<path
id="e7e19aaa-128a-408c-b3e8-326320883bbd"
data-name="Viz13#RedLight"
d="m 32.06413,238.05706 a 2.9572,2.9572 0 1 0 2.95678,2.95761 2.95725,2.95725 0 0 0 -2.95678,-2.95761"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277778"
d="m 67.04948,163.30388 c -0.11715,0 -0.22327,-0.0661 -0.27562,-0.17088 l -1.00319,-2.00367 c -0.0758,-0.15296 -0.0138,-0.33762 0.13779,-0.41478 0.15296,-0.0758 0.33761,-0.0138 0.4148,0.1378 l 0.72622,1.45383 0.7262,-1.45383 c 0.0758,-0.15159 0.26183,-0.2136 0.41342,-0.1378 0.15296,0.0772 0.21498,0.26182 0.13921,0.41478 l -1.00324,2.00367 c -0.0524,0.10473 -0.15846,0.17088 -0.27559,0.17088"
id="path41771" />
style="fill:#ff00ff" />
<path
id="b0b208d4-3cbd-4123-a6cd-a37202080f38"
data-name="Viz14#RedLight"
d="m 32.06413,253.69925 a 2.9572,2.9572 0 1 0 2.95678,2.95761 2.95725,2.95725 0 0 0 -2.95678,-2.95761"
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35277778"
d="m 64.44634,163.30388 c -0.72344,0 -1.3105,-0.58843 -1.3105,-1.31052 0,-0.72347 0.58706,-1.31051 1.3105,-1.31051 0.28663,0 0.55813,0.0909 0.78687,0.26183 0.13504,0.10197 0.16263,0.29627 0.0606,0.43132 -0.10199,0.13643 -0.29489,0.16399 -0.43134,0.062 -0.12125,-0.0909 -0.26458,-0.13918 -0.41617,-0.13918 -0.38308,0 -0.69452,0.31144 -0.69452,0.69453 0,0.3831 0.31144,0.69316 0.69452,0.69316 0.15159,0 0.29492,-0.0469 0.41617,-0.13781 0.13645,-0.10197 0.32935,-0.0758 0.43134,0.0606 0.10199,0.13642 0.0744,0.33073 -0.0606,0.4327 -0.22874,0.17088 -0.50024,0.26183 -0.78687,0.26183"
id="path41773" />
</g>
<g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="widgets"
style="display:none">
<rect
style="opacity:1;vector-effect:none;fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.64763796;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="rect61217"
width="15.239719"
height="88.125549"
x="0"
y="29.235081" />
<circle
style="opacity:1;vector-effect:none;fill:#00ff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="path61183"
cx="7.619174"
cy="21.3465"
r="1" />
<circle
r="1"
cy="33.626202"
cx="10.854124"
id="circle61185"
style="opacity:1;vector-effect:none;fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<circle
style="opacity:1;vector-effect:none;fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="circle61187"
cx="10.854124"
cy="38.916489"
r="1" />
<circle
style="opacity:1;vector-effect:none;fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="circle61189"
cx="10.854124"
cy="44.205402"
r="1" />
<circle
r="1"
cy="49.495689"
cx="10.854124"
id="circle61191"
style="opacity:1;vector-effect:none;fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<circle
style="opacity:1;vector-effect:none;fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="circle61193"
cx="10.854124"
cy="54.784603"
r="1" />
<circle
r="1"
cy="60.07489"
cx="10.854124"
id="circle61195"
style="opacity:1;vector-effect:none;fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<circle
r="1"
cy="65.3638"
cx="10.854124"
id="circle61197"
style="opacity:1;vector-effect:none;fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<circle
style="opacity:1;vector-effect:none;fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="circle61199"
cx="10.854124"
cy="70.654091"
r="1" />
<circle
style="opacity:1;vector-effect:none;fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="circle61201"
cx="10.854124"
cy="75.943008"
r="1" />
<circle
r="1"
cy="81.233292"
cx="10.854124"
id="circle61203"
style="opacity:1;vector-effect:none;fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<circle
r="1"
cy="86.522209"
cx="10.854124"
id="circle61205"
style="opacity:1;vector-effect:none;fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<circle
style="opacity:1;vector-effect:none;fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="circle61207"
cx="10.854124"
cy="91.812492"
r="1" />
<circle
r="1"
cy="97.10141"
cx="10.854124"
id="circle61209"
style="opacity:1;vector-effect:none;fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<circle
style="opacity:1;vector-effect:none;fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="circle61211"
cx="10.854124"
cy="102.39169"
r="1" />
<circle
style="opacity:1;vector-effect:none;fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
id="circle61213"
cx="10.854124"
cy="107.6806"
r="1" />
<circle
r="1"
cy="112.97089"
cx="10.854124"
id="circle61215"
style="opacity:1;vector-effect:none;fill:#ff00ff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.69999999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
style="fill:#ff00ff" />
<path
id="f363b55a-6ce5-48f0-b481-c589380adc0c"
data-name="Viz15#RedLight"
d="m 32.06413,269.34143 a 2.9572,2.9572 0 1 0 2.95678,2.95762 2.95727,2.95727 0 0 0 -2.95678,-2.95762"
inkscape:connector-curvature="0"
style="fill:#ff00ff" />
<path
id="fd7b9cfd-8efe-4008-a366-7629c9ec33ee"
data-name="Viz16#RedLight"
d="m 32.06413,284.98362 a 2.9572,2.9572 0 1 0 2.95678,2.95762 2.95727,2.95727 0 0 0 -2.95678,-2.95762"
inkscape:connector-curvature="0"
style="fill:#ff00ff" />
</g>
</svg>

+ 6
- 49
src/LFO.cpp View File

@@ -48,14 +48,12 @@ struct LFO : Module {
float clockFreq = 1.f;
dsp::Timer clockTimer;

dsp::BooleanTrigger offsetTrigger;
dsp::BooleanTrigger invertTrigger;
dsp::ClockDivider lightDivider;

LFO() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
configButton(OFFSET_PARAM, "Offset 0-10V");
configButton(INVERT_PARAM, "Invert");
configSwitch(OFFSET_PARAM, 0.f, 1.f, 0.f, "Offset", {"Bipolar", "Unipolar"});
configSwitch(INVERT_PARAM, 0.f, 1.f, 0.f, "Invert");

struct FrequencyQuantity : ParamQuantity {
float getDisplayValue() override {
@@ -95,8 +93,6 @@ struct LFO : Module {
}

void onReset() override {
offset = false;
invert = false;
for (int c = 0; c < 16; c += 4) {
phases[c / 4] = 0.f;
}
@@ -109,14 +105,8 @@ struct LFO : Module {
float fmParam = params[FM_PARAM].getValue();
float pwParam = params[PW_PARAM].getValue();
float pwmParam = params[PWM_PARAM].getValue();

// Buttons
if (offsetTrigger.process(params[OFFSET_PARAM].getValue() > 0.f)) {
offset ^= true;
}
if (invertTrigger.process(params[INVERT_PARAM].getValue() > 0.f)) {
invert ^= true;
}
bool offset = params[OFFSET_PARAM].getValue() > 0.f;
bool invert = params[INVERT_PARAM].getValue() > 0.f;

// Clock
if (inputs[CLOCK_INPUT].isConnected()) {
@@ -227,39 +217,6 @@ struct LFO : Module {
lights[INVERT_LIGHT].setBrightness(invert);
}
}

json_t* dataToJson() override {
json_t* rootJ = json_object();
// offset
json_object_set_new(rootJ, "offset", json_boolean(offset));
// invert
json_object_set_new(rootJ, "invert", json_boolean(invert));
return rootJ;
}

void dataFromJson(json_t* rootJ) override {
// offset
json_t* offsetJ = json_object_get(rootJ, "offset");
if (offsetJ)
offset = json_boolean_value(offsetJ);
// invert
json_t* invertJ = json_object_get(rootJ, "invert");
if (invertJ)
invert = json_boolean_value(invertJ);
}

void paramsFromJson(json_t* rootJ) override {
Module::paramsFromJson(rootJ);
// In <2.0, OFFSET_PARAM and INVERT_PARAM were toggle switches instead of momentary buttons, so if params are on after deserializing, set boolean states instead.
if (params[OFFSET_PARAM].getValue() > 0.f) {
offset = true;
params[OFFSET_PARAM].setValue(0.f);
}
if (params[INVERT_PARAM].getValue() > 0.f) {
invert = true;
params[INVERT_PARAM].setValue(0.f);
}
}
};


@@ -276,8 +233,8 @@ struct LFOWidget : ModuleWidget {
addParam(createParamCentered<RoundHugeBlackKnob>(mm2px(Vec(22.902, 29.803)), module, LFO::FREQ_PARAM));
addParam(createParamCentered<RoundLargeBlackKnob>(mm2px(Vec(22.861, 56.388)), module, LFO::PW_PARAM));
addParam(createParamCentered<Trimpot>(mm2px(Vec(6.604, 80.603)), module, LFO::FM_PARAM));
addParam(createLightParamCentered<LEDLightButton<MediumSimpleLight<YellowLight>>>(mm2px(Vec(17.441, 80.603)), module, LFO::INVERT_PARAM, LFO::INVERT_LIGHT));
addParam(createLightParamCentered<LEDLightButton<MediumSimpleLight<YellowLight>>>(mm2px(Vec(28.279, 80.603)), module, LFO::OFFSET_PARAM, LFO::OFFSET_LIGHT));
addParam(createLightParamCentered<LEDLightLatch<MediumSimpleLight<WhiteLight>>>(mm2px(Vec(17.441, 80.603)), module, LFO::INVERT_PARAM, LFO::INVERT_LIGHT));
addParam(createLightParamCentered<LEDLightLatch<MediumSimpleLight<WhiteLight>>>(mm2px(Vec(28.279, 80.603)), module, LFO::OFFSET_PARAM, LFO::OFFSET_LIGHT));
addParam(createParamCentered<Trimpot>(mm2px(Vec(39.116, 80.603)), module, LFO::PWM_PARAM));

addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.604, 96.859)), module, LFO::FM_INPUT));


+ 97
- 18
src/Random.cpp View File

@@ -7,6 +7,13 @@ struct Random : Module {
SHAPE_PARAM,
OFFSET_PARAM,
MODE_PARAM,
// new in 2.0
PROB_PARAM, // TODO
RANDOM_PARAM, // TODO
RATE_CV_PARAM,
SHAPE_CV_PARAM,
PROB_CV_PARAM,
RANDOM_CV_PARAM,
NUM_PARAMS
};
enum InputIds {
@@ -14,6 +21,9 @@ struct Random : Module {
SHAPE_INPUT,
TRIGGER_INPUT,
EXTERNAL_INPUT,
// new in 2.0
PROB_INPUT,
RANDOM_INPUT,
NUM_INPUTS
};
enum OutputIds {
@@ -21,35 +31,64 @@ struct Random : Module {
LINEAR_OUTPUT,
SMOOTH_OUTPUT,
EXPONENTIAL_OUTPUT,
// new in 2.0
GATE_OUTPUT, // TODO
NUM_OUTPUTS
};
enum LightIds {
RATE_LIGHT,
SHAPE_LIGHT,
PROB_LIGHT,
RANDOM_LIGHT,
OFFSET_LIGHT,
NUM_LIGHTS
};

dsp::SchmittTrigger trigTrigger;
dsp::BooleanTrigger offsetTrigger;
float lastValue = 0.f;
float value = 0.f;
float clockPhase = 0.f;
int trigFrame = 0;
int lastTrigFrames = INT_MAX;
bool offset = false;

Random() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
configParam(RATE_PARAM, std::log2(0.002f), std::log2(2000.f), std::log2(2.f), "Rate", " Hz", 2);
configParam(SHAPE_PARAM, 0.f, 1.f, 0.5f, "Shape", "%", 0, 100);
configSwitch(OFFSET_PARAM, 0.f, 1.f, 1.f, "Offset", {"Bipolar", "Unipolar"});
configSwitch(MODE_PARAM, 0.f, 1.f, 1.f, "Randomness mode", {"Relative", "Absolute"});
configParam(SHAPE_PARAM, 0.f, 1.f, 1.f, "Shape", "%", 0, 100);
configParam(PROB_PARAM, 0.f, 1.f, 1.f, "Probability", "%", 0, 100);
configParam(RANDOM_PARAM, 0.f, 1.f, 1.f, "Randomness", "%", 0, 100);

configParam(RATE_CV_PARAM, -1.f, 1.f, 0.f, "Rate CV", "%", 0, 100);
getParamQuantity(RATE_CV_PARAM)->randomizeEnabled = false;
configParam(SHAPE_CV_PARAM, -1.f, 1.f, 0.f, "Shape CV", "%", 0, 100);
getParamQuantity(SHAPE_CV_PARAM)->randomizeEnabled = false;
configParam(PROB_CV_PARAM, -1.f, 1.f, 0.f, "Probability CV", "%", 0, 100);
getParamQuantity(PROB_CV_PARAM)->randomizeEnabled = false;
configParam(RANDOM_CV_PARAM, -1.f, 1.f, 0.f, "Randomness CV", "%", 0, 100);
getParamQuantity(RANDOM_CV_PARAM)->randomizeEnabled = false;

configButton(OFFSET_PARAM, "Offset 0-10V");

configInput(RATE_INPUT, "Rate");
configInput(SHAPE_INPUT, "Shape");
configInput(PROB_INPUT, "Probability");
configInput(RANDOM_INPUT, "Randomness");
configInput(TRIGGER_INPUT, "Trigger");
configInput(EXTERNAL_INPUT, "External");

configOutput(STEPPED_OUTPUT, "Stepped");
configOutput(LINEAR_OUTPUT, "Linear");
configOutput(SMOOTH_OUTPUT, "Smooth");
configOutput(EXPONENTIAL_OUTPUT, "Exponential");
configOutput(GATE_OUTPUT, "Gate");

onReset();
}

void onReset() override {
offset = false;
}

void trigger() {
@@ -87,6 +126,10 @@ struct Random : Module {
}

void process(const ProcessArgs& args) override {
if (offsetTrigger.process(params[OFFSET_PARAM].getValue() > 0.f)) {
offset ^= true;
}

if (inputs[TRIGGER_INPUT].isConnected()) {
// Advance clock phase based on tempo estimate
trigFrame++;
@@ -104,7 +147,7 @@ struct Random : Module {
else {
// Advance clock phase by rate
float rate = params[RATE_PARAM].getValue();
rate += inputs[RATE_PARAM].getVoltage();
rate += inputs[RATE_PARAM].getVoltage() * params[RATE_CV_PARAM].getValue();
float clockFreq = std::pow(2.f, rate);
float deltaPhase = std::fmin(clockFreq * args.sampleTime, 0.5f);
clockPhase += deltaPhase;
@@ -115,10 +158,9 @@ struct Random : Module {
}
}


// Shape
float shape = params[SHAPE_PARAM].getValue();
shape += inputs[SHAPE_INPUT].getVoltage() / 10.f;
shape += inputs[SHAPE_INPUT].getVoltage() / 10.f * params[SHAPE_CV_PARAM].getValue();
shape = clamp(shape, 0.f, 1.f);

// Stepped
@@ -178,6 +220,35 @@ struct Random : Module {
// Lights
lights[RATE_LIGHT].setSmoothBrightness(0.f, args.sampleTime);
lights[SHAPE_LIGHT].setBrightness(shape);
lights[OFFSET_LIGHT].setBrightness(offset);
}

void paramsFromJson(json_t* rootJ) override {
// In <2.0, there were no attenuverters, so set them to 1.0 in case they are not overwritten.
params[RATE_CV_PARAM].setValue(1.f);
params[SHAPE_CV_PARAM].setValue(1.f);
params[PROB_CV_PARAM].setValue(1.f);
params[RANDOM_CV_PARAM].setValue(1.f);
Module::paramsFromJson(rootJ);
// In <2.0, OFFSET_PARAM was a toggle switch instead of a momentary button, so if param is on after deserializing, set boolean states instead.
if (params[OFFSET_PARAM].getValue() > 0.f) {
offset = true;
params[OFFSET_PARAM].setValue(0.f);
}
}

json_t* dataToJson() override {
json_t* rootJ = json_object();
// offset
json_object_set_new(rootJ, "offset", json_boolean(offset));
return rootJ;
}

void dataFromJson(json_t* rootJ) override {
// offset
json_t* offsetJ = json_object_get(rootJ, "offset");
if (offsetJ)
offset = json_boolean_value(offsetJ);
}
};

@@ -192,20 +263,28 @@ struct RandomWidget : ModuleWidget {
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));

addParam(createLightParamCentered<LEDLightSlider<GreenLight>>(mm2px(Vec(7.215, 30.858)), module, Random::RATE_PARAM, Random::RATE_LIGHT));
addParam(createLightParamCentered<LEDLightSlider<GreenLight>>(mm2px(Vec(18.214, 30.858)), module, Random::SHAPE_PARAM, Random::SHAPE_LIGHT));
addParam(createParamCentered<CKSS>(mm2px(Vec(7.214, 78.259)), module, Random::OFFSET_PARAM));
addParam(createParamCentered<CKSS>(mm2px(Vec(18.214, 78.259)), module, Random::MODE_PARAM));
addParam(createLightParamCentered<LEDLightSlider<GreenLight>>(mm2px(Vec(6.479, 33.605)), module, Random::RATE_PARAM, Random::RATE_LIGHT));
addParam(createLightParamCentered<LEDLightSlider<GreenLight>>(mm2px(Vec(17.315, 33.605)), module, Random::PROB_PARAM, Random::PROB_LIGHT));
addParam(createLightParamCentered<LEDLightSlider<GreenLight>>(mm2px(Vec(28.152, 33.605)), module, Random::RANDOM_PARAM, Random::RANDOM_LIGHT));
addParam(createLightParamCentered<LEDLightSlider<GreenLight>>(mm2px(Vec(38.98, 33.605)), module, Random::SHAPE_PARAM, Random::SHAPE_LIGHT));
addParam(createParamCentered<Trimpot>(mm2px(Vec(6.479, 64.347)), module, Random::RATE_CV_PARAM));
addParam(createParamCentered<Trimpot>(mm2px(Vec(17.317, 64.347)), module, Random::PROB_CV_PARAM));
addParam(createParamCentered<Trimpot>(mm2px(Vec(28.154, 64.347)), module, Random::RANDOM_CV_PARAM));
addParam(createParamCentered<Trimpot>(mm2px(Vec(38.991, 64.347)), module, Random::SHAPE_CV_PARAM));
addParam(createLightParamCentered<LEDLightButton<MediumSimpleLight<YellowLight>>>(mm2px(Vec(28.154, 96.859)), module, Random::OFFSET_PARAM, Random::OFFSET_LIGHT));

addInput(createInputCentered<PJ301MPort>(mm2px(Vec(7.214, 50.726)), module, Random::RATE_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(18.214, 50.726)), module, Random::SHAPE_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(7.214, 64.513)), module, Random::TRIGGER_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(18.214, 64.513)), module, Random::EXTERNAL_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.479, 80.549)), module, Random::RATE_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(17.317, 80.549)), module, Random::PROB_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(28.154, 80.553)), module, Random::RANDOM_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(38.991, 80.557)), module, Random::SHAPE_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.479, 96.859)), module, Random::TRIGGER_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(17.317, 96.859)), module, Random::EXTERNAL_INPUT));

addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(7.214, 96.727)), module, Random::STEPPED_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(18.214, 96.727)), module, Random::LINEAR_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(7.214, 112.182)), module, Random::SMOOTH_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(18.214, 112.182)), module, Random::EXPONENTIAL_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(38.991, 96.859)), module, Random::GATE_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(6.479, 113.115)), module, Random::STEPPED_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(17.317, 113.115)), module, Random::LINEAR_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(28.154, 113.115)), module, Random::EXPONENTIAL_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(38.991, 113.115)), module, Random::SMOOTH_OUTPUT));
}
};



+ 6
- 5
src/SEQ3.cpp View File

@@ -50,11 +50,9 @@ struct SEQ3 : Module {
dsp::BooleanTrigger gateTriggers[8];

dsp::SchmittTrigger clockTrigger;
dsp::SchmittTrigger runTrigger;
dsp::SchmittTrigger resetTrigger;

dsp::PulseGenerator clockPulse;
dsp::PulseGenerator runPulse;
dsp::PulseGenerator resetPulse;

/** Phase of internal LFO */
@@ -147,9 +145,12 @@ struct SEQ3 : Module {
void process(const ProcessArgs& args) override {
// Run
// Use bitwise OR "|" to always evaluate both expressions
if (runButtonTrigger.process(params[RUN_PARAM].getValue()) | runTrigger.process(inputs[RUN_INPUT].getVoltage(), 0.1f, 2.f)) {
if (runButtonTrigger.process(params[RUN_PARAM].getValue())) {
running ^= true;
runPulse.trigger(1e-3f);
}
// Run input overrides button
if (inputs[RUN_INPUT].isConnected()) {
running = (inputs[RUN_INPUT].getVoltage() >= 2.f);
}

// Reset
@@ -218,7 +219,7 @@ struct SEQ3 : Module {

outputs[STEPS_OUTPUT].setVoltage((numSteps - 1) * 1.f);
outputs[CLOCK_OUTPUT].setVoltage(clockGate ? 10.f : 0.f);
outputs[RUN_OUTPUT].setVoltage(runPulse.process(args.sampleTime) ? 10.f : 0.f);
outputs[RUN_OUTPUT].setVoltage(running ? 10.f : 0.f);
outputs[RESET_OUTPUT].setVoltage(resetGate ? 10.f : 0.f);

lights[CLOCK_LIGHT].setSmoothBrightness(clockGate, args.sampleTime);


+ 28
- 30
src/Scope.cpp View File

@@ -24,6 +24,9 @@ struct Scope : Module {
NUM_INPUTS
};
enum OutputIds {
// new in 2.0
X_OUTPUT,
Y_OUTPUT,
NUM_OUTPUTS
};
enum LightIds {
@@ -353,36 +356,31 @@ struct ScopeWidget : ModuleWidget {
setModule(module);
setPanel(createPanel(asset::plugin(pluginInstance, "res/Scope.svg")));

addChild(createWidget<ScrewSilver>(Vec(15, 0)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 30, 0)));
addChild(createWidget<ScrewSilver>(Vec(15, 365)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 30, 365)));

{
ScopeDisplay* display = new ScopeDisplay();
display->module = module;
display->box.pos = Vec(0, 44);
display->box.size = Vec(box.size.x, 140);
addChild(display);
}

addParam(createParam<RoundBlackSnapKnob>(Vec(15, 209), module, Scope::X_SCALE_PARAM));
addParam(createParam<RoundBlackKnob>(Vec(15, 263), module, Scope::X_POS_PARAM));
addParam(createParam<RoundBlackSnapKnob>(Vec(61, 209), module, Scope::Y_SCALE_PARAM));
addParam(createParam<RoundBlackKnob>(Vec(61, 263), module, Scope::Y_POS_PARAM));
addParam(createParam<RoundBlackKnob>(Vec(107, 209), module, Scope::TIME_PARAM));
addParam(createParam<CKD6>(Vec(106, 262), module, Scope::LISSAJOUS_PARAM));
addParam(createParam<RoundBlackKnob>(Vec(153, 209), module, Scope::TRIG_PARAM));
addParam(createParam<CKD6>(Vec(152, 262), module, Scope::EXTERNAL_PARAM));

addInput(createInput<PJ301MPort>(Vec(17, 319), module, Scope::X_INPUT));
addInput(createInput<PJ301MPort>(Vec(63, 319), module, Scope::Y_INPUT));
addInput(createInput<PJ301MPort>(Vec(154, 319), module, Scope::TRIG_INPUT));

addChild(createLight<SmallLight<GreenLight>>(Vec(104, 251), module, Scope::PLOT_LIGHT));
addChild(createLight<SmallLight<GreenLight>>(Vec(104, 296), module, Scope::LISSAJOUS_LIGHT));
addChild(createLight<SmallLight<GreenLight>>(Vec(150, 251), module, Scope::INTERNAL_LIGHT));
addChild(createLight<SmallLight<GreenLight>>(Vec(150, 296), module, Scope::EXTERNAL_LIGHT));
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));

// addParam(createParamCentered<LEDButton>(mm2px(Vec(8.643, 80.603)), module, Scope::_1X2_PARAM));
addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(24.897, 80.551)), module, Scope::X_SCALE_PARAM));
addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(41.147, 80.551)), module, Scope::Y_SCALE_PARAM));
// addParam(createParamCentered<LEDButton>(mm2px(Vec(57.397, 80.521)), module, Scope::TRIG_PARAM));
addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(8.643, 96.819)), module, Scope::TIME_PARAM));
addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(24.897, 96.789)), module, Scope::X_POS_PARAM));
addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(41.147, 96.815)), module, Scope::Y_POS_PARAM));
// addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(57.397, 96.815)), module, Scope::THERS_PARAM));

addInput(createInputCentered<PJ301MPort>(mm2px(Vec(8.643, 113.115)), module, Scope::X_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(33.023, 113.115)), module, Scope::Y_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(57.397, 113.115)), module, Scope::TRIG_INPUT));

addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(20.833, 113.115)), module, Scope::X_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(45.212, 113.115)), module, Scope::Y_OUTPUT));

ScopeDisplay* display = createWidget<ScopeDisplay>(Vec(0, 44));
display->box.size = Vec(box.size.x, 140);
display->module = module;
addChild(display);
}
};



+ 41
- 38
src/Viz.cpp View File

@@ -44,28 +44,30 @@ struct Viz : Module {

struct VizDisplay : Widget {
Viz* module;
std::shared_ptr<Font> font;

VizDisplay() {
box.size = mm2px(Vec(15.24, 88.126));
font = APP->window->loadFont(asset::plugin(pluginInstance, "res/nunito/Nunito-Bold.ttf"));
}

void draw(const DrawArgs& args) override {
for (int c = 0; c < 16; c++) {
Vec p = Vec(15, 16 + (float) c / 16 * (box.size.y - 10));
std::string text = string::f("%d", c + 1);

nvgFontFaceId(args.vg, font->handle);
nvgFontSize(args.vg, 11);
nvgTextLetterSpacing(args.vg, 0.0);
nvgTextAlign(args.vg, NVG_ALIGN_CENTER | NVG_ALIGN_BASELINE);
if (module && c < module->lastChannel)
nvgFillColor(args.vg, nvgRGB(255, 255, 255));
else
nvgFillColor(args.vg, nvgRGB(99, 99, 99));
nvgText(args.vg, p.x, p.y, text.c_str(), NULL);
void drawLayer(const DrawArgs& args, int layer) override {
if (layer == 1) {
for (int c = 0; c < 16; c++) {
Vec p = Vec(15, 16 + (float) c / 16 * (box.size.y - 10));
std::string text = string::f("%d", c + 1);
std::shared_ptr<Font> font = APP->window->loadFont(asset::plugin(pluginInstance, "res/nunito/Nunito-Bold.ttf"));

nvgFontFaceId(args.vg, font->handle);
nvgFontSize(args.vg, 11);
nvgTextLetterSpacing(args.vg, 0.0);
nvgTextAlign(args.vg, NVG_ALIGN_CENTER | NVG_ALIGN_BASELINE);
if (module && c < module->lastChannel)
nvgFillColor(args.vg, nvgRGB(255, 255, 255));
else
nvgFillColor(args.vg, nvgRGB(99, 99, 99));
nvgText(args.vg, p.x, p.y, text.c_str(), NULL);
}
}
Widget::drawLayer(args, layer);
}
};

@@ -80,28 +82,29 @@ struct VizWidget : ModuleWidget {
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));

addInput(createInputCentered<PJ301MPort>(mm2px(Vec(7.619, 21.346)), module, Viz::POLY_INPUT));

addChild(createLightCentered<SmallLight<GreenRedLight>>(mm2px(Vec(10.854, 33.626)), module, Viz::VU_LIGHTS + 0 * 2));
addChild(createLightCentered<SmallLight<GreenRedLight>>(mm2px(Vec(10.854, 38.916)), module, Viz::VU_LIGHTS + 1 * 2));
addChild(createLightCentered<SmallLight<GreenRedLight>>(mm2px(Vec(10.854, 44.205)), module, Viz::VU_LIGHTS + 2 * 2));
addChild(createLightCentered<SmallLight<GreenRedLight>>(mm2px(Vec(10.854, 49.496)), module, Viz::VU_LIGHTS + 3 * 2));
addChild(createLightCentered<SmallLight<GreenRedLight>>(mm2px(Vec(10.854, 54.785)), module, Viz::VU_LIGHTS + 4 * 2));
addChild(createLightCentered<SmallLight<GreenRedLight>>(mm2px(Vec(10.854, 60.075)), module, Viz::VU_LIGHTS + 5 * 2));
addChild(createLightCentered<SmallLight<GreenRedLight>>(mm2px(Vec(10.854, 65.364)), module, Viz::VU_LIGHTS + 6 * 2));
addChild(createLightCentered<SmallLight<GreenRedLight>>(mm2px(Vec(10.854, 70.654)), module, Viz::VU_LIGHTS + 7 * 2));
addChild(createLightCentered<SmallLight<GreenRedLight>>(mm2px(Vec(10.854, 75.943)), module, Viz::VU_LIGHTS + 8 * 2));
addChild(createLightCentered<SmallLight<GreenRedLight>>(mm2px(Vec(10.854, 81.233)), module, Viz::VU_LIGHTS + 9 * 2));
addChild(createLightCentered<SmallLight<GreenRedLight>>(mm2px(Vec(10.854, 86.522)), module, Viz::VU_LIGHTS + 10 * 2));
addChild(createLightCentered<SmallLight<GreenRedLight>>(mm2px(Vec(10.854, 91.812)), module, Viz::VU_LIGHTS + 11 * 2));
addChild(createLightCentered<SmallLight<GreenRedLight>>(mm2px(Vec(10.854, 97.101)), module, Viz::VU_LIGHTS + 12 * 2));
addChild(createLightCentered<SmallLight<GreenRedLight>>(mm2px(Vec(10.854, 102.392)), module, Viz::VU_LIGHTS + 13 * 2));
addChild(createLightCentered<SmallLight<GreenRedLight>>(mm2px(Vec(10.854, 107.681)), module, Viz::VU_LIGHTS + 14 * 2));
addChild(createLightCentered<SmallLight<GreenRedLight>>(mm2px(Vec(10.854, 112.971)), module, Viz::VU_LIGHTS + 15 * 2));

VizDisplay* vizDisplay = createWidget<VizDisplay>(mm2px(Vec(0.0, 29.235)));
vizDisplay->module = module;
addChild(vizDisplay);
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(2.58, 7.229)), module, Viz::POLY_INPUT));

addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(3.676, 11.388)), module, Viz::VU_LIGHTS + 0 * 2));
addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(3.676, 13.18)), module, Viz::VU_LIGHTS + 1 * 2));
addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(3.676, 14.971)), module, Viz::VU_LIGHTS + 2 * 2));
addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(3.676, 16.763)), module, Viz::VU_LIGHTS + 3 * 2));
addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(3.676, 18.554)), module, Viz::VU_LIGHTS + 4 * 2));
addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(3.676, 20.345)), module, Viz::VU_LIGHTS + 5 * 2));
addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(3.676, 22.137)), module, Viz::VU_LIGHTS + 6 * 2));
addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(3.676, 23.928)), module, Viz::VU_LIGHTS + 7 * 2));
addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(3.676, 25.719)), module, Viz::VU_LIGHTS + 8 * 2));
addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(3.676, 27.511)), module, Viz::VU_LIGHTS + 9 * 2));
addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(3.676, 29.302)), module, Viz::VU_LIGHTS + 10 * 2));
addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(3.676, 31.094)), module, Viz::VU_LIGHTS + 11 * 2));
addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(3.676, 32.885)), module, Viz::VU_LIGHTS + 12 * 2));
addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(3.676, 34.677)), module, Viz::VU_LIGHTS + 13 * 2));
addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(3.676, 36.468)), module, Viz::VU_LIGHTS + 14 * 2));
addChild(createLightCentered<SmallSimpleLight<GreenRedLight>>(mm2px(Vec(3.676, 38.259)), module, Viz::VU_LIGHTS + 15 * 2));

VizDisplay* display = createWidget<VizDisplay>(mm2px(Vec(0.0, 9.901)));
display->box.size = mm2px(Vec(5.161, 29.845));
display->module = module;
addChild(display);
}
};



+ 67
- 101
src/WTLFO.cpp View File

@@ -36,8 +36,6 @@ struct WTLFO : Module {
};

Wavetable wavetable;
bool offset = false;
bool invert = false;

float_4 phases[4] = {};
float lastPos = 0.f;
@@ -52,9 +50,8 @@ struct WTLFO : Module {

WTLFO() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
// TODO Change to momentary with backward compatibility in fromJson()
configButton(OFFSET_PARAM, "Offset 0-10V");
configButton(INVERT_PARAM, "Invert wave");
configSwitch(OFFSET_PARAM, 0.f, 1.f, 0.f, "Offset", {"Bipolar", "Unipolar"});
configSwitch(INVERT_PARAM, 0.f, 1.f, 0.f, "Invert");

struct FrequencyQuantity : ParamQuantity {
float getDisplayValue() override {
@@ -88,8 +85,6 @@ struct WTLFO : Module {
}

void onReset() override {
offset = false;
invert = false;
wavetable.reset();

// Reset state
@@ -100,12 +95,6 @@ struct WTLFO : Module {
clockTimer.reset();
}

void onRandomize(const RandomizeEvent& e) override {
Module::onRandomize(e);
offset = random::get<bool>();
invert = random::get<bool>();
}

void onAdd(const AddEvent& e) override {
std::string path = system::join(getPatchStorageDirectory(), "wavetable.wav");
// Silently fails
@@ -119,19 +108,9 @@ struct WTLFO : Module {
}
}

void clearOutput() {
outputs[WAVE_OUTPUT].setVoltage(0.f);
outputs[WAVE_OUTPUT].setChannels(1);
lights[PHASE_LIGHT + 0].setBrightness(0.f);
lights[PHASE_LIGHT + 1].setBrightness(0.f);
lights[PHASE_LIGHT + 2].setBrightness(0.f);
}

void process(const ProcessArgs& args) override {
if (offsetTrigger.process(params[OFFSET_PARAM].getValue() > 0.f))
offset ^= true;
if (invertTrigger.process(params[INVERT_PARAM].getValue() > 0.f))
invert ^= true;
bool offset = (params[OFFSET_PARAM].getValue() > 0.f);
bool invert = (params[INVERT_PARAM].getValue() > 0.f);

int channels = std::max(1, inputs[FM_INPUT].getChannels());

@@ -158,72 +137,71 @@ struct WTLFO : Module {
float posCvParam = params[POS_CV_PARAM].getValue();

// Check valid wave and wavetable size
if (wavetable.waveLen < 2) {
clearOutput();
return;
}
int waveCount = wavetable.getWaveCount();
if (waveCount < 1) {
clearOutput();
return;
}
// Iterate channels
for (int c = 0; c < channels; c += 4) {
// Calculate frequency in Hz
float_4 pitch = freqParam + inputs[FM_INPUT].getVoltageSimd<float_4>(c) * fmParam;
float_4 freq = clockFreq / 2.f * dsp::approxExp2_taylor5(pitch + 30.f) / std::pow(2.f, 30.f);
freq = simd::fmin(freq, 1024.f);
// Accumulate phase
float_4 phase = phases[c / 4];
phase += freq * args.sampleTime;
// Wrap phase
phase -= simd::trunc(phase);
// Reset phase
float_4 reset = resetTriggers[c / 4].process(simd::rescale(inputs[RESET_INPUT].getPolyVoltageSimd<float_4>(c), 0.1f, 2.f, 0.f, 1.f));
phase = simd::ifelse(reset, 0.f, phase);
phases[c / 4] = phase;
// Scale phase from 0 to waveLen
phase *= wavetable.waveLen;
// Get wavetable position, scaled from 0 to (waveCount - 1)
float_4 pos = posParam + inputs[POS_INPUT].getPolyVoltageSimd<float_4>(c) * posCvParam / 10.f;
pos = simd::clamp(pos);
pos *= (waveCount - 1);
if (c == 0)
lastPos = pos[0];
// Get wavetable points
float_4 out = 0.f;
for (int cc = 0; cc < 4 && c + cc < channels; cc++) {
// Get wave indexes
float phaseF = phase[cc] - std::trunc(phase[cc]);
size_t i0 = std::trunc(phase[cc]);
size_t i1 = (i0 + 1) % wavetable.waveLen;
// Get pos indexes
float posF = pos[cc] - std::trunc(pos[cc]);
size_t pos0 = std::trunc(pos[cc]);
size_t pos1 = pos0 + 1;
// Get waves
float out0 = crossfade(wavetable.at(pos0, i0), wavetable.at(pos0, i1), phaseF);
if (posF > 0.f) {
float out1 = crossfade(wavetable.at(pos1, i0), wavetable.at(pos1, i1), phaseF);
out[cc] = crossfade(out0, out1, posF);
if (wavetable.waveLen >= 2 && waveCount >= 1) {
// Iterate channels
for (int c = 0; c < channels; c += 4) {
// Calculate frequency in Hz
float_4 pitch = freqParam + inputs[FM_INPUT].getVoltageSimd<float_4>(c) * fmParam;
float_4 freq = clockFreq / 2.f * dsp::approxExp2_taylor5(pitch + 30.f) / std::pow(2.f, 30.f);
freq = simd::fmin(freq, 1024.f);
// Accumulate phase
float_4 phase = phases[c / 4];
phase += freq * args.sampleTime;
// Wrap phase
phase -= simd::trunc(phase);
// Reset phase
float_4 reset = resetTriggers[c / 4].process(simd::rescale(inputs[RESET_INPUT].getPolyVoltageSimd<float_4>(c), 0.1f, 2.f, 0.f, 1.f));
phase = simd::ifelse(reset, 0.f, phase);
phases[c / 4] = phase;
// Scale phase from 0 to waveLen
phase *= wavetable.waveLen;
// Get wavetable position, scaled from 0 to (waveCount - 1)
float_4 pos = posParam + inputs[POS_INPUT].getPolyVoltageSimd<float_4>(c) * posCvParam / 10.f;
pos = simd::clamp(pos);
pos *= (waveCount - 1);
if (c == 0)
lastPos = pos[0];
// Get wavetable points
float_4 out = 0.f;
for (int cc = 0; cc < 4 && c + cc < channels; cc++) {
// Get wave indexes
float phaseF = phase[cc] - std::trunc(phase[cc]);
size_t i0 = std::trunc(phase[cc]);
size_t i1 = (i0 + 1) % wavetable.waveLen;
// Get pos indexes
float posF = pos[cc] - std::trunc(pos[cc]);
size_t pos0 = std::trunc(pos[cc]);
size_t pos1 = pos0 + 1;
// Get waves
float out0 = crossfade(wavetable.at(pos0, i0), wavetable.at(pos0, i1), phaseF);
if (posF > 0.f) {
float out1 = crossfade(wavetable.at(pos1, i0), wavetable.at(pos1, i1), phaseF);
out[cc] = crossfade(out0, out1, posF);
}
else {
out[cc] = out0;
}
}
else {
out[cc] = out0;
}
}

// Invert and offset
if (invert)
out *= -1.f;
if (offset)
out += 1.f;
// Invert and offset
if (invert)
out *= -1.f;
if (offset)
out += 1.f;

outputs[WAVE_OUTPUT].setVoltageSimd(out * 5.f, c);
outputs[WAVE_OUTPUT].setVoltageSimd(out * 5.f, c);
}
}
else {
// Wavetable is invalid, so set 0V
for (int c = 0; c < channels; c += 4) {
outputs[WAVE_OUTPUT].setVoltageSimd(float_4(0.f), c);
}
}

outputs[WAVE_OUTPUT].setChannels(channels);
@@ -248,10 +226,6 @@ struct WTLFO : Module {

json_t* dataToJson() override {
json_t* rootJ = json_object();
// offset
json_object_set_new(rootJ, "offset", json_boolean(offset));
// invert
json_object_set_new(rootJ, "invert", json_boolean(invert));
// Merge wavetable
json_t* wavetableJ = wavetable.toJson();
json_object_update(rootJ, wavetableJ);
@@ -260,14 +234,6 @@ struct WTLFO : Module {
}

void dataFromJson(json_t* rootJ) override {
// offset
json_t* offsetJ = json_object_get(rootJ, "offset");
if (offsetJ)
offset = json_boolean_value(offsetJ);
// invert
json_t* invertJ = json_object_get(rootJ, "invert");
if (invertJ)
invert = json_boolean_value(invertJ);
// wavetable
wavetable.fromJson(rootJ);
}
@@ -287,9 +253,9 @@ struct WTLFOWidget : ModuleWidget {
addParam(createParamCentered<RoundLargeBlackKnob>(mm2px(Vec(8.913, 56.388)), module, WTLFO::FREQ_PARAM));
addParam(createParamCentered<RoundLargeBlackKnob>(mm2px(Vec(26.647, 56.388)), module, WTLFO::POS_PARAM));
addParam(createParamCentered<Trimpot>(mm2px(Vec(6.987, 80.603)), module, WTLFO::FM_PARAM));
addParam(createLightParamCentered<LEDLightButton<MediumSimpleLight<YellowLight>>>(mm2px(Vec(17.824, 80.517)), module, WTLFO::INVERT_PARAM, WTLFO::INVERT_LIGHT));
addParam(createLightParamCentered<LEDLightLatch<MediumSimpleLight<WhiteLight>>>(mm2px(Vec(17.824, 80.517)), module, WTLFO::INVERT_PARAM, WTLFO::INVERT_LIGHT));
addParam(createParamCentered<Trimpot>(mm2px(Vec(28.662, 80.536)), module, WTLFO::POS_CV_PARAM));
addParam(createLightParamCentered<LEDLightButton<MediumSimpleLight<YellowLight>>>(mm2px(Vec(17.824, 96.859)), module, WTLFO::OFFSET_PARAM, WTLFO::OFFSET_LIGHT));
addParam(createLightParamCentered<LEDLightLatch<MediumSimpleLight<WhiteLight>>>(mm2px(Vec(17.824, 96.859)), module, WTLFO::OFFSET_PARAM, WTLFO::OFFSET_LIGHT));

addInput(createInputCentered<PJ301MPort>(mm2px(Vec(6.987, 96.859)), module, WTLFO::FM_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(28.662, 96.859)), module, WTLFO::POS_INPUT));


+ 4
- 2
src/Wavetable.hpp View File

@@ -84,6 +84,8 @@ struct Wavetable {

/** Returns the number of waves in the wavetable. */
size_t getWaveCount() const {
if (waveLen == 0)
return 0;
return samples.size() / waveLen;
}

@@ -145,8 +147,6 @@ struct Wavetable {
}

void load(std::string path) {
samples.clear();

std::string ext = string::lowercase(system::getExtension(path));
if (ext == ".wav") {
// Load WAV
@@ -158,6 +158,7 @@ struct Wavetable {
#endif
return;

samples.clear();
samples.resize(wav.totalPCMFrameCount * wav.channels);

drwav_read_pcm_frames_f32(&wav, wav.totalPCMFrameCount, samples.data());
@@ -166,6 +167,7 @@ struct Wavetable {
else {
// Load bytes from file
std::vector<uint8_t> data = system::readFile(path);
samples.clear();

if (ext == ".f32") {
size_t len = data.size() / sizeof(float);


Loading…
Cancel
Save