Browse Source

Added first pass at Morphader

tags/v2.1.0
hemmer 3 years ago
parent
commit
c1cacbdd74
13 changed files with 2700 additions and 10 deletions
  1. +22
    -6
      plugin.json
  2. +85
    -0
      res/BefacoTinyKnobBlack.svg
  3. +0
    -0
      res/BefacoTinyKnobDarkGrey.svg
  4. +85
    -0
      res/BefacoTinyKnobLightGrey.svg
  5. +85
    -0
      res/CrossfaderBackground.svg
  6. +113
    -0
      res/CrossfaderHandle.svg
  7. +1751
    -0
      res/Morphader.svg
  8. +114
    -0
      res/SwitchNarrow_0.svg
  9. +114
    -0
      res/SwitchNarrow_1.svg
  10. +1
    -1
      src/Kickall.cpp
  11. +289
    -0
      src/Morphader.cpp
  12. +1
    -0
      src/plugin.cpp
  13. +40
    -3
      src/plugin.hpp

+ 22
- 6
plugin.json View File

@@ -111,7 +111,8 @@
"Envelope generator",
"Mixer",
"Polyphonic",
"Hardware clone"
"Hardware clone",
"Quad"
]
},
{
@@ -157,12 +158,27 @@
"name": "Sampling Modulator",
"description": "Multi-function module that lies somewhere between a VCO, a Sample & Hold, and an 8 step trigger sequencer",
"manualUrl": "https://www.befaco.org/sampling-modulator/",
"modularGridUrl": "https://www.modulargrid.net/e/befaco-sampling-modulator-",
"tags": [
"Sample and hold",
"modularGridUrl": "https://www.modulargrid.net/e/befaco-sampling-modulator-",
"tags": [
"Clock generator",
"Hardware clone",
"Oscillator",
"Clock generator"
"Sample and hold"
]
},
{
"slug": "Morphader",
"name": "Morphader",
"description": "Multichannel CV/Audio crossfader",
"manualUrl": "https://www.befaco.org/morphader-2/",
"modularGridUrl": "https://www.modulargrid.net/e/befaco-morphader",
"tags": [
"Controller",
"Hardware clone",
"Mixer",
"Polyphonic",
"Quad"
]
}
]
}
}

+ 85
- 0
res/BefacoTinyKnobBlack.svg View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
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="9.0000019mm"
height="9.0000801mm"
viewBox="0 0 9.0000016 9.00008"
version="1.1"
id="svg113936"
inkscape:version="1.0.2-2 (e86c870879, 2021-01-15)"
sodipodi:docname="BefacoTinyKnobBlack.svg">
<defs
id="defs113930" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="7.919596"
inkscape:cx="-34.401622"
inkscape:cy="38.846852"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="2560"
inkscape:window-height="1393"
inkscape:window-x="2473"
inkscape:window-y="40"
inkscape:window-maximized="0"
inkscape:document-rotation="0" />
<metadata
id="metadata113933">
<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>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-111.86932,-85.795053)">
<path
inkscape:connector-curvature="0"
style="fill:#d4d4d4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28209424"
d="m 120.10511,92.798549 c 1.38512,-2.062815 0.83525,-4.854005 -1.22757,-6.23803 -2.0617,-1.384026 -4.86062,-0.840773 -6.24463,1.222041 -1.38514,2.062814 -0.83306,4.866126 1.22866,6.251255 2.06282,1.384023 4.8595,0.827547 6.24354,-1.235266"
id="path109730" />
<path
inkscape:connector-curvature="0"
style="fill:#1b1b1b;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28209424"
d="m 120.02026,91.143448 c -0.46281,2.022043 -2.47716,3.285957 -4.49919,2.823148 -2.02205,-0.462813 -3.28598,-2.47714 -2.82314,-4.499182 0.46281,-2.020944 2.47713,-3.285958 4.49918,-2.82315 2.02093,0.462812 3.28594,2.477141 2.82315,4.499184"
id="path109732" />
<path
inkscape:connector-curvature="0"
style="fill:none;stroke:#7f7878;stroke-width:0.11481237;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
d="m 120.02026,91.143463 c -0.46281,2.022042 -2.47715,3.285956 -4.49919,2.823145 -2.02204,-0.462811 -3.28595,-2.47714 -2.82314,-4.499183 0.46281,-2.020941 2.47714,-3.285957 4.49918,-2.823145 2.02094,0.46281 3.28596,2.47714 2.82315,4.499183 z m 0,0"
id="path109734" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28209424"
d="m 116.20648,88.009558 c -0.11239,-0.07603 -0.14328,-0.229201 -0.0672,-0.342701 0.0761,-0.113495 0.23029,-0.143251 0.34379,-0.06722 0.11356,0.07603 0.14325,0.229201 0.0672,0.342701 -0.076,0.113495 -0.23031,0.14325 -0.34379,0.06722"
id="path109736" />
<path
inkscape:connector-curvature="0"
style="fill:#ffffff;stroke:#ffffff;stroke-width:0.46912277;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;fill-opacity:1"
d="m 116.20647,88.009571 c -0.11239,-0.07603 -0.14326,-0.229202 -0.0672,-0.3427 0.076,-0.113495 0.23032,-0.14325 0.34381,-0.06722 0.11356,0.07602 0.14325,0.229201 0.0672,0.3427 -0.076,0.113495 -0.2303,0.143251 -0.3438,0.06722 z m 0,0"
id="path109738" />
</g>
</svg>

