{
  "format": "forge.graph/0",
  "name": "Ramp Filter",
  "author": "Chirp",
  "license": "CC-BY-4.0",
  "remixed_from": null,
  "description": "A resonant filter that travels from one setting to another and back, the way Chase Bliss pedals ramp their knobs: it rises, falls or bounces at Rate, along a straight or bent path (Curve), from Freq across Range octaves (down, if Range is below noon). Per note starts a fresh sweep at each pick attack, for a quacky envelope filter you can shape.",
  "tags": ["filter", "ramp", "modulation", "sweep", "envelope"],
  "face": {
    "display": { "kind": "trace", "label": "Ramp", "source": "ramp", "range": [0, 1] },
    "knobs": [
      { "id": "freq", "label": "Freq", "default": 0.35,
        "controls": [ { "target": "start.v", "from": 0.15, "to": 3, "curve": "exp" } ] },
      { "id": "range", "label": "Range", "default": 0.75,
        "controls": [ { "target": "octaves.v", "from": -4, "to": 4 } ] },
      { "id": "rate", "label": "Rate", "default": 0.4,
        "controls": [ { "target": "ramp.rate", "from": 0.05, "to": 8, "curve": "exp" } ] },
      { "id": "curve", "label": "Curve", "default": 0.5,
        "controls": [ { "target": "ramp.curve", "from": -1, "to": 1 } ] },
      { "id": "resonance", "label": "Reso", "default": 0.45,
        "controls": [ { "target": "f.q", "from": 0.7, "to": 8, "curve": "exp" } ] },
      { "id": "level", "label": "Level", "default": 0.5,
        "controls": [ { "target": "level.amount", "from": 0.6, "to": 1.6 } ] }
    ],
    "menus": [
      { "id": "shape", "label": "Shape", "options": ["Rise", "Fall", "Bounce", "Per note"], "default": 2,
        "controls": [ { "target": "ramp.shape", "values": [0, 1, 2, 3] },
                      { "target": "picks.v", "values": [0, 0, 0, 1] } ] },
      { "id": "mode", "label": "Mode", "options": ["Lowpass", "Bandpass"], "default": 0,
        "controls": [ { "target": "pick.choice" } ] }
    ]
  },
  "nodes": {
    "fast": { "block": "envelope", "mono": true, "set": { "attack_ms": 1, "release_ms": 40 }, "in": { "x": "in" } },
    "slow": { "block": "envelope", "mono": true, "set": { "attack_ms": 40, "release_ms": 300 }, "in": { "x": "in" } },
    "picks": { "block": "value", "mono": true },
    "onset": { "block": "formula", "mono": true, "set": { "expr": "(a - b * 1.2) * 40 * c" },
               "in": { "a": "fast", "b": "slow", "c": "picks" } },
    "ramp": { "block": "ramp", "in": { "trig": "onset" } },
    "start": { "block": "value", "mono": true },
    "octaves": { "block": "value", "mono": true },
    "khz": { "block": "formula", "mono": true, "set": { "expr": "min(b * exp2(a * c), 18) - 0.02" },
             "in": { "a": "ramp", "b": "start", "c": "octaves" } },
    "f": { "block": "svf", "set": { "freq": 20 }, "in": { "x": "in" } },
    "pick": { "block": "select", "in": { "a": "f:lp", "b": "f:bp" } },
    "level": { "block": "gain", "in": { "x": "pick" } }
  },
  "mods": {
    "track": { "from": "khz", "target": "f.freq", "amount": 1000 }
  },
  "out": "level"
}
