node-red-contrib-music
Version:
Synthesise music with node-red. The beat node creates regular beats at a rate you can control, and which can be sunchronised with other machines. The divider node adds information to beat events, dividing beats into bars, bars into phrases, phrases into s
1 lines • 3.78 kB
JSON
[{"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":[]}]