res/BefacoTinyKnobGrey.svg → res/BefacoTinyKnobDarkGrey.svg View File


+ 85
- 0
res/BefacoTinyKnobLightGrey.svg View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
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="9.0000019mm"
height="9.0000801mm"
viewBox="0 0 9.0000016 9.00008"
version="1.1"
id="svg113936"
inkscape:version="1.0.2-2 (e86c870879, 2021-01-15)"
sodipodi:docname="BefacoTinyKnobLightGrey.svg">
<defs
id="defs113930" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="7.919596"
inkscape:cx="-34.401622"
inkscape:cy="38.846852"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="2560"
inkscape:window-height="1393"
inkscape:window-x="2473"
inkscape:window-y="40"
inkscape:window-maximized="0"
inkscape:document-rotation="0" />
<metadata
id="metadata113933">
<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>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-111.86932,-85.795053)">
<path
inkscape:connector-curvature="0"
style="fill:#d4d4d4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28209424"
d="m 120.10511,92.798549 c 1.38512,-2.062815 0.83525,-4.854005 -1.22757,-6.23803 -2.0617,-1.384026 -4.86062,-0.840773 -6.24463,1.222041 -1.38514,2.062814 -0.83306,4.866126 1.22866,6.251255 2.06282,1.384023 4.8595,0.827547 6.24354,-1.235266"
id="path109730" />
<path
inkscape:connector-curvature="0"
style="fill:#a8a8a8;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28209424"
d="m 120.02026,91.143448 c -0.46281,2.022043 -2.47716,3.285957 -4.49919,2.823148 -2.02205,-0.462813 -3.28598,-2.47714 -2.82314,-4.499182 0.46281,-2.020944 2.47713,-3.285958 4.49918,-2.82315 2.02093,0.462812 3.28594,2.477141 2.82315,4.499184"
id="path109732" />
<path
inkscape:connector-curvature="0"
style="fill:none;stroke:#7f7878;stroke-width:0.11481237;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1"
d="m 120.02026,91.143463 c -0.46281,2.022042 -2.47715,3.285956 -4.49919,2.823145 -2.02204,-0.462811 -3.28595,-2.47714 -2.82314,-4.499183 0.46281,-2.020941 2.47714,-3.285957 4.49918,-2.823145 2.02094,0.46281 3.28596,2.47714 2.82315,4.499183 z m 0,0"
id="path109734" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28209424"
d="m 116.20648,88.009558 c -0.11239,-0.07603 -0.14328,-0.229201 -0.0672,-0.342701 0.0761,-0.113495 0.23029,-0.143251 0.34379,-0.06722 0.11356,0.07603 0.14325,0.229201 0.0672,0.342701 -0.076,0.113495 -0.23031,0.14325 -0.34379,0.06722"
id="path109736" />
<path
inkscape:connector-curvature="0"
style="fill:#ffffff;stroke:#ffffff;stroke-width:0.46912277;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;fill-opacity:1"
d="m 116.20647,88.009571 c -0.11239,-0.07603 -0.14326,-0.229202 -0.0672,-0.3427 0.076,-0.113495 0.23032,-0.14325 0.34381,-0.06722 0.11356,0.07602 0.14325,0.229201 0.0672,0.3427 -0.076,0.113495 -0.2303,0.143251 -0.3438,0.06722 z m 0,0"
id="path109738" />
</g>
</svg>

