[{"id":"7a7d4d3b.7a52d4","type":"regression","z":"c92ed898.fa0328","name":"midi2cv","dataSetSize":0,"regressionType":"linear","polynomialOrder":"1","precision":"4","xInputField":"midi","xInputFieldType":"msg","yInputField":"cv","yInputFieldType":"msg","yOutputField":"payload","yOutputFieldType":"msg","functionOutputField":"","functionOutputFieldType":"none","resultOnly":true,"x":520,"y":100,"wires":[["c07deafb.5391f8"]]},{"id":"e54c98e5.2c8ae8","type":"function","z":"c92ed898.fa0328","name":"modular tuner","func":"// to be used with a regression node\n// two outputs: first one goes to regression node\n// second one goes to PWM node\n// the regression node should also send its output to the PWM node\n\n\nvar tuning = context.get(\"tuning\") || false;\nvar cvlist = context.get(\"cvlist\");\nif(!cvlist){\n    cvlist = [];\n    for(let i =1; i<=99; i+=2){\n        cvlist.push(i);\n    }\n    context.set(\"cvlist\", cvlist);\n}\n\nvar cvpos = context.get(\"cvpos\"); // position in cvlist\n\n//node.warn(\"Started modular tuner\");\n//node.warn(msg);\n\nif (tuning) {\n//    node.warn(\"Tuning\");\n    if(msg.topic == \"/pitch\"){\n        var pitch = msg.payload;\n//        node.warn(\"received pitch \" + pitch + \" cvpos \" + cvpos);\n        if (cvpos >= 0) {\n            // send the received pitch on to the regression node\n            var regressionMsg = {cv: cvlist[cvpos], midi: pitch};\n            node.send([regressionMsg,null]);\n        }\n        cvpos++;\n        context.set(\"cvpos\", cvpos);\n\n        if (cvpos < cvlist.length) {\n            // send the new cv on to the pwm node\n            msg.payload = cvlist[cvpos];\n            return [null, msg];\n            \n        } else {\n// back to doing nothing\n            context.set(\"tuning\", false);\n        }\n        return [null, null];\n    } else {\n        // don't do anything with other requests while tuning\n        return [null, null]; \n    }\n}\nelse{\n//    node.warn(\"Not tuning\");\n    if (msg.topic == \"/pitch\") {\n//        node.warn(\"received pitch, doing nothing\");\n        // don't do anything with incoming pitch information while not tuning\n        return [null,null];\n    } else if (msg.payload == \"tune\") {\n        // start tuning\n        context.set(\"tuning\", true);\n        context.set(\"cvpos\",-1);\n        return [null, null];\n    } else {\n        return [null, null];\n    }\n}\n","outputs":2,"noerr":0,"x":265,"y":142,"wires":[["7a7d4d3b.7a52d4"],["c07deafb.5391f8"]]},{"id":"aff152c.921f8b","type":"inject","z":"c92ed898.fa0328","name":"","topic":"","payload":"tune","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":70,"y":120,"wires":[["e54c98e5.2c8ae8"]]},{"id":"44c17957.a04508","type":"osc","z":"c92ed898.fa0328","name":"","path":"","metadata":false,"x":110,"y":180,"wires":[["e54c98e5.2c8ae8","abdd7b73.e43f08"]]},{"id":"43fb494.ffc00b8","type":"udp in","z":"c92ed898.fa0328","name":"","iface":"","port":"3000","ipv":"udp4","multicast":"false","group":"","datatype":"buffer","x":60,"y":240,"wires":[["44c17957.a04508"]]},{"id":"162ac8ae.921f57","type":"change","z":"c92ed898.fa0328","name":"","rules":[{"t":"set","p":"midi","pt":"msg","to":"(msg.note - 4)*2 + 70","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":230,"y":80,"wires":[["7a7d4d3b.7a52d4"]]},{"id":"abdd7b73.e43f08","type":"debug","z":"c92ed898.fa0328","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":300,"y":200,"wires":[]},{"id":"c07deafb.5391f8","type":"pi-gpiod out","z":"c92ed898.fa0328","name":"","host":"192.168.2.8","port":8888,"pin":"18","set":"","level":"0","out":"hwpwm","sermin":"1000","sermax":"2000","x":720,"y":160,"wires":[]}]