{"version":3,"sources":["_init.js","Player.js","Display/Video.js","Audio/Effect/Chorus.js","Audio/Effect/ConReverb.js","Audio/Effect/CutOff.js","Audio/Effect/Delay.js","Audio/Effect/Distortion.js","Audio/Effect/DubDelay.js","Audio/Effect/Equalizer.js","Audio/Effect/Fade.js","Audio/Effect/Flanger.js","Audio/Effect/Harmonizer.js","Audio/Effect/Noise.js","Audio/Effect/PingPongDelay.js","Audio/Effect/PitchShift.js","Audio/Effect/Reverb.js","Audio/Effect/StereoPanner.js","Audio/Effect/Tremolo.js","Audio/Input/Microphone.js","Audio/Output/Destination.js"],"names":["window","module","_class","_class2","_class3","_class4","_class5","_class6","_class7","_class8","_class9","_class10","_class11","_class12","_class13","_class14","_class15","_class16","_class17","_class18","_class19","_class20","async","imports","urls","sf","loader","mjs","Promise","all","map","v","import","exports","globalThis","Object","defineProperty","value","task","Blackprint","Environment","isBrowser","console","log","loadScope","url","hasInterface","hasDocs","Context","createContext","EventSlot","slot","objLength","obj","i","k","fakeDestination","ScarletsMedia","audioContext","createGain","gain","connect","destination","MediaEffect","Interface","init","iface","this","node","input","In","on","cable","audioInput","disconnect","customEffectFunctionBind","effect","data","prop","includes","func","constructor","Number","toFixed","enumerable","get","set","val","inputComp","which","whenChanged","now","name","toUpperCase","slice","port","createPort","default","insertComponent","registerNode","Node","instance","super","setInterface","title","output","AudioNode","Element","HTMLVideoElement","MediaStream","Port","StructOf","Video","type","MediaStreamTrack","handle","getVideoTracks","Audio","getAudioTracks","Duration","URL","String","Seek","Play","Trigger","play","Pause","pause","Stop","stop","registerInterface","IFace","Player","_paused","player","document","createElement","crossOrigin","preload","autoload","createMediaElementSource","oncanplay","captureStream","duration","onplay","src","currentTime","Sketch","template","VideoTrack","stream","IInput","IOutput","Input","Output","ref","My","cables","length","videoElement","trigger","disconnectAll","_playVideo","_videoElement","el","srcObject","paused","catch","$","ownerDocument","once","ev","addClass","description","mix","rate","intensity","ArrayOf","Out","Chorus","ScarletsMediaEffect","chorus","audioOutput","imported","Buffer","setBuffer","AudioBuffer","ConReverb","conReverb","frequency","width","CutOff","cutOff","time","feedback","Delay","delay","Distortion","distortion","cutoff","DubDelay","dubDelay","decibel","Equalizer","equalizer","Start","FadeIn","in","Volume","Time","Finish","out","Boolean","Types","Fade","fade","speed","depth","Flanger","flanger","pitch","slope","Harmonizer","harmonizer","Noise","noise","PingPongDelay","pingPongDelay","shift","PitchShift","pitchShift","decay","reverse","Reverb","reverb","StereoPanner","stereoPanner","Tremolo","tremolo","Microphone","selected","devices","_waitForInit","_refreshList","activate","undefined","startStream","stopStream","navigator","mediaDevices","enumerateDevices","list","ids","Set","kind","id","groupId","has","add","push","label","device","select","old","disableCables","success","callback","getUserMedia","audio","createMediaStreamSource","e","getTracks","forEach","track","Destination","hotReloaded"],"mappings":"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","file":"nodes-multimedia.mjs","sourcesContent":["// This script will run first, and then the other files\n// depends on blackprint.config.js configuration\n\nif(!window.Blackprint.Environment.isBrowser){\n\tconsole.log(\"@blackprint/nodes-multimedia is only for browser, nodes will not be registered\");\n\treturn;\n}\n\n// Prepare stuff when the page is loading\n// maybe like loading our dependencies for the nodes\n\n// Load dependencies\nawait imports([\n\t\"https://cdn.jsdelivr.net/npm/sfmediastream@latest\",\n\t// \"https://cdn.jsdelivr.net/npm/resonance-audio/build/resonance-audio.min.js\",\n]);\n\n// Because .js and .sf is separated\n// we also need to call loadScope just like _init.js\nlet Blackprint = window.Blackprint.loadScope({\n\t// You can find the URL on Blackprint menu -> Modules\n\t// This will also be exported to JSON if this module's nodes is being used\n\turl: import.meta.url,\n\n\t// This will autoload (*.sf.mjs) and (*.sf.css) file for Browser\n\thasInterface: true,\n\n\t// This will autoload (*.docs.json) for Browser\n\thasDocs: true,\n});\n\n// Global shared context\nlet Context = Blackprint.createContext('Multimedia');\n\n// This is needed to avoid duplicated event listener when using hot reload\n// Event listener that registered with same slot will be replaced\nContext.EventSlot = {slot: 'my-private-event-slot'};\n\n// Shared function\nContext.objLength = function objLength(obj){\n\tvar i = 0;\n\tfor(var k in obj) i++;\n\treturn i;\n}\n\n// To fix video sync bug\nvar fakeDestination = Context.fakeDestination = ScarletsMedia.audioContext.createGain();\nfakeDestination.gain.value = 0\nfakeDestination.connect(ScarletsMedia.audioContext.destination);\n\n// To be extended by Interface on /multimedia/effect\n// Don't immediately put in 'Context.MediaEffect = class MediaEffect {}'\n// Or the compiler will not soft hot reload the class prototype\n// We may need to migrate this to other file, because this file contains 'import.meta'\n// and it may broke when this file will be hot reloaded\nclass MediaEffect extends Blackprint.Interface {\n\tinit(){\n\t\tvar iface = this;\n\t\tvar node = this.node;\n\n\t\tiface.input.In.on('value', function({ cable }){\n\t\t\tcable.value.connect(iface.audioInput);\n\t\t})\n\t\t.on('disconnect', function({ cable }){\n\t\t\tcable.value.disconnect(iface.audioInput);\n\t\t});\n\t}\n};\n\nContext.MediaEffect = MediaEffect;\n\nfunction customEffectFunctionBind(iface){\n\tvar node = iface.node;\n\tvar effect = iface.effect;\n\tvar data = iface.data;\n\n\tfor(let prop in data){\n\t\tif(prop.includes('$'))\n\t\t\tcontinue;\n\n\t\tlet value = data[prop];\n\n\t\tlet func = effect[prop];\n\t\tif(value !== void 0)\n\t\t\tfunc(value);\n\t\telse value = data[prop] = func();\n\n\t\tif(value.constructor === Number)\n\t\t\tvalue = Number(value.toFixed(2));\n\n\t\tObject.defineProperty(data, prop, {\n\t\t\tenumerable:true,\n\t\t\tget(){ return value },\n\t\t\tset(val){ func(value = val) }\n\t\t});\n\n\t\tlet inputComp = {\n\t\t\twhich: prop,\n\t\t\tdata: iface.data,\n\t\t\twhenChanged(now){ func(value = now) }\n\t\t};\n\n\t\tvar name = prop[0].toUpperCase()+prop.slice(1);\n\n\t\tvar port = node.createPort('input', name, value.constructor);\n\t\tport.on('value', function({ cable }){\n\t\t\tdata[prop] = cable.value; // For data value\n\t\t\tinputComp.default = cable.value;\n\t\t\tfunc(cable.value); // For ScarletsMediaEffect value\n\t\t});\n\n\t\tport.insertComponent(null, 'comp-port-input', inputComp);\n\t}\n}","/**\n * Media player that can be used to play audio or video from an URL into streamable object.\n * Make sure CORS is enabled and configured properly if you want to use cross-domain URL\n * @blackprint node\n * @summary Multimedia media player\n */\nBlackprint.registerNode('Multimedia/Player',\nclass PlayerNode extends Blackprint.Node {\n\tstatic output = {\n\t\t/** You can connect this audio source to audio destination */\n\t\tAudioNode: AudioNode,\n\t\t/** Player's HTML element */\n\t\tElement: HTMLVideoElement,\n\t\t/** Can be used for obtaining audio or video stream */\n\t\tMediaStream: Blackprint.Port.StructOf(MediaStream, {\n\t\t\tVideo: {type: MediaStreamTrack, handle(data){ return data.getVideoTracks()[0] }},\n\t\t\tAudio: {type: MediaStreamTrack, handle(data){ return data.getAudioTracks()[0] }},\n\t\t}),\n\t\t/** Total duration of the media file */\n\t\tDuration: Number,\n\t};\n\n\tstatic input = {\n\t\t/** This can be Blob URL or remote URL */\n\t\tURL: String,\n\t\t/** Change the start point */\n\t\tSeek: Number,\n\t\t/** Play the media loaded into this player */\n\t\tPlay: Blackprint.Port.Trigger(function({ iface }){\n\t\t\tiface.play();\n\t\t}),\n\t\t/** Pause this player */\n\t\tPause: Blackprint.Port.Trigger(function({ iface }){\n\t\t\tiface.pause();\n\t\t}),\n\t\t/** Pause this player and reset the seek to default */\n\t\tStop: Blackprint.Port.Trigger(function({ iface }){\n\t\t\tiface.stop();\n\t\t}),\n\t}\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Player');\n\t\tiface.title = 'Media Player';\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Player',\nContext.IFace.Player = class PlayerIFace extends Blackprint.Interface {\n\tconstructor(node){\n\t\tsuper(node);\n\t\tthis._paused = true;\n\t\tthis.player = document.createElement('video');\n\t}\n\n\tinit(){\n\t\tlet iface = this;\n\t\tiface.player.crossOrigin = 'anonymouse';\n\t\tiface.player.preload = 'auto';\n\t\tiface.player.autoload = true;\n\n\t\tiface.node.output.Element = iface.player;\n\t\tiface.node.output.AudioNode = ScarletsMedia.audioContext.createMediaElementSource(iface.player);\n\n\t\t// Fix video sync\n\t\tiface.node.output.AudioNode.connect(fakeDestination);\n\n\t\t// Update tracks after the file is playable\n\t\tiface.player.oncanplay = function(){\n\t\t\tiface.node.output.MediaStream = iface.player.captureStream();\n\t\t\tiface.node.output.Duration = iface.player.duration;\n\t\t}\n\n\t\tiface.player.onplay = function(){\n\t\t\tif(iface._paused) iface.player.pause();\n\t\t}\n\n\t\tiface.input.URL.on('value', Context.EventSlot, function({ cable }){\n\t\t\tiface.player.src = cable.value;\n\t\t});\n\n\t\tiface.input.Seek.on('value', Context.EventSlot, function({ cable }){\n\t\t\tiface.player.currentTime = cable.value;\n\t\t});\n\t}\n\n\tplay(){\n\t\tthis._paused = false;\n\t\tthis.player.play();\n\t}\n\tpause(){\n\t\tthis._paused = true;\n\t\tthis.player.pause();\n\t}\n\tstop(){\n\t\tthis._paused = true;\n\t\tthis.player.pause();\n\t\tthis.player.currentTime = 0;\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Player', {\n\ttemplate: null\n}, Context.IFace.Player);","/**\n * Visualize video from a stream or video source\n * @blackprint node\n */\nBlackprint.registerNode('Multimedia/Display/Video',\nclass VideoNode extends Blackprint.Node {\n\tstatic input = {\n\t\t/** Visualize video from a MediaStream */\n\t\tMediaStream: MediaStream,\n\t\t/** Visualize video from a VideoTrack */\n\t\tVideoTrack: MediaStreamTrack,\n\t}\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Display/Video');\n\t\tiface.title = 'Video Visualization';\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Display/Video',\nContext.IFace.Video = class VideoIFace extends Blackprint.Interface {\n\tconstructor(node){\n\t\tsuper(node);\n\t\tthis.stream = null;\n\t}\n\n\t// Also put stream data on cloned node, or when HTML hot reload\n\tinit(){\n\t\tconst {\n\t\t\tIInput, IOutput, // Port interface\n\t\t\tInput, Output, // Port value\n\t\t} = this.ref;\n\n\t\tvar My = this;\n\n\t\tIInput.VideoTrack.on('value', Context.EventSlot, function({ cable }){\n\t\t\tIInput.MediaStream.disconnectAll();\n\n\t\t\tMy.stream = new MediaStream([cable.value]);\n\t\t\tMy._playVideo();\n\t\t});\n\n\t\tIInput.MediaStream.on('value', Context.EventSlot, function({ cable }){\n\t\t\tIInput.VideoTrack.disconnectAll();\n\n\t\t\tMy.stream = cable.value;\n\t\t\tMy._playVideo();\n\t\t});\n\n\t\tfunction disconnect(){\n\t\t\tif(IInput.VideoTrack.cables.length === 0 && IInput.MediaStream.cables.length === 0){\n\t\t\t\tMy.videoElement.trigger('pause', void 0, true);\n\t\t\t\tMy.videoElement.prop('srcObject', null);\n\t\t\t\tMy.stream = null;\n\t\t\t}\n\t\t}\n\n\t\tIInput.VideoTrack.on('disconnect', Context.EventSlot, disconnect);\n\t\tIInput.MediaStream.on('disconnect', Context.EventSlot, disconnect);\n\t}\n\n\t_playVideo(){\n\t\tlet val = this._videoElement;\n\t\tfor (let i=0; i < val.length; i++){\n\t\t\tlet el = val[i];\n\n\t\t\tif(el.srcObject === this.stream && !el.paused) continue;\n\n\t\t\tel.srcObject = this.stream;\n\t\t\tel.play().catch(function(){\n\t\t\t\t$(el.ownerDocument).once('pointerdown', ev => el.play());\n\t\t\t});\n\t\t}\n\t}\n\n\tget videoElement(){ return this._videoElement }\n\tset videoElement(val){\n\t\tif(val == null)\n\t\t\treturn this._videoElement = $([]);\n\n\t\tif(val.addClass === void 0)\n\t\t\tval = $(val);\n\n\t\tthis._videoElement = val;\n\t\tval.prop('srcObject', this.stream);\n\t\tthis._playVideo();\n\t}\n});","Blackprint.registerNode('Multimedia/Audio/Effect/Chorus',\nclass ChorusNode extends Blackprint.Node {\n\tstatic input = { In: Blackprint.Port.ArrayOf(AudioNode) };\n\tstatic output = { Out: AudioNode };\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Effect/Chorus');\n\n\t\tiface.title = 'Chorus';\n\t\tiface.description = 'Multimedia Effect';\n\n\t\tiface.data = {\n\t\t\tmix: 0.5,\n\t\t\trate: 0, // 0~1\n\t\t\tintensity: 0.75, // 0~1\n\t\t};\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Effect/Chorus',\nContext.IFace.Chorus = class ChorusIFace extends Context.MediaEffect {\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\tthis.effect = ScarletsMediaEffect.chorus();\n\t\tthis.audioInput = this.effect.input;\n\t\tthis.audioOutput = this.effect.output;\n\t}\n\n\tinit(){\n\t\tsuper.init(); // Call parent function\n\t\tthis.node.output.Out = this.audioOutput;\n\n\t\t// Custom bind for ScarletsFrame with ScarletsMediaEffect object\n\t\tcustomEffectFunctionBind(this);\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Audio/Effect/Chorus', {\n\ttemplate: null\n}, Context.IFace.Chorus);","Blackprint.registerNode('Multimedia/Audio/Effect/ConReverb',\nclass ConReverbNode extends Blackprint.Node {\n\tstatic input = {\n\t\tIn: Blackprint.Port.ArrayOf(AudioNode),\n\t\tBuffer: AudioBuffer,\n\t};\n\tstatic output = { Out: AudioNode };\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Effect/ConReverb');\n\n\t\tiface.title = 'ConReverb';\n\t\tiface.description = 'Multimedia Effect';\n\n\t\tiface.data = {\n\t\t\tmix: 0.5,\n\t\t};\n\t}\n\n\timported(){\n\t\tlet {Input, IInput} = this.ref;\n\t\tlet {iface} = this;\n\n\t\tIInput.Buffer.on('value', Context.EventSlot, function(ev){\n\t\t\tiface.effect.setBuffer(Input.Buffer);\n\t\t});\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Effect/ConReverb',\nContext.IFace.ConReverb = class ConReverbIFace extends Context.MediaEffect {\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\tthis.effect = ScarletsMediaEffect.conReverb();\n\t\tthis.audioInput = this.effect.input;\n\t\tthis.audioOutput = this.effect.output;\n\t}\n\n\tinit(){\n\t\tsuper.init(); // Call parent function\n\t\tthis.node.output.Out = this.audioOutput;\n\n\t\t// Custom bind for ScarletsFrame with ScarletsMediaEffect object\n\t\tcustomEffectFunctionBind(this);\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Audio/Effect/ConReverb', {\n\ttemplate: null\n}, Context.IFace.ConReverb);","Blackprint.registerNode('Multimedia/Audio/Effect/CutOff',\nclass CutOffNode extends Blackprint.Node {\n\tstatic input = { In: Blackprint.Port.ArrayOf(AudioNode) };\n\tstatic output = { Out: AudioNode };\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Effect/CutOff');\n\n\t\tiface.title = 'CutOff';\n\t\tiface.description = 'Multimedia Effect';\n\n\t\tiface.data = {\n\t\t\ttype: 'lowpass', // lowpass | highpass | midpass\n\t\t\tfrequency: 350, // Filter node's frequency value\n\t\t\twidth: 1, // Filter node's Q value\n\t\t};\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Effect/CutOff',\nContext.IFace.CutOff = class CutOffIFace extends Context.MediaEffect {\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\tthis.effect = ScarletsMediaEffect.cutOff();\n\t\tthis.audioInput = this.effect.input;\n\t\tthis.audioOutput = this.effect.output;\n\t}\n\n\tinit(){\n\t\tsuper.init(); // Call parent function\n\t\tthis.node.output.Out = this.audioOutput;\n\n\t\t// Custom bind for ScarletsFrame with ScarletsMediaEffect object\n\t\tcustomEffectFunctionBind(this);\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Audio/Effect/CutOff', {\n\ttemplate: null\n}, Context.IFace.CutOff);","Blackprint.registerNode('Multimedia/Audio/Effect/Delay',\nclass DelayNode extends Blackprint.Node {\n\tstatic input = { In: Blackprint.Port.ArrayOf(AudioNode) };\n\tstatic output = { Out: AudioNode };\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Effect/Delay');\n\n\t\tiface.title = 'Delay';\n\t\tiface.description = 'Multimedia Effect';\n\n\t\tiface.data = {\n\t\t\tmix: 0.5, // 0 ~ 1\n\t\t\ttime: 0.3, // 0 ~ 180\n\t\t\tfeedback: 0.5, // 0 ~ 1\n\t\t};\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Effect/Delay',\nContext.IFace.Delay = class DelayIFace extends Context.MediaEffect {\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\tthis.effect = ScarletsMediaEffect.delay();\n\t\tthis.audioInput = this.effect.input;\n\t\tthis.audioOutput = this.effect.output;\n\t}\n\n\tinit(){\n\t\tsuper.init(); // Call parent function\n\t\tthis.node.output.Out = this.audioOutput;\n\n\t\t// Custom bind for ScarletsFrame with ScarletsMediaEffect object\n\t\tcustomEffectFunctionBind(this);\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Audio/Effect/Delay', {\n\ttemplate: null\n}, Context.IFace.Delay);","Blackprint.registerNode('Multimedia/Audio/Effect/Distortion',\nclass DistortionNode extends Blackprint.Node {\n\tstatic input = { In: Blackprint.Port.ArrayOf(AudioNode) };\n\tstatic output = { Out: AudioNode };\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Effect/Distortion');\n\n\t\tiface.title = 'Distortion';\n\t\tiface.description = 'Multimedia Effect';\n\n\t\tiface.data = {\n\t\t\tset: 0.5, // 0 ~ 1\n\t\t};\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Effect/Distortion',\nContext.IFace.Distortion = class DistortionIFace extends Context.MediaEffect {\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\tthis.effect = ScarletsMediaEffect.distortion();\n\t\tthis.audioInput = this.effect.input;\n\t\tthis.audioOutput = this.effect.output;\n\t}\n\n\tinit(){\n\t\tsuper.init(); // Call parent function\n\t\tthis.node.output.Out = this.audioOutput;\n\n\t\t// Custom bind for ScarletsFrame with ScarletsMediaEffect object\n\t\tcustomEffectFunctionBind(this);\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Audio/Effect/Distortion', {\n\ttemplate: null\n}, Context.IFace.Distortion);","Blackprint.registerNode('Multimedia/Audio/Effect/DubDelay',\nclass DubDelayNode extends Blackprint.Node {\n\tstatic input = { In: Blackprint.Port.ArrayOf(AudioNode) };\n\tstatic output = { Out: AudioNode };\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Effect/DubDelay');\n\n\t\tiface.title = 'DubDelay';\n\t\tiface.description = 'Multimedia Effect';\n\n\t\tiface.data = {\n\t\t\tmix: 0.5, // 0 ~ 1\n\t\t\ttime: 0.7, // 0 ~ 180\n\t\t\tfeedback: 0.5, // 0 ~ 1\n\t\t\tcutoff: 700, // 0 ~ 4000\n\t\t};\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Effect/DubDelay',\nContext.IFace.DubDelay = class DubDelayIFace extends Context.MediaEffect {\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\tthis.effect = ScarletsMediaEffect.dubDelay();\n\t\tthis.audioInput = this.effect.input;\n\t\tthis.audioOutput = this.effect.output;\n\t}\n\n\tinit(){\n\t\tsuper.init(); // Call parent function\n\t\tthis.node.output.Out = this.audioOutput;\n\n\t\t// Custom bind for ScarletsFrame with ScarletsMediaEffect object\n\t\tcustomEffectFunctionBind(this);\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Audio/Effect/DubDelay', {\n\ttemplate: null\n}, Context.IFace.DubDelay);","// ToDo: Fix this and add support for adding more ports to control frequency\n\nBlackprint.registerNode('Multimedia/Audio/Effect/Equalizer',\nclass EqualizerNode extends Blackprint.Node {\n\tstatic input = { In: Blackprint.Port.ArrayOf(AudioNode) };\n\tstatic output = { Out: AudioNode };\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Effect/Equalizer');\n\n\t\tiface.title = 'Equalizer';\n\t\tiface.description = 'Multimedia Effect';\n\n\t\tiface.data = {\n\t\t\tfrequency: 0.7,\n\t\t\tdecibel: 0.5, // -20 ~ 20\n\t\t};\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Effect/Equalizer',\nContext.IFace.Equalizer = class EqualizerIFace extends Context.MediaEffect {\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\tthis.effect = ScarletsMediaEffect.equalizer();\n\t\tthis.audioInput = this.effect.input;\n\t\tthis.audioOutput = this.effect.output;\n\t}\n\n\tinit(){\n\t\tsuper.init(); // Call parent function\n\t\tthis.node.output.Out = this.audioOutput;\n\n\t\t// Custom bind for ScarletsFrame with ScarletsMediaEffect object\n\t\tcustomEffectFunctionBind(this);\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Audio/Effect/Equalizer', {\n\ttemplate: null\n}, Context.IFace.Equalizer);","Blackprint.registerNode('Multimedia/Audio/Effect/Fade',\nclass FadeNode extends Blackprint.Node {\n\tstatic input = {\n\t\tIn: Blackprint.Port.ArrayOf(AudioNode),\n\t\tStart: Blackprint.Port.Trigger(function({ iface }){\n\t\t\tlet node = iface.node;\n\t\t\tlet input = node.input;\n\n\t\t\tif(input.FadeIn)\n\t\t\t\tiface.effect.in(input.Volume, input.Time, node.output.Finish);\n\t\t\telse iface.effect.out(input.Volume, input.Time, node.output.Finish);\n\t\t}),\n\t\tFadeIn: Boolean,\n\t\tVolume: Number,\n\t\tTime: Number,\n\t};\n\n\tstatic output = {\n\t\tOut: AudioNode,\n\t\tFinish: Blackprint.Types.Trigger\n\t};\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Effect/Fade');\n\n\t\tiface.title = 'Fade';\n\t\tiface.description = 'Multimedia Effect';\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Effect/Fade',\nContext.IFace.Fade = class FadeIFace extends Context.MediaEffect {\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\tthis.effect = ScarletsMediaEffect.fade();\n\t\tthis.audioInput = this.effect.input;\n\t\tthis.audioOutput = this.effect.output;\n\t}\n\n\tinit(){\n\t\tsuper.init(); // Call parent function\n\t\tthis.node.output.Out = this.audioOutput;\n\n\t\t// Custom bind for ScarletsFrame with ScarletsMediaEffect object\n\t\tcustomEffectFunctionBind(this);\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Audio/Effect/Fade', {\n\ttemplate: null\n}, Context.IFace.Fade);","Blackprint.registerNode('Multimedia/Audio/Effect/Flanger',\nclass FlangerNode extends Blackprint.Node {\n\tstatic input = { In: Blackprint.Port.ArrayOf(AudioNode) };\n\tstatic output = { Out: AudioNode };\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Effect/Flanger');\n\n\t\tiface.title = 'Flanger';\n\t\tiface.description = 'Multimedia Effect';\n\n\t\tiface.data = {\n\t\t\tmix: 0.5, // 0 ~ 1\n\t\t\ttime: 0.45, // 0 ~ 1\n\t\t\tspeed: 0.2, // 0 ~ 1\n\t\t\tdepth: 0.1, // 0 ~ 1\n\t\t\tfeedback: 1.1, // 0 ~ 1\n\t\t};\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Effect/Flanger',\nContext.IFace.Flanger = class FlangerIFace extends Context.MediaEffect {\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\tthis.effect = ScarletsMediaEffect.flanger();\n\t\tthis.audioInput = this.effect.input;\n\t\tthis.audioOutput = this.effect.output;\n\t}\n\n\tinit(){\n\t\tsuper.init(); // Call parent function\n\t\tthis.node.output.Out = this.audioOutput;\n\n\t\t// Custom bind for ScarletsFrame with ScarletsMediaEffect object\n\t\tcustomEffectFunctionBind(this);\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Audio/Effect/Flanger', {\n\ttemplate: null\n}, Context.IFace.Flanger);","Blackprint.registerNode('Multimedia/Audio/Effect/Harmonizer',\nclass HarmonizerNode extends Blackprint.Node {\n\tstatic input = { In: Blackprint.Port.ArrayOf(AudioNode) };\n\tstatic output = { Out: AudioNode };\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Effect/Harmonizer');\n\n\t\tiface.title = 'Harmonizer';\n\t\tiface.description = 'Multimedia Effect';\n\n\t\tiface.data = {\n\t\t\tpitch: 34, // 0 ~ 1\n\t\t\tslope: 0.65, // 0 ~ 1\n\t\t\twidth: 0.15, // 0 ~ 1\n\t\t};\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Effect/Harmonizer',\nContext.IFace.Harmonizer = class HarmonizerIFace extends Context.MediaEffect {\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\tthis.effect = ScarletsMediaEffect.harmonizer();\n\t\tthis.audioInput = this.effect.input;\n\t\tthis.audioOutput = this.effect.output;\n\t}\n\n\tinit(){\n\t\tsuper.init(); // Call parent function\n\t\tthis.node.output.Out = this.audioOutput;\n\n\t\t// Custom bind for ScarletsFrame with ScarletsMediaEffect object\n\t\tcustomEffectFunctionBind(this);\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Audio/Effect/Harmonizer', {\n\ttemplate: null\n}, Context.IFace.Harmonizer);","Blackprint.registerNode('Multimedia/Audio/Effect/Noise',\nclass NoiseNode extends Blackprint.Node {\n\tstatic input = { In: Blackprint.Port.ArrayOf(AudioNode) };\n\tstatic output = { Out: AudioNode };\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Effect/Noise');\n\n\t\tiface.title = 'Noise';\n\t\tiface.description = 'Multimedia Effect';\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Effect/Noise',\nContext.IFace.Noise = class NoiseIFace extends Context.MediaEffect {\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\tthis.effect = ScarletsMediaEffect.noise();\n\t\tthis.audioInput = this.effect.input;\n\t\tthis.audioOutput = this.effect.output;\n\t}\n\n\tinit(){\n\t\tsuper.init(); // Call parent function\n\t\tthis.node.output.Out = this.audioOutput;\n\n\t\t// Custom bind for ScarletsFrame with ScarletsMediaEffect object\n\t\tcustomEffectFunctionBind(this);\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Audio/Effect/Noise', {\n\ttemplate: null\n}, Context.IFace.Noise);","Blackprint.registerNode('Multimedia/Audio/Effect/PingPongDelay',\nclass PingPongDelayNode extends Blackprint.Node {\n\tstatic input = { In: Blackprint.Port.ArrayOf(AudioNode) };\n\tstatic output = { Out: AudioNode };\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Effect/PingPongDelay');\n\n\t\tiface.title = 'PingPongDelay';\n\t\tiface.description = 'Multimedia Effect';\n\n\t\tiface.data = {\n\t\t\tmix: 0.5,\n\t\t\ttime: 0.3, // 0~180\n\t\t\tfeedback: 0.5, // 0~1\n\t\t};\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Effect/PingPongDelay',\nContext.IFace.PingPongDelay = class PingPongDelayIFace extends Context.MediaEffect {\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\tthis.effect = ScarletsMediaEffect.pingPongDelay();\n\t\tthis.audioInput = this.effect.input;\n\t\tthis.audioOutput = this.effect.output;\n\t}\n\n\tinit(){\n\t\tsuper.init(); // Call parent function\n\t\tthis.node.output.Out = this.audioOutput;\n\n\t\t// Custom bind for ScarletsFrame with ScarletsMediaEffect object\n\t\tcustomEffectFunctionBind(this);\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Audio/Effect/PingPongDelay', {\n\ttemplate: null\n}, Context.IFace.PingPongDelay);","Blackprint.registerNode('Multimedia/Audio/Effect/PitchShift',\nclass PitchShiftNode extends Blackprint.Node {\n\tstatic input = { In: Blackprint.Port.ArrayOf(AudioNode) };\n\tstatic output = { Out: AudioNode };\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Effect/PitchShift');\n\n\t\tiface.title = 'PitchShift';\n\t\tiface.description = 'Multimedia Effect';\n\n\t\tiface.data = {\n\t\t\tshift: 0, // -3 ~ 3\n\t\t};\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Effect/PitchShift',\nContext.IFace.PitchShift = class PitchShiftIFace extends Context.MediaEffect {\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\tthis.effect = ScarletsMediaEffect.pitchShift();\n\t\tthis.audioInput = this.effect.input;\n\t\tthis.audioOutput = this.effect.output;\n\t}\n\n\tinit(){\n\t\tsuper.init(); // Call parent function\n\t\tthis.node.output.Out = this.audioOutput;\n\n\t\t// Custom bind for ScarletsFrame with ScarletsMediaEffect object\n\t\tcustomEffectFunctionBind(this);\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Audio/Effect/PitchShift', {\n\ttemplate: null\n}, Context.IFace.PitchShift);","Blackprint.registerNode('Multimedia/Audio/Effect/Reverb',\nclass ReverbNode extends Blackprint.Node {\n\tstatic input = { In: Blackprint.Port.ArrayOf(AudioNode) };\n\tstatic output = { Out: AudioNode };\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Effect/Reverb');\n\n\t\tiface.title = 'Reverb';\n\t\tiface.description = 'Multimedia Effect';\n\n\t\tiface.data = {\n\t\t\tmix: 1, // 0 ~ 1\n\t\t\ttime: 1, // 0 ~ 3\n\t\t\tdecay: 0.1, // 0 ~ 3\n\t\t\treverse: false, // boolean\n\t\t};\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Effect/Reverb',\nContext.IFace.Reverb = class ReverbIFace extends Context.MediaEffect {\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\tthis.effect = ScarletsMediaEffect.reverb();\n\t\tthis.audioInput = this.effect.input;\n\t\tthis.audioOutput = this.effect.output;\n\t}\n\n\tinit(){\n\t\tsuper.init(); // Call parent function\n\t\tthis.node.output.Out = this.audioOutput;\n\n\t\t// Custom bind for ScarletsFrame with ScarletsMediaEffect object\n\t\tcustomEffectFunctionBind(this);\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Audio/Effect/Reverb', {\n\ttemplate: null\n}, Context.IFace.Reverb);","Blackprint.registerNode('Multimedia/Audio/Effect/StereoPanner',\nclass StereoPannerNode extends Blackprint.Node {\n\tstatic input = { In: Blackprint.Port.ArrayOf(AudioNode) };\n\tstatic output = { Out: AudioNode };\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Effect/StereoPanner');\n\n\t\tiface.title = 'StereoPanner';\n\t\tiface.description = 'Multimedia Effect';\n\n\t\tiface.data = {\n\t\t\tset: 1, // 0 ~ 1\n\t\t};\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Effect/StereoPanner',\nContext.IFace.StereoPanner = class StereoPannerIFace extends Context.MediaEffect {\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\tthis.effect = ScarletsMediaEffect.stereoPanner();\n\t\tthis.audioInput = this.effect.input;\n\t\tthis.audioOutput = this.effect.output;\n\t}\n\n\tinit(){\n\t\tsuper.init(); // Call parent function\n\t\tthis.node.output.Out = this.audioOutput;\n\n\t\t// Custom bind for ScarletsFrame with ScarletsMediaEffect object\n\t\tcustomEffectFunctionBind(this);\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Audio/Effect/StereoPanner', {\n\ttemplate: null\n}, Context.IFace.StereoPanner);","Blackprint.registerNode('Multimedia/Audio/Effect/Tremolo',\nclass TremoloNode extends Blackprint.Node {\n\tstatic input = { In: Blackprint.Port.ArrayOf(AudioNode) };\n\tstatic output = { Out: AudioNode };\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Effect/Tremolo');\n\n\t\tiface.title = 'Tremolo';\n\t\tiface.description = 'Multimedia Effect';\n\n\t\tiface.data = {\n\t\t\tmix: 0.8, // 0 ~ 1\n\t\t\tspeed: 0.2, // 0 ~ 3\n\t\t\tdepth: 1, // 0 ~ 3\n\t\t};\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Effect/Tremolo',\nContext.IFace.Tremolo = class TremoloIFace extends Context.MediaEffect {\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\tthis.effect = ScarletsMediaEffect.tremolo();\n\t\tthis.audioInput = this.effect.input;\n\t\tthis.audioOutput = this.effect.output;\n\t}\n\n\tinit(){\n\t\tsuper.init(); // Call parent function\n\t\tthis.node.output.Out = this.audioOutput;\n\n\t\t// Custom bind for ScarletsFrame with ScarletsMediaEffect object\n\t\tcustomEffectFunctionBind(this);\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Audio/Effect/Tremolo', {\n\ttemplate: null\n}, Context.IFace.Tremolo);","/**\n * Obtain audio source from your microphone input\n * @blackprint node\n */\nBlackprint.registerNode('Multimedia/Audio/Input/Microphone',\nclass MicrophoneNode extends Blackprint.Node {\n\t// Blackprint Node Output\n\tstatic output = {\n\t\t/** AudioNode that stream the microphone data */\n\t\tNode: AudioNode,\n\t};\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Input/Microphone');\n\t\tiface.title = 'Microphone';\n\t}\n});\n\n// Interface-> BPIC/Multimedia/Audio/Input/Microphone\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Input/Microphone',\nContext.IFace.Microphone = class MicrophoneIFace extends Blackprint.Interface {\n\tconstructor(node){\n\t\tsuper(node);\n\n\t\tthis.selected = 0; // Default, first option\n\t\tthis.devices = [];\n\t\tthis._waitForInit = false;\n\t\tthis.stream = null;\n\t}\n\n\tinit(){\n\t\tlet iface = this;\n\t\tiface._refreshList();\n\n\t\tiface.output.Node\n\t\t\t.on('connecting', Context.EventSlot, function({ port, activate }){\n\t\t\t\t// undefined = Mark cable connection as disabled\n\t\t\t\t// true = Mark cable connection as enabled\n\t\t\t\t// false = Mark cable connection as failed\n\t\t\t\tactivate(undefined);\n\t\t\t\tiface.startStream(activate); // Callback\n\t\t\t})\n\t\t\t.on('disconnect', Context.EventSlot, function(){\n\t\t\t\t// Stop any stream when it doesn't have cable anymore\n\t\t\t\tif(iface.output.Node.cables.length === 0)\n\t\t\t\t\tiface.stopStream();\n\t\t\t});\n\t}\n\n\tasync _refreshList(){\n\t\tlet devices = await navigator.mediaDevices.enumerateDevices();\n\t\tvar list = [];\n\t\tvar ids = new Set();\n\n\t\tfor (var i = 0; i < devices.length; i++) {\n\t\t\tif(devices[i].kind === 'audioinput'){ // Microphone only\n\t\t\t\t// Avoid duplicate\n\t\t\t\tvar id = devices[i].groupId;\n\t\t\t\tif(id){\n\t\t\t\t\tif(ids.has(id)) continue;\n\t\t\t\t\tids.add(id);\n\t\t\t\t}\n\n\t\t\t\tlist.push({\n\t\t\t\t\ti: list.length,\n\t\t\t\t\tlabel: (devices[i].label || 'Device'),\n\t\t\t\t\tdevice: devices[i]\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tthis.devices = list; // Put them here, ScarletsFrame will handle the HTML binding\n\t\tthis._waitForInit && this._waitForInit();\n\t}\n\n\tselect(which){\n\t\tif(this.selected === which) return;\n\t\tlet old = this.selected;\n\n\t\tthis.selected = which;\n\t\tthis.stopStream();\n\n\t\tlet iface = this;\n\t\tiface.output.Node.disableCables(true);\n\t\tthis.startStream(function(success){\n\t\t\tif(!success) return this.selected = old;\n\n\t\t\t// Only reset when success\n\t\t\tiface.output.Node.disableCables(false);\n\t\t});\n\t}\n\n\tasync startStream(callback){\n\t\tvar selected = this.devices[this.selected].device;\n\t\tif(this.stream !== null)\n\t\t\treturn callback(true);\n\n\t\tif(this.devices.length === 0){\n\t\t\t// Wait for initialization\n\t\t\tthis._waitForInit = function(){\n\t\t\t\tthis.startStream(callback);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.stream = await navigator.mediaDevices.getUserMedia({audio: selected});\n\t\t\tthis.node.output.Node = ScarletsMedia.audioContext.createMediaStreamSource(this.stream);\n\n\t\t\t// Refresh again in case if the list was changed after user\n\t\t\t// give the permission\n\t\t\tthis._refreshList();\n\t\t\tcallback(true);\n\t\t} catch(e) {\n\t\t\tcallback(false);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tstopStream(){\n\t\tif(this.stream === null)\n\t\t\treturn;\n\n\t\tthis.stream.getTracks().forEach(track=> track.stop());\n\t\tthis.stream = null;\n\t}\n});","// ToDo: implement w3c draft after it's available for multi target audio output\n// https://www.w3.org/TR/audio-output/\n\n/**\n * Send the audio output to destination\n * This may be your speaker or default output devices\n * @blackprint node\n * @summary Audio output\n */\nBlackprint.registerNode('Multimedia/Audio/Output/Destination',\nclass DestinationNode extends Blackprint.Node {\n\tstatic input = {\n\t\t/** AudioNode that can be from from Microphone, Effects, etc */\n\t\tIn: Blackprint.Port.ArrayOf(AudioNode),\n\t};\n\n\tconstructor(instance){\n\t\tsuper(instance);\n\n\t\tlet iface = this.setInterface('BPIC/Multimedia/Audio/Output/Destination');\n\t\tiface.title = 'Destination';\n\t}\n});\n\nBlackprint.registerInterface('BPIC/Multimedia/Audio/Output/Destination',\nContext.IFace.Destination = class DestinationIFace extends Blackprint.Interface {\n\tinit(){\n\t\tvar destination = ScarletsMedia.audioContext.destination;\n\t\tlet iface = this;\n\n\t\tiface.on('cable.connect', Context.EventSlot, function({ port, cable }){\n\t\t\tif(port === iface.input.In)\n\t\t\t\tcable.value.connect(destination);\n\t\t});\n\n\t\tiface.on('cable.disconnect', Context.EventSlot, function({ port, cable }){\n\t\t\tif(port === iface.input.In)\n\t\t\t\tcable.value.disconnect(destination);\n\t\t});\n\t}\n\n\thotReloaded(){\n\t\tthis.init();\n\t}\n});\n\n// For Sketch Editor (use default UI, and use similar interface)\nBlackprint.Sketch.registerInterface('BPIC/Multimedia/Audio/Output/Destination', {\n\ttemplate: null\n}, Context.IFace.Destination);"]}