+ 85
- 0
res/CrossfaderBackground.svg View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
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="39.553001mm"
height="2.3859999mm"
viewBox="0 0 39.553001 2.3859999"
version="1.1"
id="svg4394"
inkscape:version="1.0.2-2 (e86c870879, 2021-01-15)"
sodipodi:docname="CrossfaderBackground.svg">
<defs
id="defs4388" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="134.10114"
inkscape:cy="23.67955"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1361"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1" />
<metadata
id="metadata4391">
<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>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
style="display:inline"
id="g67105"
transform="matrix(0,0.26458333,0.26458333,0,-33.883796,-5.288544)">
<rect
inkscape:export-ydpi="300"
inkscape:export-xdpi="300"
inkscape:export-filename="/home/diego/Escritorio/Miniaturas_modulos_web/Slew_limiter.png"
y="128.23293"
x="20.15638"
height="149.15367"
width="8.6811705"
id="rect67099"
style="display:inline;fill:#333333;fill-opacity:1;stroke:#000000;stroke-width:0.336363;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
ry="5.9719005"
rx="4.3405852" />
<g
inkscape:export-ydpi="300"
inkscape:export-xdpi="300"
inkscape:export-filename="/home/diego/Escritorio/Miniaturas_modulos_web/Slew_limiter.png"
inkscape:label="Layer 1"
id="g67103"
transform="translate(-167.13749,-255.25313)"
style="display:inline">
<g
transform="translate(219.29845,-487.66016)"
style="display:inline"
id="g67101" />
</g>
</g>
</g>
</svg>

+ 113
- 0
res/CrossfaderHandle.svg View File

@@ -0,0 +1,113 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
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="11.247mm"
height="7.415mm"
viewBox="0 0 11.247 7.415"
version="1.1"
id="svg3778"
inkscape:version="1.0.2-2 (e86c870879, 2021-01-15)"
sodipodi:docname="CrossfaderHandle.svg">
<defs
id="defs3772" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="7.9195959"
inkscape:cx="73.979315"
inkscape:cy="61.676685"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
inkscape:document-rotation="0"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1361"
inkscape:window-x="-9"
inkscape:window-y="-9"
inkscape:window-maximized="1" />
<metadata
id="metadata3775">
<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>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
style="display:inline"
transform="matrix(0.9989706,0,0,1.1317921,-30.621884,-314.11007)"
id="g67123">
<g
style="display:inline"
id="g67111"
transform="matrix(0,-0.26458333,0.26458333,0,-22.851599,302.31088)">
<g
inkscape:export-ydpi="300"
inkscape:export-xdpi="300"
inkscape:export-filename="/home/diego/Escritorio/Miniaturas_modulos_web/Slew_limiter.png"
transform="translate(-110.33749,-283.5198)"
id="g67109"
inkscape:label="Layer 1"
style="display:inline">
<g
id="g67107"
style="display:inline"
transform="translate(219.29845,-487.66016)" />
</g>
</g>
<g
transform="matrix(0,-0.26458333,0.26458333,0,-147.75502,337.10612)"
style="display:inline"
id="g67121"
inkscape:label="Capa 1">
<g
style="display:inline"
id="g67119"
transform="matrix(1.5157369,0,0,-1.8423541,411.1976,1075.6321)">
<rect
transform="matrix(0.8,0,0,-0.8,0,363.96845)"
y="183.06221"
x="-173.42"
height="28.076494"
width="19.524609"
id="rect67113"
style="fill:#292929;fill-opacity:1;fill-rule:nonzero;stroke:#767171;stroke-width:0.795136;stroke-linecap:square;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
transform="scale(1,-1)"
y="-212.17532"
x="-136.838"
height="11.539498"
width="11.688397"
id="rect67115"
style="fill:#6b6b6b;fill-opacity:1;fill-rule:nonzero;stroke:none" />
<rect
transform="scale(1,-1)"
y="-206.99741"
x="-139.07549"
height="1.6550338"
width="16.336033"
id="rect67117"
style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
</g>
</g>
</g>
</g>
</svg>

+ 1751
- 0
res/Morphader.svg
File diff suppressed because it is too large
View File


+ 114
- 0
res/SwitchNarrow_0.svg View File

@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
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="10"
height="20.641106"
viewBox="0 0 2.6458333 5.4612927"
version="1.1"
id="svg56722"
inkscape:version="1.0.2-2 (e86c870879, 2021-01-15)"
sodipodi:docname="SwitchNarrow_0.svg">
<defs
id="defs56716" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="-7.1500998"
inkscape:cy="8.220078"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="2560"
inkscape:window-height="1393"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
units="px"
inkscape:document-rotation="0" />
<metadata
id="metadata56719">
<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>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-35.423779,-63.339207)">
<g
transform="matrix(0.19690649,0,0,-0.27523902,-118.85399,385.03395)"
id="g56714"
style="stroke-width:1.28171">
<path
d="m 783.5078,1167.3652 c 0,0.779 0.639,1.418 1.418,1.418 h 10.622 c 0.779,0 1.418,-0.639 1.418,-1.418 v -17.007 c 0,-0.779 -0.639,-1.417 -1.418,-1.417 h -10.622 c -0.779,0 -1.418,0.638 -1.418,1.417 z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.28171"
id="path5785"
inkscape:connector-curvature="0" />
<g
style="fill:#282828;fill-opacity:1;stroke-width:1.28171"
id="g5795">
<g
style="fill:#282828;fill-opacity:1;stroke-width:1.28171"
id="g5797">
<path
inkscape:connector-curvature="0"
id="path5805"
style="fill:#282828;fill-opacity:1;stroke:none;stroke-width:1.28171"
d="m 785.616,1167.502 c -0.468,0 -0.85,-0.382 -0.85,-0.85 v 0 -15.724 c 0,-0.468 0.382,-0.851 0.85,-0.851 v 0 h 9.241 c 0.466,0 0.849,0.383 0.849,0.851 v 0 15.724 c 0,0.468 -0.383,0.85 -0.849,0.85 v 0 z" />
</g>
</g>
<path
inkscape:connector-curvature="0"
id="path5815"
style="fill:#444444;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.28171"
d="m 784.767,1158.581 h 10.94 v -8.504 h -10.94 z" />
<path
inkscape:connector-curvature="0"
id="path5817"
style="fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.28171"
d="m 784.767,1154.797 h 10.94 v -0.936 h -10.94 z" />
<path
inkscape:connector-curvature="0"
id="path5819"
style="fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.28171"
d="m 784.767,1151.013 h 10.94 v -0.936 h -10.94 z" />
<path
inkscape:connector-curvature="0"
id="path5821"
style="fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.28171"
d="m 784.767,1152.904 h 10.94 v -0.936 h -10.94 z" />
<path
inkscape:connector-curvature="0"
id="path5823"
style="fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.28171"
d="m 784.767,1156.689 h 10.94 v -0.936 h -10.94 z" />
<path
inkscape:connector-curvature="0"
id="path5825"
style="fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.28171"
d="m 784.767,1158.581 h 10.94 v -0.936 h -10.94 z" />
</g>
</g>
</svg>

+ 114
- 0
res/SwitchNarrow_1.svg View File

@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
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="10"
height="20.641106"
viewBox="0 0 2.6458333 5.4612927"
version="1.1"
id="svg56722"
inkscape:version="1.0.2-2 (e86c870879, 2021-01-15)"
sodipodi:docname="SwitchNarrow_1.svg">
<defs
id="defs56716" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="-7.1500998"
inkscape:cy="8.220078"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="2560"
inkscape:window-height="1393"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
units="px"
inkscape:document-rotation="0" />
<metadata
id="metadata56719">
<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>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-35.423779,-63.339207)">
<g
transform="matrix(0.19690649,0,0,0.27523902,-118.85399,-252.89424)"
id="g56714"
style="stroke-width:1.28171">
<path
d="m 783.5078,1167.3652 c 0,0.779 0.639,1.418 1.418,1.418 h 10.622 c 0.779,0 1.418,-0.639 1.418,-1.418 v -17.007 c 0,-0.779 -0.639,-1.417 -1.418,-1.417 h -10.622 c -0.779,0 -1.418,0.638 -1.418,1.417 z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.28171"
id="path5785"
inkscape:connector-curvature="0" />
<g
style="fill:#282828;fill-opacity:1;stroke-width:1.28171"
id="g5795">
<g
style="fill:#282828;fill-opacity:1;stroke-width:1.28171"
id="g5797">
<path
inkscape:connector-curvature="0"
id="path5805"
style="fill:#282828;fill-opacity:1;stroke:none;stroke-width:1.28171"
d="m 785.616,1167.502 c -0.468,0 -0.85,-0.382 -0.85,-0.85 v 0 -15.724 c 0,-0.468 0.382,-0.851 0.85,-0.851 v 0 h 9.241 c 0.466,0 0.849,0.383 0.849,0.851 v 0 15.724 c 0,0.468 -0.383,0.85 -0.849,0.85 v 0 z" />
</g>
</g>
<path
inkscape:connector-curvature="0"
id="path5815"
style="fill:#444444;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.28171"
d="m 784.767,1158.581 h 10.94 v -8.504 h -10.94 z" />
<path
inkscape:connector-curvature="0"
id="path5817"
style="fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.28171"
d="m 784.767,1154.797 h 10.94 v -0.936 h -10.94 z" />
<path
inkscape:connector-curvature="0"
id="path5819"
style="fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.28171"
d="m 784.767,1151.013 h 10.94 v -0.936 h -10.94 z" />
<path
inkscape:connector-curvature="0"
id="path5821"
style="fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.28171"
d="m 784.767,1152.904 h 10.94 v -0.936 h -10.94 z" />
<path
inkscape:connector-curvature="0"
id="path5823"
style="fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.28171"
d="m 784.767,1156.689 h 10.94 v -0.936 h -10.94 z" />
<path
inkscape:connector-curvature="0"
id="path5825"
style="fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.28171"
d="m 784.767,1158.581 h 10.94 v -0.936 h -10.94 z" />
</g>
</g>
</svg>

+ 1
- 1
src/Kickall.cpp View File

@@ -123,7 +123,7 @@ struct KickallWidget : ModuleWidget {
addChild(createWidget<Knurlie>(Vec(RACK_GRID_WIDTH, 0)));
addChild(createWidget<Knurlie>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
addParam(createParamCentered<BefacoTinyKnobGrey>(mm2px(Vec(8.472, 28.97)), module, Kickall::TUNE_PARAM));
addParam(createParamCentered<BefacoTinyKnobDarkGrey>(mm2px(Vec(8.472, 28.97)), module, Kickall::TUNE_PARAM));
addParam(createParamCentered<BefacoPush>(mm2px(Vec(22.409, 29.159)), module, Kickall::TRIGG_BUTTON_PARAM));
addParam(createParamCentered<Davies1900hLargeGreyKnob>(mm2px(Vec(15.526, 49.292)), module, Kickall::SHAPE_PARAM));
addParam(createParam<BefacoSlidePot>(mm2px(Vec(19.667, 63.897)), module, Kickall::DECAY_PARAM));


+ 289
- 0
src/Morphader.cpp View File

@@ -0,0 +1,289 @@
#include "plugin.hpp"


// equal sum crossfade, -1 <= p <= 1
template <typename T>
inline T equalSumCrossfade(T a, T b, const float p) {
return a * (0.5f * (1.f - p)) + b * (0.5f * (1.f + p));
}

// equal power crossfade, -1 <= p <= 1
template <typename T>
inline T equalPowerCrossfade(T a, T b, const float p) {
// TODO: investigate more efficient representation (avoid exp)
return std::min(std::exp(4.f * p), 1.f) * b + std::min(std::exp(4.f * -p), 1.f) * a;
}

// TExponentialSlewLimiter doesn't appear to work correctly (tried for -1 -> +1, and 0 -> 1)
// TODO: confirm, or explain better how it doesn't work
struct ExpLogSlewLimiter {

float out = 0.f;
float slew = 0.f;

void reset() {
out = 0.f;
}

void setSlew(float slew) {
this->slew = slew;
}
float process(float deltaTime, float in) {
if (in > out) {
out += slew * (in - out) * deltaTime;
if (out > in) {
out = in;
}
}
else if (in < out) {
out -= slew * (out - in) * deltaTime;
if (out < in) {
out = in;
}
}
return out;
}
};


struct Morphader : Module {
enum ParamIds {
CV_PARAM,
ENUMS(A_LEVEL, 4),
ENUMS(B_LEVEL, 4),
ENUMS(MODE, 4),
FADER_LAG_PARAM,
FADER_PARAM,
NUM_PARAMS
};
enum InputIds {
ENUMS(CV_INPUT, 4),
ENUMS(A_INPUT, 4),
ENUMS(B_INPUT, 4),
NUM_INPUTS
};
enum OutputIds {
ENUMS(OUT, 4),
NUM_OUTPUTS
};
enum LightIds {
ENUMS(A_LED, 4),
ENUMS(B_LED, 4),
NUM_LIGHTS
};
enum CrossfadeMode {
AUDIO_MODE,
CV_MODE
};

static const int NUM_MIXER_CHANNELS = 4;
const simd::float_4 normal10VSimd = {10.f};
ExpLogSlewLimiter slewLimiter;

// minimum and maximum slopes in volts per second, they specify the time to get
// from A (-1) to B (+1)
constexpr static float slewMin = 2.0 / 15.f;
constexpr static float slewMax = 2.0 / 0.01f;

struct AudioCVModeParam : ParamQuantity {
std::string getDisplayValueString() override {
switch (static_cast<CrossfadeMode>(getValue())) {
case AUDIO_MODE: return "Audio";
case CV_MODE: return "CV";
default: assert(false);
}
}
};

struct FaderLagParam : ParamQuantity {
std::string getDisplayValueString() override {
const float slewTime = 2.f / (slewMax * std::pow(slewMin / slewMax, getValue()));
return string::f("%.3gs", slewTime);
}
};

Morphader() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);

configParam(CV_PARAM, 0.f, 1.f, 1.f, "CV");

for (int i = 0; i < NUM_MIXER_CHANNELS; i++) {
configParam(A_LEVEL + i, 0.f, 1.f, 0.f, "A level " + std::to_string(i + 1));
}
for (int i = 0; i < NUM_MIXER_CHANNELS; i++) {
configParam(B_LEVEL + i, 0.f, 1.f, 0.f, "B level " + std::to_string(i + 1));
}
for (int i = 0; i < NUM_MIXER_CHANNELS; i++) {
configParam<AudioCVModeParam>(MODE + i, AUDIO_MODE, CV_MODE, AUDIO_MODE, "Mode " + std::to_string(i + 1));
}

configParam<FaderLagParam>(FADER_LAG_PARAM, 0.f, 1.f, 0.f, "Fader lag");
configParam(FADER_PARAM, -1.f, 1.f, 0.f, "Fader");
}

// determine the cross-fade between -1 (A) and +1 (B) for each of the 4 channels
simd::float_4 determineChannelCrossfades(const float deltaTime) {

simd::float_4 channelCrossfades = {0.f};

slewLimiter.setSlew(slewMax * std::pow(slewMin / slewMax, params[FADER_LAG_PARAM].getValue()));
const float masterCrossfadeValue = slewLimiter.process(deltaTime, params[FADER_PARAM].getValue());

for (int i = 0; i < NUM_MIXER_CHANNELS; i++) {

if (i == 0) {
// CV will be added to master for channel 1, and if not connected, the normalled value of 5.0V will correspond to the midpoint
const float crossfadeCV = clamp(inputs[CV_INPUT + i].getNormalVoltage(5.f), 0.f, 10.f);
channelCrossfades[i] = params[CV_PARAM].getValue() * rescale(crossfadeCV, 0.f, 10.f, 0.f, +2.f) + masterCrossfadeValue;
}
else {
// if present for the current channel, CV has total control (crossfader is ignored)
if (inputs[CV_INPUT + i].isConnected()) {
const float crossfadeCV = clamp(inputs[CV_INPUT + i].getVoltage(), 0.f, 10.f);
channelCrossfades[i] = rescale(crossfadeCV, 0.f, 10.f, -1.f, +1.f);
}
// if channel 1 is plugged in, use that
else if (inputs[CV_INPUT + 0].isConnected()) {
// TODO: is this right, or is is channelCrossfades[i] (i.e. with master fader)?
const float crossfadeCV = clamp(inputs[CV_INPUT + 0].getVoltage(), 0.f, 10.f);
channelCrossfades[i] = params[CV_PARAM].getValue() * rescale(crossfadeCV, 0.f, 10.f, -1.f, +1.f);
}
else {
channelCrossfades[i] = masterCrossfadeValue;
}
}
}

return channelCrossfades;
}

void process(const ProcessArgs& args) override {

int maxChannels = 1;
simd::float_4 mix[4] = {0.f};
const simd::float_4 channelCrossfades = determineChannelCrossfades(args.sampleTime);

for (int i = 0; i < NUM_MIXER_CHANNELS; i++) {

const int channels = std::max(std::max(inputs[A_INPUT + i].getChannels(), inputs[B_INPUT + i].getChannels()), 1);
// keep track of the max number of channels for the mix output, noting that if channels are taken out of the mix
// (i.e. they're connected) they shouldn't contribute to the polyphony calculation
if (!outputs[OUT + i].isConnected()) {
maxChannels = std::max(maxChannels, channels);
}

simd::float_4 out[4] = {0.f};
for (int c = 0; c < channels; c += 4) {
simd::float_4 inA = inputs[A_INPUT + i].getNormalVoltageSimd(normal10VSimd, c) * params[A_LEVEL + i].getValue();
simd::float_4 inB = inputs[B_INPUT + i].getNormalVoltageSimd(normal10VSimd, c) * params[B_LEVEL + i].getValue();

switch (static_cast<CrossfadeMode>(params[MODE + i].getValue())) {
case CV_MODE: {
out[c / 4] = equalSumCrossfade(inA, inB, channelCrossfades[i]);
break;
}
case AUDIO_MODE: {
out[c / 4] = equalPowerCrossfade(inA, inB, channelCrossfades[i]);
break;
}
default: assert(false);
}
}

// if output is patched, the channel is taken out of the mix
if (outputs[OUT + i].isConnected() && i != NUM_MIXER_CHANNELS - 1) {
outputs[OUT + i].setChannels(channels);
for (int c = 0; c < channels; c += 4) {
out[c / 4].store(outputs[OUT + i].getVoltages(c));
}
}
else {
for (int c = 0; c < channels; c += 4) {
mix[c / 4] += out[c / 4];
}
}

if (i == NUM_MIXER_CHANNELS - 1) {
outputs[OUT + i].setChannels(maxChannels);

for (int c = 0; c < maxChannels; c += 4) {
mix[c / 4].store(outputs[OUT + i].getVoltages(c));
}
}

switch (static_cast<CrossfadeMode>(params[MODE + i].getValue())) {
case AUDIO_MODE: {
lights[A_LED + i].setBrightness(equalPowerCrossfade(1.f, 0.f, channelCrossfades[i]));
lights[B_LED + i].setBrightness(equalPowerCrossfade(0.f, 1.f, channelCrossfades[i]));
break;
}
case CV_MODE: {
lights[A_LED + i].setBrightness(equalSumCrossfade(1.f, 0.f, channelCrossfades[i]));
lights[B_LED + i].setBrightness(equalSumCrossfade(0.f, 1.f, channelCrossfades[i]));
break;
}
default: assert(false);
}
} // end loop over mixer channels
}
};


struct MorphaderWidget : ModuleWidget {
MorphaderWidget(Morphader* module) {
setModule(module);
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Morphader.svg")));

addChild(createWidget<Knurlie>(Vec(RACK_GRID_WIDTH, 0)));
addChild(createWidget<Knurlie>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
addChild(createWidget<Knurlie>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
addChild(createWidget<Knurlie>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));

addParam(createParamCentered<BefacoTinyKnob>(mm2px(Vec(10.817, 15.075)), module, Morphader::CV_PARAM));
addParam(createParamCentered<BefacoTinyKnob>(mm2px(Vec(30.243, 30.537)), module, Morphader::A_LEVEL + 0));
addParam(createParamCentered<BefacoTinyKnobLightGrey>(mm2px(Vec(30.243, 48.017)), module, Morphader::A_LEVEL + 1));
addParam(createParamCentered<BefacoTinyKnobDarkGrey>(mm2px(Vec(30.243, 65.523)), module, Morphader::A_LEVEL + 2));
addParam(createParamCentered<BefacoTinyKnobBlack>(mm2px(Vec(30.243, 83.051)), module, Morphader::A_LEVEL + 3));
addParam(createParamCentered<BefacoTinyKnob>(mm2px(Vec(52.696, 30.537)), module, Morphader::B_LEVEL + 0));
addParam(createParamCentered<BefacoTinyKnobLightGrey>(mm2px(Vec(52.696, 48.017)), module, Morphader::B_LEVEL + 1));
addParam(createParamCentered<BefacoTinyKnobDarkGrey>(mm2px(Vec(52.696, 65.523)), module, Morphader::B_LEVEL + 2));
addParam(createParamCentered<BefacoTinyKnobBlack>(mm2px(Vec(52.696, 83.051)), module, Morphader::B_LEVEL + 3));
addParam(createParam<CKSSNarrow>(mm2px(Vec(39.775, 28.107)), module, Morphader::MODE + 0));
addParam(createParam<CKSSNarrow>(mm2px(Vec(39.775, 45.627)), module, Morphader::MODE + 1));
addParam(createParam<CKSSNarrow>(mm2px(Vec(39.775, 63.146)), module, Morphader::MODE + 2));
addParam(createParam<CKSSNarrow>(mm2px(Vec(39.775, 80.666)), module, Morphader::MODE + 3));
addParam(createParamCentered<BefacoTinyKnobRed>(mm2px(Vec(10.817, 99.242)), module, Morphader::FADER_LAG_PARAM));
addParam(createParamCentered<Crossfader>(mm2px(Vec(30., 114.25)), module, Morphader::FADER_PARAM));

addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(25.214, 14.746)), module, Morphader::CV_INPUT + 0));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(35.213, 14.746)), module, Morphader::CV_INPUT + 1));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(45.236, 14.746)), module, Morphader::CV_INPUT + 2));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(55.212, 14.746)), module, Morphader::CV_INPUT + 3));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(5.812, 32.497)), module, Morphader::A_INPUT + 0));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(5.812, 48.017)), module, Morphader::A_INPUT + 1));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(5.812, 65.523)), module, Morphader::A_INPUT + 2));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(5.812, 81.185)), module, Morphader::A_INPUT + 3));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(15.791, 32.497)), module, Morphader::B_INPUT + 0));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(15.791, 48.017)), module, Morphader::B_INPUT + 1));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(15.791, 65.523)), module, Morphader::B_INPUT + 2));
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(15.791, 81.185)), module, Morphader::B_INPUT + 3));

addOutput(createOutputCentered<BefacoOutputPort>(mm2px(Vec(25.177, 100.5)), module, Morphader::OUT + 0));
addOutput(createOutputCentered<BefacoOutputPort>(mm2px(Vec(35.177, 100.5)), module, Morphader::OUT + 1));
addOutput(createOutputCentered<BefacoOutputPort>(mm2px(Vec(45.177, 100.5)), module, Morphader::OUT + 2));
addOutput(createOutputCentered<BefacoOutputPort>(mm2px(Vec(55.176, 100.5)), module, Morphader::OUT + 3));

addChild(createLightCentered<SmallLight<RedLight>>(mm2px(Vec(37.594, 24.378)), module, Morphader::A_LED + 0));
addChild(createLightCentered<SmallLight<RedLight>>(mm2px(Vec(37.594, 41.908)), module, Morphader::A_LED + 1));
addChild(createLightCentered<SmallLight<RedLight>>(mm2px(Vec(37.594, 59.488)), module, Morphader::A_LED + 2));
addChild(createLightCentered<SmallLight<RedLight>>(mm2px(Vec(37.594, 76.918)), module, Morphader::A_LED + 3));

addChild(createLightCentered<SmallLight<RedLight>>(mm2px(Vec(45.332, 24.378)), module, Morphader::B_LED + 0));
addChild(createLightCentered<SmallLight<RedLight>>(mm2px(Vec(45.332, 41.908)), module, Morphader::B_LED + 1));
addChild(createLightCentered<SmallLight<RedLight>>(mm2px(Vec(45.332, 59.488)), module, Morphader::B_LED + 2));
addChild(createLightCentered<SmallLight<RedLight>>(mm2px(Vec(45.332, 76.918)), module, Morphader::B_LED + 3));
}
};


Model* modelMorphader = createModel<Morphader, MorphaderWidget>("Morphader");

+ 1
- 0
src/plugin.cpp View File

@@ -18,4 +18,5 @@ void init(rack::Plugin *p) {
p->addModel(modelChoppingKinky);
p->addModel(modelKickall);
p->addModel(modelSamplingModulator);
p->addModel(modelMorphader);
}

+ 40
- 3
src/plugin.hpp View File

@@ -18,6 +18,7 @@ extern Model *modelHexmixVCA;
extern Model *modelChoppingKinky;
extern Model *modelKickall;
extern Model *modelSamplingModulator;
extern Model *modelMorphader;


struct Knurlie : SvgScrew {
@@ -44,11 +45,27 @@ struct BefacoTinyKnobWhite : app::SvgKnob {
}
};

struct BefacoTinyKnobGrey : app::SvgKnob {
BefacoTinyKnobGrey() {
struct BefacoTinyKnobDarkGrey : app::SvgKnob {
BefacoTinyKnobDarkGrey() {
minAngle = -0.8 * M_PI;
maxAngle = 0.8 * M_PI;
setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/BefacoTinyKnobGrey.svg")));
setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/BefacoTinyKnobDarkGrey.svg")));
}
};

struct BefacoTinyKnobLightGrey : app::SvgKnob {
BefacoTinyKnobLightGrey() {
minAngle = -0.8 * M_PI;
maxAngle = 0.8 * M_PI;
setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/BefacoTinyKnobLightGrey.svg")));
}
};

struct BefacoTinyKnobBlack : app::SvgKnob {
BefacoTinyKnobBlack() {
minAngle = -0.8 * M_PI;
maxAngle = 0.8 * M_PI;
setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/BefacoTinyKnobBlack.svg")));
}
};

@@ -70,6 +87,26 @@ struct BefacoInputPort : app::SvgPort {
}
};

struct CKSSNarrow : app::SvgSwitch {
CKSSNarrow() {
addFrame(APP->window->loadSvg(asset::plugin(pluginInstance, "res/SwitchNarrow_0.svg")));
addFrame(APP->window->loadSvg(asset::plugin(pluginInstance, "res/SwitchNarrow_1.svg")));
}
};

struct Crossfader : app::SvgSlider {
Crossfader() {
setBackgroundSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/CrossfaderBackground.svg")));
setHandleSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/CrossfaderHandle.svg")));
minHandlePos = mm2px(Vec(4.5f, -0.8f));
maxHandlePos = mm2px(Vec(34.5, -0.8f));
horizontal = true;
math::Vec margin = math::Vec(15, 5);
background->box.pos = margin;
box.size = background->box.size.plus(margin.mult(2));
}
};

template <typename T>
T sin2pi_pade_05_5_4(T x) {
x -= 0.5f;


Loading…
Cancel
Save