@blibliki/engine 0.3.9 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs DELETED
@@ -1,2 +0,0 @@
1
- "use strict";var ut=Object.create;var oe=Object.defineProperty;var pt=Object.getOwnPropertyDescriptor;var dt=Object.getOwnPropertyNames;var at=Object.getPrototypeOf,lt=Object.prototype.hasOwnProperty;var ct=(r,e)=>{for(var t in e)oe(r,t,{get:e[t],enumerable:!0})},Ae=(r,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of dt(e))!lt.call(r,i)&&i!==t&&oe(r,i,{get:()=>e[i],enumerable:!(o=pt(e,i))||o.enumerable});return r};var mt=(r,e,t)=>(t=r!=null?ut(at(r)):{},Ae(e||!r||!r.__esModule?oe(t,"default",{value:r,enumerable:!0}):t,r)),Mt=r=>Ae(oe({},"__esModule",{value:!0}),r);var bt={};ct(bt,{Context:()=>st.Context,Engine:()=>x,MidiDevice:()=>v,MidiMappingMode:()=>ue,MidiPortState:()=>q,ModuleType:()=>Z,Note:()=>a,OscillatorWave:()=>Q,TransportState:()=>nt.TransportState,moduleSchemas:()=>pe});module.exports=Mt(bt);var rt=require("@blibliki/transport"),S=require("@blibliki/utils");var ne=require("@blibliki/utils");var Ce=require("@blibliki/utils"),be=require("es-toolkit");var ie=require("@blibliki/utils");var m=class{id;engineId;moduleType;audioModules;inputs;outputs;monoModuleConstructor;_props;_voices;_name;pendingUIUpdates=!1;constructor(e,t){let{id:o,name:i,moduleType:n,voices:s,monoModuleConstructor:d,props:u}=t;this.audioModules=[],this.monoModuleConstructor=d,this.id=o??(0,ie.uuidv4)(),this.engineId=e,this.name=i,this.moduleType=n,this._props=u,this.inputs=new O(this),this.outputs=new C(this),queueMicrotask(()=>{this.voices=s||1,this.props=u})}get name(){return this._name}set name(e){this._name=e,this.audioModules.forEach(t=>t.name=e)}get props(){return this._props}set props(e){this._props={...this._props,...e},this.audioModules.forEach(t=>t.props=e)}get voices(){return this._voices}set voices(e){this._voices=e,this.adjustNumberOfModules(),this.rePlugAll()}start(e){this.audioModules.forEach(t=>{t.start(e)})}stop(e){this.audioModules.forEach(t=>{t.stop(e)})}serialize(){return{id:this.id,name:this.name,moduleType:this.moduleType,voices:this.voices,props:this.props,inputs:this.inputs.serialize(),outputs:this.outputs.serialize()}}plug({audioModule:e,from:t,to:o}){let i=this.outputs.findByName(t),n=e.inputs.findByName(o);i.plug(n)}rePlugAll(e){this.inputs.rePlugAll(e),this.outputs.rePlugAll(e)}unPlugAll(){this.inputs.unPlugAll(),this.outputs.unPlugAll()}dispose(){this.inputs.unPlugAll(),this.outputs.unPlugAll(),this.audioModules.forEach(e=>{e.dispose()})}onMidiEvent=e=>{let t=e.voiceNo??0;this.findVoice(t).onMidiEvent(e)};triggerPropsUpdate=()=>{this.pendingUIUpdates||(this.pendingUIUpdates=!0,this.sheduleTriggerUpdate())};sheduleTriggerUpdate(){requestAnimationFrame(()=>{this.engine._triggerPropsUpdate({id:this.id,moduleType:this.moduleType,voices:this.voices,name:this.name,props:this.props}),this.pendingUIUpdates=!1})}findVoice(e){let t=this.audioModules.find(o=>o.voiceNo===e);if(!t)throw Error(`Voice ${e} on module ${this.name} not found`);return t}registerDefaultIOs(e="both"){this.registerMidiInput({name:"midi in",onMidiEvent:this.onMidiEvent}),(e==="in"||e==="both")&&this.registerAudioInput({name:"in"}),(e==="out"||e==="both")&&this.registerAudioOutput({name:"out"})}registerAudioInput(e){return this.inputs.add({...e,ioType:"polyAudioInput"})}registerAudioOutput(e){return this.outputs.add({...e,ioType:"polyAudioOutput"})}registerMidiInput(e){return this.inputs.add({...e,ioType:"midiInput"})}registerMidiOutput(e){return this.outputs.add({...e,ioType:"midiOutput"})}adjustNumberOfModules(){if(this.audioModules.length!==this.voices){if(this.audioModules.length>this.voices)this.audioModules.pop()?.dispose();else{let e=this.audioModules.length,t=(0,ie.deterministicId)(this.id,e.toString()),o=this.monoModuleConstructor(this.engineId,{id:t,name:this.name,moduleType:this.moduleType,voiceNo:e,props:{...this.props}});this.audioModules.push(o)}this.adjustNumberOfModules()}}get engine(){return x.getById(this.engineId)}get context(){return this.engine.context}};var Oe=require("@blibliki/utils");var le=class{id;ioType;name;module;connections;constructor(e,t){this.module=e,this.name=t.name,this.ioType=t.ioType,this.id=(0,Oe.deterministicId)(this.module.id,this.name),this.connections=[]}plug(e,t=!0){this.connections.push(e),t&&e.plug(this,!1)}unPlug(e,t=!0){this.connections=this.connections.filter(o=>o.id!==e.id),t&&e.unPlug(this,!1)}rePlugAll(e){let t=this.connections;this.unPlugAll(),e&&e(),t.forEach(o=>{this.plug(o)})}unPlugAll(){this.connections.forEach(e=>{this.unPlug(e)})}isAudio(){return this.ioType==="audioInput"||this.ioType==="audioOutput"||this.ioType==="polyAudioInput"||this.ioType==="polyAudioOutput"}isMidi(){return this.ioType==="midiInput"||this.ioType==="midiOutput"}serialize(){return{id:this.id,name:this.name,ioType:this.ioType,moduleId:this.module.id}}},g=class extends le{plug(e,t){super.plug(e,t)}unPlug(e,t){super.unPlug(e,t)}};var P=class extends g{plug(e,t=!0){super.plug(e,t),!(!t&&e instanceof b)&&re(this,e,!0)}unPlug(e,t=!0){super.unPlug(e,t),!(!t&&e instanceof b)&&re(this,e,!1)}findIOByVoice(e){return this.module.findVoice(e).inputs.findByName(this.name)}},b=class extends g{plug(e,t=!0){super.plug(e,t),!(!t&&e instanceof P)&&re(this,e,!0)}unPlug(e,t=!0){super.unPlug(e,t),!(!t&&e instanceof P)&&re(this,e,!1)}findIOByVoice(e){return this.module.findVoice(e).outputs.findByName(this.name)}};function re(r,e,t){if(e instanceof P||e instanceof b){let o=Math.max(r.module.voices,e.module.voices);for(let i=0;i<o;i++){let n=r.findIOByVoice(i%r.module.voices),s=e.findIOByVoice(i%e.module.voices);t?n.plug(s):n.unPlug(s)}}else for(let o=0;o<r.module.voices;o++){let i=r.findIOByVoice(o);t?i.plug(e):i.unPlug(e)}}var D=class extends g{getAudioNode;constructor(e,t){super(e,t),this.getAudioNode=t.getAudioNode}},F=class extends g{getAudioNode;constructor(e,t){super(e,t),this.getAudioNode=t.getAudioNode}plug(e,t=!0){if(super.plug(e,t),e instanceof P)return;let o=e.getAudioNode();o instanceof AudioParam?this.getAudioNode().connect(o):this.getAudioNode().connect(o)}unPlug(e,t=!0){if(super.unPlug(e,t),e instanceof P)return;let o=e.getAudioNode();try{o instanceof AudioParam?this.getAudioNode().disconnect(o):this.getAudioNode().disconnect(o)}catch{}}};var N=class extends g{onMidiEvent;constructor(e,t){super(e,t),this.onMidiEvent=t.onMidiEvent}},z=class extends g{onMidiEvent=e=>{this.midiConnections.forEach(t=>{t.onMidiEvent(e)})};get midiConnections(){return this.connections.filter(e=>e instanceof N)}};var G=class{module;collection=[];collectionType;constructor(e,t){this.collectionType=e,this.module=t}add(e){let t;switch(this.validateUniqName(e.name),e.ioType){case"audioInput":if(this.module instanceof m)throw Error("Not compatible");t=new D(this.module,e);break;case"audioOutput":if(this.module instanceof m)throw Error("Not compatible");t=new F(this.module,e);break;case"polyAudioInput":if(this.module instanceof p)throw Error("Not compatible");t=new P(this.module,e);break;case"polyAudioOutput":if(this.module instanceof p)throw Error("Not compatible");t=new b(this.module,e);break;case"midiInput":t=new N(this.module,e);break;case"midiOutput":t=new z(this.module,e);break;default:(0,Ce.assertNever)(e)}return this.collection.push(t),t}unPlugAll(){this.collection.forEach(e=>{e.unPlugAll()})}rePlugAll(e){this.collection.forEach(t=>{t.rePlugAll(e)})}find(e){let t=this.collection.find(o=>o.id===e);if(!t)throw Error(`The io with id ${e} is not exists`);return t}findByName(e){let t=this.collection.find(o=>o.name===e);if(!t)throw Error(`The io with name ${e} is not exists`);return t}serialize(){return(0,be.sortBy)(this.collection,[e=>e.isMidi()?-1:1]).map(e=>e.serialize())}validateUniqName(e){if(this.collection.some(t=>t.name===e))throw Error(`An io with name ${e} is already exists`)}},O=class extends G{constructor(e){super("Input",e)}},C=class extends G{constructor(e){super("Output",e)}};var A=class{data;constructor(e){this.data=e}get dataBytes(){return Array.from(this.data.slice(1))}get type(){switch(this.data[0]&240){case 144:return this.data[2]===0?"noteoff":"noteon";case 128:return"noteoff";case 176:return"controlchange";case 224:return"pitchbend";case 208:return"channelaftertouch";case 160:return"keyaftertouch";case 192:return"programchange";default:return"unknown"}}};var ht=new Map([["C0",16.35],["C#0",17.32],["Db0",17.32],["D0",18.35],["D#0",19.45],["Eb0",19.45],["E0",20.6],["F0",21.83],["F#0",23.12],["Gb0",23.12],["G0",24.5],["G#0",25.96],["Ab0",25.96],["A0",27.5],["A#0",29.14],["Bb0",29.14],["B0",30.87],["C1",32.7],["C#1",34.65],["Db1",34.65],["D1",36.71],["D#1",38.89],["Eb1",38.89],["E1",41.2],["F1",43.65],["F#1",46.25],["Gb1",46.25],["G1",49],["G#1",51.91],["Ab1",51.91],["A1",55],["A#1",58.27],["Bb1",58.27],["B1",61.74],["C2",65.41],["C#2",69.3],["Db2",69.3],["D2",73.42],["D#2",77.78],["Eb2",77.78],["E2",82.41],["F2",87.31],["F#2",92.5],["Gb2",92.5],["G2",98],["G#2",103.83],["Ab2",103.83],["A2",110],["A#2",116.54],["Bb2",116.54],["B2",123.47],["C3",130.81],["C#3",138.59],["Db3",138.59],["D3",146.83],["D#3",155.56],["Eb3",155.56],["E3",164.81],["F3",174.61],["F#3",185],["Gb3",185],["G3",196],["G#3",207.65],["Ab3",207.65],["A3",220],["A#3",233.08],["Bb3",233.08],["B3",246.94],["C4",261.63],["C#4",277.18],["Db4",277.18],["D4",293.66],["D#4",311.13],["Eb4",311.13],["E4",329.63],["F4",349.23],["F#4",369.99],["Gb4",369.99],["G4",392],["G#4",415.3],["Ab4",415.3],["A4",440],["A#4",466.16],["Bb4",466.16],["B4",493.88],["C5",523.25],["C#5",554.37],["Db5",554.37],["D5",587.33],["D#5",622.25],["Eb5",622.25],["E5",659.26],["F5",698.46],["F#5",739.99],["Gb5",739.99],["G5",783.99],["G#5",830.61],["Ab5",830.61],["A5",880],["A#5",932.33],["Bb5",932.33],["B5",987.77],["C6",1046.5],["C#6",1108.73],["Db6",1108.73],["D6",1174.66],["D#6",1244.51],["Eb6",1244.51],["E6",1318.51],["F6",1396.91],["F#6",1479.98],["Gb6",1479.98],["G6",1567.98],["G#6",1661.22],["Ab6",1661.22],["A6",1760],["A#6",1864.66],["Bb6",1864.66],["B6",1975.53],["C7",2093],["C#7",2217.46],["Db7",2217.46],["D7",2349.32],["D#7",2489.02],["Eb7",2489.02],["E7",2637.02],["F7",2793.83],["F#7",2959.96],["Gb7",2959.96],["G7",3135.96],["G#7",3322.44],["Ab7",3322.44],["A7",3520],["A#7",3729.31],["Bb7",3729.31],["B7",3951.07],["C8",4186.01],["C#8",4434.92],["Db8",4434.92],["D8",4698.64],["D#8",4978.03],["Eb8",4978.03]]),ce=ht;var me=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"],ft=2,a=class r{static _notes;name;octave;velocity=1;duration;static fromFrequency(e){let t;for(let[o,i]of ce)if(i===e){t=o;break}if(!t)throw Error("Not matching frequency with a note");return new r(t)}static fromEvent(e){let t=me[e.data[1]%12],o=Math.floor(e.data[1]/12)-2;return new r(`${t}${o}`)}static notes(e=3){return me.map(t=>new r(`${t}${e}`))}constructor(e){typeof e=="string"?this.fromString(e):this.fromProps(e)}get isSemi(){return this.name.endsWith("#")}get fullName(){return`${this.name}${this.octave}`}get frequency(){return ce.get(`${this.name}${this.octave}`)}midiData(e=!0){let t=e?144:128;return new Uint8Array([t,this.midiNumber,this.velocity*100])}get midiNumber(){return(this.octave+ft)*12+this.noteIndex}get noteIndex(){return me.indexOf(this.name)}valueOf(){return this.fullName}serialize(){return{name:this.name,octave:this.octave,frequency:this.frequency,velocity:this.velocity,duration:this.duration}}fromString(e){let t=/(\w#?)(\d)?/.exec(e)??[];this.name=t[1],this.octave=t[2]?parseInt(t[2]):1}fromProps(e){Object.assign(this,e)}};var f=class r{note;voiceNo;triggeredAt;message;static fromNote(e,t=!0,o){let i=e instanceof a?e:new a(e);return new r(new A(i.midiData(t)),o)}static fromCC(e,t,o){return new r(new A(new Uint8Array([176,e,t])),o)}constructor(e,t){this.message=e,this.triggeredAt=t,this.defineNotes()}get type(){return this.message.type}get isNote(){return this.type==="noteon"||this.type==="noteoff"}get isCC(){return this.type==="controlchange"}get cc(){if(this.isCC)return this.message.dataBytes[0]}get ccValue(){if(this.isCC)return this.message.dataBytes[1]}defineNotes(){this.isNote&&(this.note||(this.note=a.fromEvent(this.message)))}get rawMessage(){return this.message}clone(e){let t=new r(this.message,this.triggeredAt);return t.voiceNo=e,t}};var p=class{id;engineId;name;moduleType;voiceNo;audioNode;inputs;outputs;_props;activeNotes;pendingUIUpdates=!1;constructor(e,t){let{id:o,name:i,moduleType:n,voiceNo:s,audioNodeConstructor:d,props:u}=t;this.id=o??(0,ne.uuidv4)(),this.engineId=e,this.name=i,this.moduleType=n,this.voiceNo=s??0,this.activeNotes=[],this.audioNode=d?.(this.context),this._props=u,this.inputs=new O(this),this.outputs=new C(this),queueMicrotask(()=>{this.props=u})}get props(){return this._props}set props(e){let t={...e};Object.keys(e).forEach(o=>{let i=e[o];if(i!==void 0){let n=this.callPropHook("onSet",o,i);n!==void 0&&(t[o]=n)}}),this._props={...this._props,...t},Object.keys(t).forEach(o=>{let i=t[o];i!==void 0&&this.callPropHook("onAfterSet",o,i)})}callPropHook(e,t,o){let i=`${e}${(0,ne.upperFirst)(t)}`,n=this[i];if(typeof n=="function")return n.call(this,o)}serialize(){return{id:this.id,name:this.name,moduleType:this.moduleType,voiceNo:this.voiceNo,props:this.props,inputs:this.inputs.serialize(),outputs:this.outputs.serialize()}}plug({audioModule:e,from:t,to:o}){let i=this.outputs.findByName(t),n=e.inputs.findByName(o);i.plug(n)}rePlugAll(e){this.inputs.rePlugAll(e),this.outputs.rePlugAll(e)}unPlugAll(){this.inputs.unPlugAll(),this.outputs.unPlugAll()}start(e){}stop(e){}triggerAttack(e,t){this.activeNotes.some(o=>o.fullName===e.fullName)||this.activeNotes.push(e)}triggerRelease(e,t){this.activeNotes=this.activeNotes.filter(o=>o.fullName!==e.fullName)}handleCC(e,t){}onMidiEvent=e=>{let{note:t,triggeredAt:o}=e;switch(e.type){case"noteon":{this.triggerAttack(t,o);break}case"noteoff":this.triggerRelease(t,o);break;case"controlchange":this.handleCC(e,o);break;default:throw Error("This type is not a note")}};triggerPropsUpdate=()=>{this.pendingUIUpdates||(this.pendingUIUpdates=!0,this.sheduleTriggerUpdate())};sheduleTriggerUpdate(){requestAnimationFrame(()=>{this.engine._triggerPropsUpdate({id:this.id,moduleType:this.moduleType,voiceNo:this.voiceNo,name:this.name,props:this.props}),this.pendingUIUpdates=!1})}dispose(){this.inputs.unPlugAll(),this.outputs.unPlugAll()}registerDefaultIOs(e="both"){this.registerMidiInput({name:"midi in",onMidiEvent:this.onMidiEvent}),this.audioNode&&((e==="in"||e==="both")&&this.registerAudioInput({name:"in",getAudioNode:()=>this.audioNode}),(e==="out"||e==="both")&&this.registerAudioOutput({name:"out",getAudioNode:()=>this.audioNode}))}registerAudioInput(e){return this.inputs.add({...e,ioType:"audioInput"})}registerAudioOutput(e){return this.outputs.add({...e,ioType:"audioOutput"})}registerMidiInput(e){return this.inputs.add({...e,ioType:"midiInput"})}registerMidiOutput(e){return this.outputs.add({...e,ioType:"midiOutput"})}get engine(){return x.getById(this.engineId)}get context(){return this.engine.context}};var Ne=require("@blibliki/utils"),V=class{engine;routes;constructor(e){this.engine=e,this.routes=new Map}addRoute(e){let t=e.id??(0,Ne.uuidv4)(),o={...e,id:t};return this.routes.set(t,o),this.plug(t),o}removeRoute(e){this.unPlug(e),this.routes.delete(e)}clear(){this.routes.forEach((e,t)=>{this.removeRoute(t)})}replug(){this.routes.forEach((e,t)=>{let{sourceIO:o,destinationIO:i}=this.getIOs(t);o.rePlugAll(),i.rePlugAll()})}serialize(){return Array.from(this.routes.values())}plug(e){let{sourceIO:t,destinationIO:o}=this.getIOs(e);t.plug(o)}unPlug(e){let{sourceIO:t,destinationIO:o}=this.getIOs(e);t.unPlug(o)}find(e){let t=this.routes.get(e);if(!t)throw Error(`Route with id ${e} not found`);return t}getIOs(e){let t=this.find(e),{source:o,destination:i}=t,n=this.engine.findIO(o.moduleId,o.ioName,"output"),s=this.engine.findIO(i.moduleId,i.ioName,"input");return{sourceIO:n,destinationIO:s}}};var Ee=mt(require("jzz"),1);var q=(t=>(t.connected="connected",t.disconnected="disconnected",t))(q||{}),v=class{id;name;eventListerCallbacks=[];context;input;_state="connected";constructor(e,t,o,i){this.id=t,this.name=o||`Device ${t}`,this.input=e,this.context=i,this.connect()}get state(){return this._state}connect(){this.input.connect(e=>{this.processEvent(e)})}disconnect(){this.input.close(),this._state="disconnected"}serialize(){let{id:e,name:t,state:o}=this;return{id:e,name:t,state:o}}addEventListener(e){this.eventListerCallbacks.push(e)}removeEventListener(e){this.eventListerCallbacks=this.eventListerCallbacks.filter(t=>t!==e)}processEvent(e){let t=new Uint8Array(e.slice()),o=new A(t),i=performance.now(),n=new f(o,this.context.browserToContextTime(i));switch(n.type){case"noteon":case"noteoff":case"controlchange":this.eventListerCallbacks.forEach(s=>{s(n)})}}};var yt={a:new a("C3"),s:new a("D3"),d:new a("E3"),f:new a("F3"),g:new a("G3"),h:new a("A3"),j:new a("B3"),k:new a("C4"),l:new a("D4"),w:new a("C#3"),e:new a("D#3"),t:new a("F#3"),y:new a("G#3"),u:new a("A#3"),o:new a("C#4"),p:new a("D#4")},gt=()=>({id:"computer_keyboard",name:"Computer Keyboard",state:"connected"}),E=class{id;name;state;eventListerCallbacks=[];context;constructor(e){let{id:t,name:o,state:i}=gt();this.id=t,this.name=o,this.state=i,this.context=e,document.addEventListener("keydown",this.onKeyTrigger(!0)),document.addEventListener("keyup",this.onKeyTrigger(!1))}addEventListener(e){this.eventListerCallbacks.push(e)}removeEventListener(e){this.eventListerCallbacks=this.eventListerCallbacks.filter(t=>t!==e)}serialize(){let{id:e,name:t,state:o}=this;return{id:e,name:t,state:o}}onKeyTrigger=e=>t=>{let o=this.extractNote(t);if(!o)return;let i=f.fromNote(o,e,this.context.browserToContextTime(t.timeStamp));this.eventListerCallbacks.forEach(n=>{n(i)})};extractNote(e){if(!e.repeat)return yt[e.key]}};var w=class{devices=new Map;initialized=!1;listeners=[];context;jzz=null;constructor(e){this.context=e,this.addComputerKeyboard()}async initialize(){await this.initializeDevices(),this.listenChanges(),this.initialized=!0}find(e){return this.devices.get(e)}findByName(e){return Array.from(this.devices.values()).find(t=>t.name===e)}addListener(e){this.listeners.push(e)}async initializeDevices(){if(!this.initialized)try{let e=await(0,Ee.default)();this.jzz=e;let t=e.info();for(let o of t.inputs??[]){let i=o.id??o.name;if(!this.devices.has(i)){let n=await e.openMidiIn(o.name),s=new v(n,i,o.name,this.context);this.devices.set(i,s)}}}catch(e){console.error("Error enabling JZZ MIDI:",e)}}addComputerKeyboard(){if(typeof document>"u")return;let e=new E(this.context);this.devices.set(e.id,e)}listenChanges(){this.jzz&&this.jzz.onChange(()=>{if(!this.jzz)return;let e=this.jzz.info(),t=new Set((e.inputs??[]).map(o=>o.id??o.name));for(let o of e.inputs??[]){let i=o.id??o.name;this.devices.has(i)||this.jzz.openMidiIn(o.name).then(n=>{let s=n,d=new v(s,i,o.name,this.context);this.devices.set(i,d),this.listeners.forEach(u=>{u(d)})})}for(let[o,i]of this.devices)i instanceof E||t.has(o)||(i.disconnect(),this.devices.delete(o),this.listeners.forEach(n=>{n(i)}))})}};var it=require("@blibliki/utils");var we={},ke={},he=class extends p{activeNote=null;triggeredAt=0;constructor(e,t){let o={...ke,...t.props};super(e,{...t,props:o})}midiTriggered=e=>{let{triggeredAt:t,note:o,type:i}=e;if(!o)return;let n=o.fullName;switch(i){case"noteon":this.activeNote=n,this.triggeredAt=t;break;case"noteoff":this.activeNote=null;break;default:throw Error("This type is not a note")}}},R=class extends m{midiOutput;constructor(e,t){let o={...ke,...t.props},i=(n,s)=>new he(n,s);super(e,{...t,props:o,monoModuleConstructor:i}),this.registerInputs(),this.registerOutputs()}onMidiEvent=e=>{let t;switch(e.type){case"noteon":t=this.findFreeVoice();break;case"noteoff":t=this.audioModules.find(o=>o.activeNote===e.note.fullName);break;default:throw Error("This type is not a note")}t&&(t.midiTriggered(e),e.voiceNo=t.voiceNo,this.midiOutput.onMidiEvent(e))};findFreeVoice(){let e=this.audioModules.find(t=>!t.activeNote);return e??=this.audioModules.sort((t,o)=>t.triggeredAt-o.triggeredAt)[0],e}registerInputs(){this.registerMidiInput({name:"midi in",onMidiEvent:this.onMidiEvent})}registerOutputs(){this.midiOutput=this.registerMidiOutput({name:"midi out"})}};var De={value:{kind:"number",min:-1/0,max:1/0,step:.01,label:"Value"}},It={value:1},U=class extends p{isStated=!1;constructor(e,t){let o={...It,...t.props},i=n=>new ConstantSourceNode(n.audioContext);super(e,{...t,props:o,audioNodeConstructor:i}),this.registerDefaultIOs("out")}onAfterSetValue=e=>{this.audioNode.offset.value=e};start(e){this.isStated||(this.isStated=!0,this.audioNode.start(e))}stop(e){this.isStated&&(this.audioNode.stop(e),this.rePlugAll(()=>{this.audioNode=new ConstantSourceNode(this.context.audioContext,{offset:this.props.value})}),this.isStated=!1)}triggerAttack=(e,t)=>{this.audioNode.offset.setValueAtTime(e.frequency,t),this.start(t)};triggerRelease=()=>{}};var fe=require("@blibliki/utils");var Fe={attack:.01,decay:0,sustain:1,release:0},ze={attack:{kind:"number",min:1e-4,max:20,step:.01,exp:3,label:"Attack"},decay:{kind:"number",min:0,max:20,step:.01,exp:3,label:"Decay"},sustain:{kind:"number",min:0,max:1,step:.01,label:"Sustain"},release:{kind:"number",min:0,max:20,step:.01,exp:3,label:"Release"}},ye=class extends p{constructor(e,t){let o={...Fe,...t.props},i=n=>{let s=new GainNode(n.audioContext);return s.gain.value=0,s};super(e,{...t,props:o,audioNodeConstructor:i}),this.registerDefaultIOs()}triggerAttack(e,t){super.triggerAttack(e,t);let o=this.props.attack,i=this.props.decay,n=this.props.sustain;(0,fe.cancelAndHoldAtTime)(this.audioNode.gain,t),this.audioNode.gain.value===0&&this.audioNode.gain.setValueAtTime(.001,t),this.audioNode.gain.exponentialRampToValueAtTime(1,t+o),n>0?this.audioNode.gain.exponentialRampToValueAtTime(n,t+o+i):this.audioNode.gain.exponentialRampToValueAtTime(.001,t+o+i)}triggerRelease(e,t){if(super.triggerRelease(e,t),this.activeNotes.length>0)return;let o=this.props.release,i=(0,fe.cancelAndHoldAtTime)(this.audioNode.gain,t);i>=1e-4&&(this.audioNode.gain.setValueAtTime(i,t),this.audioNode.gain.exponentialRampToValueAtTime(1e-4,t+o-1e-4)),this.audioNode.gain.setValueAtTime(0,t+o)}},_=class extends m{constructor(e,t){let o={...Fe,...t.props},i=(n,s)=>new ye(n,s);super(e,{...t,props:o,monoModuleConstructor:i}),this.registerDefaultIOs()}};var Ge={gain:{kind:"number",min:0,max:1/0,step:.01,label:"Gain"}},Ve={gain:1},B=class extends p{constructor(e,t){let o={...Ve,...t.props},i=n=>new GainNode(n.audioContext);super(e,{...t,audioNodeConstructor:i,props:o}),this.registerDefaultIOs(),this.registerAdditionalInputs()}onAfterSetGain=e=>{this.audioNode.gain.value=e};registerAdditionalInputs(){this.registerAudioInput({name:"gain",getAudioNode:()=>this.audioNode.gain})}},L=class extends m{constructor(e,t){let o={...Ve,...t.props},i=(n,s)=>new B(n,s);super(e,{...t,props:o,monoModuleConstructor:i}),this.registerAdditionalInputs(),this.registerDefaultIOs()}registerAdditionalInputs(){this.registerAudioInput({name:"gain"})}};var qe=20,Ie=2e4,Re={cutoff:Ie,envelopeAmount:0,type:"lowpass",Q:1},Ue={cutoff:{kind:"number",min:qe,max:Ie,step:1,exp:5,label:"Cutoff"},envelopeAmount:{kind:"number",min:-1,max:1,step:.01,label:"Envelope Amount"},type:{kind:"enum",options:["lowpass","highpass","bandpass"],label:"Type"},Q:{kind:"number",min:1e-4,max:1e3,step:.1,exp:5,label:"Q"}},ge=class extends p{scale;amount;constructor(e,t){let o={...Re,...t.props},i=n=>new BiquadFilterNode(n.audioContext,{type:o.type,frequency:0,Q:o.Q});super(e,{...t,props:o,audioNodeConstructor:i}),this.amount=new B(e,{name:"amount",moduleType:"Gain",props:{gain:o.envelopeAmount}}),this.scale=se(e,{name:"scale",moduleType:"Scale",props:{min:qe,max:Ie,current:this.props.cutoff}}),this.amount.plug({audioModule:this.scale,from:"out",to:"in"}),this.scale.audioNode.connect(this.audioNode.frequency),this.registerDefaultIOs(),this.registerInputs()}onAfterSetType=e=>{this.audioNode.type=e};onAfterSetCutoff=e=>{this.scale.props={current:e}};onAfterSetQ=e=>{this.audioNode.Q.value=e};onAfterSetEnvelopeAmount=e=>{this.amount.props={gain:e}};registerInputs(){this.registerAudioInput({name:"cutoff",getAudioNode:()=>this.audioNode.frequency}),this.registerAudioInput({name:"cutoffMod",getAudioNode:()=>this.amount.audioNode}),this.registerAudioInput({name:"Q",getAudioNode:()=>this.audioNode.Q})}},H=class extends m{constructor(e,t){let o={...Re,...t.props},i=(n,s)=>new ge(n,s);super(e,{...t,props:o,monoModuleConstructor:i}),this.registerInputs(),this.registerDefaultIOs()}registerInputs(){this.registerAudioInput({name:"cutoff"}),this.registerAudioInput({name:"cutoffMod"}),this.registerAudioInput({name:"Q"})}};var _e={fftSize:{kind:"enum",options:[32,64,128,256,512,1024,2048,4096,8192,16384,32768],label:"FFT size"}},Pt={fftSize:512},K=class extends p{_buffer;constructor(e,t){let o={...Pt,...t.props},i=n=>new AnalyserNode(n.audioContext);super(e,{...t,props:o,audioNodeConstructor:i}),this.registerDefaultIOs("in")}onAfterSetFftSize=e=>{this._buffer=new Float32Array(e)};get buffer(){return this._buffer?this._buffer:(this._buffer=new Float32Array(this.props.fftSize),this._buffer)}getValue(){return this.getValues()[0]}getValues(){return this.audioNode.getFloatTimeDomainData(this.buffer),this.buffer}};var Tt={},Be={},j=class extends p{constructor(e,t){let o={...Tt,...t.props},i=n=>n.destination;super(e,{...t,audioNodeConstructor:i,props:o}),this.registerDefaultIOs("in")}};var ue=(s=>(s.direct="direct",s.directRev="directRev",s.toggleInc="toggleInc",s.toggleDec="toggleDec",s.incDec="incDec",s.incDecRev="incDecRev",s))(ue||{}),Le={pages:{kind:"array",label:"Midi mapping pages"},activePage:{kind:"number",label:"Active page",min:0,max:100,step:1},globalMappings:{kind:"array",label:"Global midi mappings"}},vt={pages:[{name:"Page 1",mappings:[{}]}],activePage:0,globalMappings:[{}]};function St({value:r,midiValue:e,propSchema:t,mapping:o}){let i=t.min??0,n=t.max??1,s=t.exp??1,{threshold:d=64,mode:u}=o,c=(r-i)/(n-i),M=Math.pow(c,1/s)*127;return M=e>=d&&u==="incDec"||e<=d&&u==="incDecRev"?M+1:M-1,Math.round(Math.max(0,Math.min(127,M)))}var $=class extends p{constructor(e,t){let o={...vt,...t.props};super(e,{...t,props:o}),this.registerMidiInput({name:"midi in",onMidiEvent:this.onMidiEvent})}onSetActivePage=e=>Math.max(Math.min(e,this.props.pages.length-1),0);handleCC=(e,t)=>{this.checkAutoAssign(e);let o=this.props.pages[this.props.activePage];[...this.props.globalMappings.filter(i=>i.cc===e.cc),...o.mappings.filter(i=>i.cc===e.cc)].forEach(i=>{this.forwardMapping(e,i,t)})};forwardMapping=(e,t,o)=>{if(t.moduleId===void 0||t.moduleType===void 0||t.propName===void 0)return;let i=t.propName,n=e.ccValue;if(n===void 0)return;let s=t.mode??"direct";if((s==="toggleInc"||s==="toggleDec")&&n!==127)return;let d=this.engine.findModule(t.moduleId),u=pe[d.moduleType][i],c;switch(u.kind){case"number":{let h=d.props[i];if(s==="incDec"||s==="incDecRev"?n=St({value:h,propSchema:u,mapping:t,midiValue:n}):s==="directRev"&&(n=127-n),s==="toggleInc")c=h+(u.step??1);else if(s==="toggleDec")c=h-(u.step??1);else{let M=u.min??0,I=u.max??1,y=n/127,l=Math.pow(y,u.exp??1);if(c=M+l*(I-M),u.step!==void 0&&(!u.exp||u.exp===1)){let k=Math.round((c-M)/u.step);c=M+k*u.step}}break}case"enum":{let h=Math.floor(n/127*u.options.length),M=Math.min(h,u.options.length-1);c=u.options[M];break}case"boolean":c=n>=64;break;case"string":throw Error("MidiMapper not support string type of values");case"array":throw Error("MidiMapper not support array type of values");default:throw Error("MidiMapper unknown type")}d.props={[i]:c},d.triggerPropsUpdate()};checkAutoAssign(e){if(e.cc===void 0)return;let t=this.props.pages[this.props.activePage],o=this.props.globalMappings.some(({autoAssign:u})=>u),i=t.mappings.some(({autoAssign:u})=>u);if(!o&&!i)return;let n=o?this.props.globalMappings.map(u=>u.autoAssign?{...u,cc:e.cc,autoAssign:!1}:u):this.props.globalMappings,s=i?t.mappings.map(u=>u.autoAssign?{...u,cc:e.cc,autoAssign:!1}:u):t.mappings,d=this.props.pages.map((u,c)=>c===this.props.activePage?{...u,mappings:s}:u);this.props={pages:d,globalMappings:n},this.triggerPropsUpdate()}};var He={selectedId:{kind:"string",label:"Midi device ID"},selectedName:{kind:"string",label:"Midi device name"}},xt={selectedId:void 0,selectedName:void 0},J=class extends p{midiOutput;_forwardMidiEvent;constructor(e,t){let o={...xt,...t.props};super(e,{...t,props:o});let i=(this.props.selectedId&&this.engine.findMidiDevice(this.props.selectedId))??(this.props.selectedName&&this.engine.findMidiDeviceByName(this.props.selectedName));i&&this.addEventListener(i),this.registerOutputs()}onSetSelectedId=e=>{if(this.removeEventListener(),!e)return e;let t=this.engine.findMidiDevice(e);return t&&(this.props={selectedName:t.name},this.addEventListener(t)),e};get forwardMidiEvent(){return this._forwardMidiEvent?this._forwardMidiEvent:(this._forwardMidiEvent=e=>{this.midiOutput.onMidiEvent(e)},this._forwardMidiEvent)}addEventListener(e){e.addEventListener(this.forwardMidiEvent)}removeEventListener(){if(!this.props.selectedId)return;this.engine.findMidiDevice(this.props.selectedId)?.removeEventListener(this.forwardMidiEvent)}registerOutputs(){this.midiOutput=this.registerMidiOutput({name:"midi out"})}};var Pe=require("@blibliki/utils");var Te=-18,Q=(i=>(i.sine="sine",i.triangle="triangle",i.square="square",i.sawtooth="sawtooth",i))(Q||{}),Ze={wave:{kind:"enum",options:Object.values(Q),label:"Waveform"},frequency:{kind:"number",min:0,max:25e3,step:1,label:"Frequency"},fine:{kind:"number",min:-1,max:1,step:.01,label:"Fine"},coarse:{kind:"number",min:-12,max:12,step:1,label:"Coarse"},octave:{kind:"number",min:-1,max:2,step:1,label:"Octave"},lowGain:{kind:"boolean",label:`Use ${Te}db Gain`}},Ke={wave:"sine",frequency:440,fine:0,coarse:0,octave:0,lowGain:!1},ve=class extends p{isStated=!1;outputGain;detuneGain;constructor(e,t){let o={...Ke,...t.props},i=n=>new OscillatorNode(n.audioContext);super(e,{...t,props:o,audioNodeConstructor:i}),this.outputGain=new GainNode(this.context.audioContext,{gain:(0,Pe.dbToGain)(Te)}),this.applyOutputGain(),this.initializeGainDetune(),this.registerInputs(),this.registerOutputs()}onAfterSetWave=e=>{this.audioNode.type=e};onAfterSetFrequency=()=>{this.updateFrequency()};onAfterSetFine=()=>{this.updateFrequency()};onAfterSetCoarse=()=>{this.updateFrequency()};onAfterSetOctave=()=>{this.updateFrequency()};onAfterSetLowGain=e=>{this.outputGain.gain.value=e?(0,Pe.dbToGain)(Te):1};start(e){this.isStated||(this.isStated=!0,this.audioNode.start(e))}stop(e){this.isStated&&(this.audioNode.stop(e),this.rePlugAll(()=>{this.audioNode=new OscillatorNode(this.context.audioContext,{type:this.props.wave,frequency:this.finalFrequency}),this.applyOutputGain(),this.detuneGain.connect(this.audioNode.detune)}),this.isStated=!1)}triggerAttack=(e,t)=>{super.triggerAttack(e,t),this.props={frequency:e.frequency},this.updateFrequency(t),this.start(t)};triggerRelease(e,t){super.triggerRelease(e,t);let o=this.activeNotes.length?this.activeNotes[this.activeNotes.length-1]:null;o&&(this.props={frequency:o.frequency},this.updateFrequency(t))}get finalFrequency(){let{frequency:e,coarse:t,octave:o,fine:i}=this.props;return e*Math.pow(2,t/12+o+i/12)}updateFrequency(e){this.finalFrequency!==void 0&&(e?this.audioNode.frequency.setValueAtTime(this.finalFrequency,e):this.audioNode.frequency.value=this.finalFrequency)}applyOutputGain(){this.audioNode.connect(this.outputGain)}initializeGainDetune(){this.detuneGain=new GainNode(this.context.audioContext,{gain:100}),this.detuneGain.connect(this.audioNode.detune)}registerInputs(){this.registerAudioInput({name:"detune",getAudioNode:()=>this.detuneGain})}registerOutputs(){this.registerAudioOutput({name:"out",getAudioNode:()=>this.outputGain})}},W=class extends m{constructor(e,t){let o={...Ke,...t.props},i=(n,s)=>new ve(n,s);super(e,{...t,props:o,monoModuleConstructor:i}),this.registerInputs(),this.registerDefaultIOs("out")}start(e){this.audioModules.forEach(t=>{t.start(e)})}stop(e){this.audioModules.forEach(t=>{t.stop(e)})}registerInputs(){this.registerAudioInput({name:"detune"})}};var Je=require("@blibliki/utils");var je=URL.createObjectURL(new Blob(["(",(()=>{class r extends AudioWorkletProcessor{s0;s1;constructor(){super(),this.s0=0,this.s1=0}static get parameterDescriptors(){return[{name:"cutoff",defaultValue:1e3,minValue:20,maxValue:2e4},{name:"resonance",defaultValue:0,minValue:0,maxValue:4}]}process(t,o,i){let n=t[0],s=o[0],d=i.cutoff,u=i.resonance;for(let c=0;c<n.length;c++){let h=n[c],M=s[c];for(let I=0;I<h.length;I++){let y=h[I],l=d.length>1?d[I]:d[0],k=Math.max(20,Math.min(2e4,l)),de=Math.log(k/20)/Math.log(2e4/20),T=Math.pow(.5,(1-de)/.125),xe=1-Math.pow(.5,((u.length>1?u[I]:u[0])+.125)/.125)*T;this.s0=xe*this.s0-T*this.s1+T*y,this.s1=xe*this.s1+T*this.s0,M[I]=this.s1}}return!0}}registerProcessor("filter-processor",r)}).toString(),")()"],{type:"application/javascript"}));var $e=URL.createObjectURL(new Blob(["(",(()=>{class r extends AudioWorkletProcessor{static get parameterDescriptors(){return[{name:"min",defaultValue:1e-10},{name:"max",defaultValue:1},{name:"current",defaultValue:.5}]}process(t,o,i){let n=t[0],s=o[0],d=i.min,u=i.max,c=i.current;if(!n.length||n[0].length===0){for(let h of s){let M=(i.current.length>1,i.current[0]);h.fill(M)}return!0}for(let h=0;h<n.length;h++){let M=n[h],I=s[h];for(let y=0;y<M.length;y++){let l=M[y],k=d.length>1?d[y]:d[0],de=u.length>1?u[y]:u[0],T=c.length>1?c[y]:c[0];l<0?I[y]=T*Math.pow(k/T,-l):I[y]=T*Math.pow(de/T,l)}}return!0}}registerProcessor("scale-processor",r)}).toString(),")()"],{type:"application/javascript"}));async function We(r){await r.addModule($e),await r.addModule(je)}function Qe(r,e){switch(e){case"ScaleProcessor":return r.newAudioWorklet("scale-processor");case"FilterProcessor":return r.newAudioWorklet("filter-processor");default:(0,Je.assertNever)(e)}}var Ye={min:{kind:"number",min:-1/0,max:1/0,step:.01,label:"Min"},max:{kind:"number",min:-1/0,max:1/0,step:.01,label:"Max"},current:{kind:"number",min:-1/0,max:1/0,step:.01,label:"Current"}},At={min:0,max:1,current:.5},Y=class extends p{constructor(e,t){let o={...At,...t.props},i=n=>Qe(n,"ScaleProcessor");super(e,{...t,props:o,audioNodeConstructor:i}),this.registerDefaultIOs()}get current(){return this.audioNode.parameters.get("current")}get min(){return this.audioNode.parameters.get("min")}get max(){return this.audioNode.parameters.get("max")}onAfterSetMin=e=>{this.min.value=e};onAfterSetMax=e=>{this.max.value=e};onAfterSetCurrent=e=>{this.current.value=e}};var Xe={steps:{kind:"number",min:1,max:16,step:1,label:"Steps"},bars:{kind:"number",min:1,max:16,step:1,label:"Steps"}},Ot={sequences:[],steps:16,bars:1},X=class extends p{midiOutput;constructor(e,t){let o={...Ot,...t.props};super(e,{...t,props:o})}};var et={pan:{kind:"number",min:-1,max:1,step:.01,label:"Pan"}},tt={pan:0},Se=class extends p{constructor(e,t){let o={...tt,...t.props},i=n=>new StereoPannerNode(n.audioContext);super(e,{...t,audioNodeConstructor:i,props:o}),this.registerDefaultIOs(),this.registerAdditionalInputs()}onAfterSetPan=e=>{this.audioNode.pan.value=e};registerAdditionalInputs(){this.registerAudioInput({name:"pan",getAudioNode:()=>this.audioNode.pan})}},ee=class extends m{constructor(e,t){let o={...tt,...t.props},i=(n,s)=>new Se(n,s);super(e,{...t,props:o,monoModuleConstructor:i}),this.registerAdditionalInputs(),this.registerDefaultIOs()}registerAdditionalInputs(){this.registerAudioInput({name:"pan"})}};var ot={activeNotes:{kind:"array",label:"Active notes"}},Ct={activeNotes:[]},te=class extends p{midiOutput;constructor(e,t){let o={...Ct,...t.props};super(e,{...t,props:o}),this.registerInputs(),this.registerOutputs()}sendMidi(e){this.midiOutput.onMidiEvent(e)}triggerAttack=(e,t)=>{this.props={activeNotes:[...this.props.activeNotes,e.fullName]},this.triggerPropsUpdate(),this.sendMidi(f.fromNote(e,!0,t))};triggerRelease=(e,t)=>{this.props={activeNotes:this.props.activeNotes.filter(o=>o!==e.fullName)},this.triggerPropsUpdate(),this.sendMidi(f.fromNote(e,!1,t))};registerInputs(){this.registerMidiInput({name:"midi in",onMidiEvent:this.onMidiEvent})}registerOutputs(){this.midiOutput=this.registerMidiOutput({name:"midi out"})}};var Z=(l=>(l.Master="Master",l.Oscillator="Oscillator",l.Gain="Gain",l.MidiSelector="MidiSelector",l.Envelope="Envelope",l.Filter="Filter",l.Scale="Scale",l.StereoPanner="StereoPanner",l.Inspector="Inspector",l.Constant="Constant",l.MidiMapper="MidiMapper",l.VirtualMidi="VirtualMidi",l.StepSequencer="StepSequencer",l.VoiceScheduler="VoiceScheduler",l))(Z||{}),pe={Oscillator:Ze,Gain:Ge,Master:Be,MidiSelector:He,Envelope:ze,Filter:Ue,Scale:Ye,StereoPanner:et,Inspector:_e,Constant:De,MidiMapper:Le,VirtualMidi:ot,StepSequencer:Xe,VoiceScheduler:we};function se(r,e){switch(e.moduleType){case"Oscillator":return new W(r,e);case"Gain":return new L(r,e);case"Master":return new j(r,e);case"MidiSelector":return new J(r,e);case"Envelope":return new _(r,e);case"Filter":return new H(r,e);case"Scale":return new Y(r,e);case"StereoPanner":return new ee(r,e);case"Inspector":return new K(r,e);case"Constant":return new U(r,e);case"MidiMapper":return new $(r,e);case"VirtualMidi":return new te(r,e);case"StepSequencer":return new X(r,e);case"VoiceScheduler":return new R(r,e);default:(0,it.assertNever)(e)}}var x=class r{static _engines=new Map;static _currentId;propsUpdateCallbacks=[];id;context;isInitialized=!1;routes;transport;modules;midiDeviceManager;static getById(e){let t=r._engines.get(e);return(0,S.assertDefined)(t),t}static get current(){return(0,S.assertDefined)(this._currentId),this.getById(this._currentId)}static async load(e){let{bpm:t,timeSignature:o,modules:i,routes:n}=e,s=new S.Context,d=new r(s);return await d.initialize(),d.timeSignature=o,d.bpm=t,i.forEach(u=>{d.addModule(u)}),n.forEach(u=>{d.addRoute(u)}),d}constructor(e){this.id=(0,S.uuidv4)(),this.context=e,this.transport=new rt.Transport(this.context,{generator:(t,o)=>[],consumer:t=>{},onJump:t=>{},onStart:this.onStart,onStop:this.onStop,silence:t=>{}}),this.routes=new V(this),this.modules=new Map,this.midiDeviceManager=new w(this.context),r._engines.set(this.id,this),r._currentId=this.id}get state(){return this.transport.state}async initialize(){this.isInitialized||(await We(this.context),await this.midiDeviceManager.initialize(),this.isInitialized=!0)}addModule(e){let t=se(this.id,e);return this.modules.set(t.id,t),t.serialize()}updateModule(e){let t=this.findModule(e.id);if(t.moduleType!==e.moduleType)throw Error(`The module id ${e.id} isn't moduleType ${e.moduleType}`);let o=(0,S.pick)(e.changes,["name","props"]);return Object.assign(t,o),t instanceof m&&e.changes.voices!==void 0&&(t.voices=e.changes.voices),t.serialize()}removeModule(e){this.modules.delete(e)}addRoute(e){return this.routes.addRoute(e)}removeRoute(e){this.routes.removeRoute(e)}validRoute(e){let{source:t,destination:o}=e,i=this.findIO(t.moduleId,t.ioName,"output"),n=this.findIO(o.moduleId,o.ioName,"input");return i.isMidi()&&n.isMidi()||i.isAudio()&&n.isAudio()}async start(){await this.resume(),this.transport.start()}stop(){this.transport.stop(),this.transport.reset()}pause(){this.transport.stop()}get bpm(){return this.transport.bpm}set bpm(e){this.transport.bpm=e}get timeSignature(){return this.transport.timeSignature}set timeSignature(e){this.transport.timeSignature=e}async resume(){await this.context.resume()}dispose(){this.stop(),this.routes.clear(),this.modules.forEach(e=>{e.dispose()}),this.modules.clear()}serialize(){return{bpm:this.bpm,timeSignature:this.timeSignature,modules:Array.from(this.modules.values()).map(e=>e.serialize()),routes:this.routes.serialize()}}findModule(e){let t=this.modules.get(e);if(!t)throw Error(`The module with id ${e} is not exists`);return t}findIO(e,t,o){return this.findModule(e)[`${o}s`].findByName(t)}findMidiDevice(e){return this.midiDeviceManager.find(e)}findMidiDeviceByName(e){return this.midiDeviceManager.findByName(e)}onPropsUpdate(e){this.propsUpdateCallbacks.push(e)}_triggerPropsUpdate(e){this.propsUpdateCallbacks.forEach(t=>{t(e)})}triggerVirtualMidi(e,t,o){let i=this.findModule(e);if(i.moduleType!=="VirtualMidi")throw Error("This is not a virtual mid");i.sendMidi(f.fromNote(t,o==="noteOn",this.context.currentTime))}onStart=e=>{this.modules.forEach(t=>{t.start(e)})};onStop=e=>{this.modules.forEach(t=>{t.stop(e)})}};var nt=require("@blibliki/transport"),st=require("@blibliki/utils");
2
- //# sourceMappingURL=index.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts","../src/Engine.ts","../src/core/module/Module.ts","../src/core/IO/Collection.ts","../src/core/module/PolyModule.ts","../src/core/IO/Base.ts","../src/core/IO/PolyAudioIO.ts","../src/core/IO/AudioIO.ts","../src/core/IO/MidiIO.ts","../src/core/midi/Message.ts","../src/core/Note/frequencyTable.ts","../src/core/Note/index.ts","../src/core/midi/MidiEvent.ts","../src/core/Route.ts","../src/core/midi/MidiDeviceManager.ts","../src/core/midi/MidiDevice.ts","../src/core/midi/ComputerKeyboardDevice.ts","../src/modules/index.ts","../src/core/module/VoiceScheduler.ts","../src/modules/Constant.ts","../src/modules/Envelope.ts","../src/modules/Gain.ts","../src/modules/Filter.ts","../src/modules/Inspector.ts","../src/modules/Master.ts","../src/modules/MidiMapper.ts","../src/modules/MidiSelector.ts","../src/modules/Oscillator.ts","../src/processors/index.ts","../src/processors/filter-processor.ts","../src/processors/scale-processor.ts","../src/modules/Scale.ts","../src/modules/StepSequencer.ts","../src/modules/StereoPanner.ts","../src/modules/VirtualMidi.ts"],"sourcesContent":["export { Engine } from \"./Engine\";\nexport type { ICreateRoute, IUpdateModule, IEngineSerialize } from \"./Engine\";\n\nexport type {\n IRoute,\n IIOSerialize,\n IModule,\n IModuleSerialize,\n IPolyModuleSerialize,\n IMidiDevice,\n ModulePropSchema,\n PropSchema,\n StringProp,\n NumberProp,\n EnumProp,\n BooleanProp,\n ArrayProp,\n INote,\n} from \"./core\";\nexport { MidiDevice, MidiPortState, Note } from \"./core\";\n\nexport { TransportState } from \"@blibliki/transport\";\nexport type { TimeSignature, Position } from \"@blibliki/transport\";\n\nexport { Context } from \"@blibliki/utils\";\n\nexport {\n ModuleType,\n moduleSchemas,\n OscillatorWave,\n MidiMappingMode,\n} from \"./modules\";\nexport type {\n IOscillator,\n IGain,\n IMaster,\n ISequence,\n IStepSequencerProps,\n IStepSequencer,\n ModuleTypeToPropsMapping,\n ICreateModule,\n ModuleParams,\n IMidiMapper,\n IMidiMapperProps,\n MidiMapping,\n} from \"./modules\";\n","import {\n BPM,\n ContextTime,\n Ticks,\n TimeSignature,\n Transport,\n TransportEvent,\n} from \"@blibliki/transport\";\nimport {\n assertDefined,\n Context,\n Optional,\n pick,\n uuidv4,\n} from \"@blibliki/utils\";\nimport {\n IRoute,\n Routes,\n MidiDeviceManager,\n IModule,\n MidiEvent,\n IModuleSerialize,\n} from \"@/core\";\nimport {\n ICreateModule,\n ModuleParams,\n ModuleType,\n ModuleTypeToModuleMapping,\n createModule,\n} from \"@/modules\";\nimport {\n IPolyModule,\n IPolyModuleSerialize,\n PolyModule,\n} from \"./core/module/PolyModule\";\nimport { loadProcessors } from \"./processors\";\n\nexport type IUpdateModule<T extends ModuleType> = {\n id: string;\n moduleType: T;\n changes: Partial<Omit<ICreateModule<T>, \"id\" | \"moduleType\" | \"voice\">> & {\n voices?: number;\n };\n};\n\nexport type ICreateRoute = Optional<IRoute, \"id\">;\n\nexport interface IEngineSerialize {\n bpm: BPM;\n timeSignature: TimeSignature;\n modules: (IModuleSerialize<ModuleType> | IPolyModuleSerialize<ModuleType>)[];\n routes: IRoute[];\n}\n\nexport class Engine {\n private static _engines = new Map<string, Engine>();\n private static _currentId: string | undefined;\n private propsUpdateCallbacks: (<T extends ModuleType>(\n params: IModule<T> | IPolyModule<T>,\n ) => void)[] = [];\n\n readonly id: string;\n context: Context;\n isInitialized = false;\n routes: Routes;\n transport: Transport<TransportEvent>;\n modules: Map<\n string,\n ModuleTypeToModuleMapping[keyof ModuleTypeToModuleMapping]\n >;\n\n midiDeviceManager: MidiDeviceManager;\n\n static getById(id: string): Engine {\n const engine = Engine._engines.get(id);\n assertDefined(engine);\n\n return engine;\n }\n\n static get current(): Engine {\n assertDefined(this._currentId);\n\n return this.getById(this._currentId);\n }\n\n static async load(data: IEngineSerialize): Promise<Engine> {\n const { bpm, timeSignature, modules, routes } = data;\n const context = new Context();\n const engine = new Engine(context);\n await engine.initialize();\n\n engine.timeSignature = timeSignature;\n engine.bpm = bpm;\n modules.forEach((m) => {\n engine.addModule(m);\n });\n routes.forEach((r) => {\n engine.addRoute(r);\n });\n\n return engine;\n }\n\n constructor(context: Context) {\n this.id = uuidv4();\n\n this.context = context;\n this.transport = new Transport(this.context, {\n generator: (_start: Ticks, _end: Ticks) => {\n return [] as TransportEvent[];\n },\n consumer: (_event: TransportEvent) => {\n return;\n },\n onJump: (_ticks: Ticks) => {\n return;\n },\n onStart: this.onStart,\n onStop: this.onStop,\n silence: (_actionAt: ContextTime) => {\n return;\n },\n });\n this.routes = new Routes(this);\n this.modules = new Map();\n this.midiDeviceManager = new MidiDeviceManager(this.context);\n\n Engine._engines.set(this.id, this);\n Engine._currentId = this.id;\n }\n\n get state() {\n return this.transport.state;\n }\n\n async initialize() {\n if (this.isInitialized) return;\n\n await loadProcessors(this.context);\n await this.midiDeviceManager.initialize();\n this.isInitialized = true;\n }\n\n addModule<T extends ModuleType>(params: ICreateModule<T>) {\n const module = createModule(this.id, params as ModuleParams);\n this.modules.set(module.id, module);\n\n return module.serialize();\n }\n\n updateModule<T extends ModuleType>(params: IUpdateModule<T>) {\n const module = this.findModule(params.id);\n if (module.moduleType !== params.moduleType) {\n throw Error(\n `The module id ${params.id} isn't moduleType ${params.moduleType}`,\n );\n }\n\n const updates = pick(params.changes, [\"name\", \"props\"]);\n Object.assign(module, updates);\n\n if (module instanceof PolyModule && params.changes.voices !== undefined) {\n module.voices = params.changes.voices;\n }\n\n return module.serialize();\n }\n\n removeModule(id: string) {\n this.modules.delete(id);\n }\n\n addRoute(props: ICreateRoute): IRoute {\n return this.routes.addRoute(props);\n }\n\n removeRoute(id: string) {\n this.routes.removeRoute(id);\n }\n\n validRoute(props: Optional<IRoute, \"id\">): boolean {\n const { source, destination } = props;\n\n const output = this.findIO(source.moduleId, source.ioName, \"output\");\n const input = this.findIO(\n destination.moduleId,\n destination.ioName,\n \"input\",\n );\n\n return (\n (output.isMidi() && input.isMidi()) ||\n (output.isAudio() && input.isAudio())\n );\n }\n\n async start() {\n await this.resume();\n this.transport.start();\n }\n\n stop() {\n this.transport.stop();\n this.transport.reset();\n }\n\n pause() {\n this.transport.stop();\n }\n\n get bpm() {\n return this.transport.bpm;\n }\n\n set bpm(value: number) {\n this.transport.bpm = value;\n }\n\n get timeSignature() {\n return this.transport.timeSignature;\n }\n\n set timeSignature(value: TimeSignature) {\n this.transport.timeSignature = value;\n }\n\n async resume() {\n await this.context.resume();\n }\n\n dispose() {\n this.stop();\n this.routes.clear();\n this.modules.forEach((module) => {\n module.dispose();\n });\n this.modules.clear();\n }\n\n serialize(): IEngineSerialize {\n return {\n bpm: this.bpm,\n timeSignature: this.timeSignature,\n modules: Array.from(this.modules.values()).map((m) => m.serialize()),\n routes: this.routes.serialize(),\n };\n }\n\n findModule(\n id: string,\n ): ModuleTypeToModuleMapping[keyof ModuleTypeToModuleMapping] {\n const module = this.modules.get(id);\n if (!module) throw Error(`The module with id ${id} is not exists`);\n\n return module;\n }\n\n findIO(moduleId: string, ioName: string, type: \"input\" | \"output\") {\n const module = this.findModule(moduleId);\n return module[`${type}s`].findByName(ioName);\n }\n\n findMidiDevice(id: string) {\n return this.midiDeviceManager.find(id);\n }\n\n findMidiDeviceByName(name: string) {\n return this.midiDeviceManager.findByName(name);\n }\n\n onPropsUpdate(\n callback: <T extends ModuleType>(\n params: IModule<T> | IPolyModule<T>,\n ) => void,\n ) {\n this.propsUpdateCallbacks.push(callback);\n }\n\n _triggerPropsUpdate<T extends ModuleType>(\n params: IModule<T> | IPolyModule<T>,\n ) {\n this.propsUpdateCallbacks.forEach((callback) => {\n callback(params);\n });\n }\n\n // TODO: Find better way to support this\n triggerVirtualMidi(id: string, noteName: string, type: \"noteOn\" | \"noteOff\") {\n const virtualMidi = this.findModule(id);\n if (virtualMidi.moduleType !== ModuleType.VirtualMidi)\n throw Error(\"This is not a virtual mid\");\n\n virtualMidi.sendMidi(\n MidiEvent.fromNote(noteName, type === \"noteOn\", this.context.currentTime),\n );\n }\n\n // actionAt is context time\n private onStart = (actionAt: ContextTime) => {\n this.modules.forEach((module) => {\n module.start(actionAt);\n });\n };\n\n // actionAt is context time\n private onStop = (actionAt: ContextTime) => {\n this.modules.forEach((module) => {\n module.stop(actionAt);\n });\n };\n}\n","import { ContextTime } from \"@blibliki/transport\";\nimport { Context, Optional, upperFirst, uuidv4 } from \"@blibliki/utils\";\nimport { Engine } from \"@/Engine\";\nimport { AnyModule, ModuleType, ModuleTypeToPropsMapping } from \"@/modules\";\nimport {\n AudioInputProps,\n AudioOutputProps,\n IIOSerialize,\n IOType,\n InputCollection,\n OutputCollection,\n MidiInputProps,\n MidiOutputProps,\n} from \"../IO\";\nimport Note from \"../Note\";\nimport MidiEvent, { MidiEventType } from \"../midi/MidiEvent\";\n\nexport type IModule<T extends ModuleType> = {\n id: string;\n name: string;\n voiceNo: number;\n moduleType: T;\n props: ModuleTypeToPropsMapping[T];\n};\n\nexport type IModuleSerialize<T extends ModuleType> = IModule<T> & {\n inputs: IIOSerialize[];\n outputs: IIOSerialize[];\n};\n\nexport type IModuleConstructor<T extends ModuleType> = Optional<\n IModule<T>,\n \"id\" | \"voiceNo\"\n> & {\n audioNodeConstructor?: (context: Context) => AudioNode;\n};\n\nexport type SetterHooks<P> = {\n [K in keyof P as `onSet${Capitalize<string & K>}`]: (value: P[K]) => P[K];\n} & {\n [K in keyof P as `onAfterSet${Capitalize<string & K>}`]: (\n value: P[K],\n ) => void;\n};\n\nexport abstract class Module<T extends ModuleType> implements IModule<T> {\n id: string;\n engineId: string;\n name: string;\n moduleType: T;\n voiceNo: number;\n audioNode: AudioNode | undefined;\n inputs: InputCollection;\n outputs: OutputCollection;\n protected _props!: ModuleTypeToPropsMapping[T];\n protected activeNotes: Note[];\n private pendingUIUpdates = false;\n\n constructor(engineId: string, params: IModuleConstructor<T>) {\n const { id, name, moduleType, voiceNo, audioNodeConstructor, props } =\n params;\n\n this.id = id ?? uuidv4();\n this.engineId = engineId;\n this.name = name;\n this.moduleType = moduleType;\n this.voiceNo = voiceNo ?? 0;\n this.activeNotes = [];\n this.audioNode = audioNodeConstructor?.(this.context);\n this._props = props;\n\n this.inputs = new InputCollection(this);\n this.outputs = new OutputCollection(this);\n\n // Defer hook calls until after subclass is fully initialized\n queueMicrotask(() => {\n this.props = props;\n });\n }\n\n get props(): ModuleTypeToPropsMapping[T] {\n return this._props;\n }\n\n set props(value: Partial<ModuleTypeToPropsMapping[T]>) {\n const updatedValue = { ...value };\n\n (Object.keys(value) as (keyof ModuleTypeToPropsMapping[T])[]).forEach(\n (key) => {\n const propValue = value[key];\n if (propValue !== undefined) {\n const result = this.callPropHook(\"onSet\", key, propValue);\n if (result !== undefined) {\n updatedValue[key] = result;\n }\n }\n },\n );\n\n this._props = { ...this._props, ...updatedValue };\n\n (\n Object.keys(updatedValue) as (keyof ModuleTypeToPropsMapping[T])[]\n ).forEach((key) => {\n const propValue = updatedValue[key];\n if (propValue !== undefined) {\n this.callPropHook(\"onAfterSet\", key, propValue);\n }\n });\n }\n\n private callPropHook<K extends keyof ModuleTypeToPropsMapping[T]>(\n hookType: \"onSet\" | \"onAfterSet\",\n key: K,\n value: ModuleTypeToPropsMapping[T][K],\n ): ModuleTypeToPropsMapping[T][K] | undefined {\n const hookName = `${hookType}${upperFirst(key as string)}`;\n const hook = this[hookName as keyof this];\n\n if (typeof hook === \"function\") {\n const result = (\n hook as (\n value: ModuleTypeToPropsMapping[T][K],\n ) => ModuleTypeToPropsMapping[T][K] | undefined\n ).call(this, value);\n return result;\n }\n return undefined;\n }\n\n serialize(): IModuleSerialize<T> {\n return {\n id: this.id,\n name: this.name,\n moduleType: this.moduleType,\n voiceNo: this.voiceNo,\n props: this.props,\n inputs: this.inputs.serialize(),\n outputs: this.outputs.serialize(),\n };\n }\n\n plug({\n audioModule,\n from,\n to,\n }: {\n audioModule: AnyModule;\n from: string;\n to: string;\n }) {\n const output = this.outputs.findByName(from);\n const input = audioModule.inputs.findByName(to);\n\n output.plug(input);\n }\n\n protected rePlugAll(callback?: () => void) {\n this.inputs.rePlugAll(callback);\n this.outputs.rePlugAll(callback);\n }\n\n protected unPlugAll() {\n this.inputs.unPlugAll();\n this.outputs.unPlugAll();\n }\n\n start(_time: ContextTime): void {\n // Optional implementation in modules\n }\n\n stop(_time: ContextTime): void {\n // Optional implementation in modules\n }\n\n triggerAttack(note: Note, _triggeredAt: ContextTime): void {\n if (this.activeNotes.some((n) => n.fullName === note.fullName)) return;\n\n this.activeNotes.push(note);\n }\n\n triggerRelease(note: Note, _triggeredAt: ContextTime): void {\n this.activeNotes = this.activeNotes.filter(\n (n) => n.fullName !== note.fullName,\n );\n }\n\n handleCC(_event: MidiEvent, _triggeredAt: ContextTime): void {\n // Optional implementation in modules\n }\n\n onMidiEvent = (midiEvent: MidiEvent) => {\n const { note, triggeredAt } = midiEvent;\n\n switch (midiEvent.type) {\n case MidiEventType.noteOn: {\n this.triggerAttack(note!, triggeredAt);\n break;\n }\n case MidiEventType.noteOff:\n this.triggerRelease(note!, triggeredAt);\n break;\n case MidiEventType.cc:\n this.handleCC(midiEvent, triggeredAt);\n break;\n default:\n throw Error(\"This type is not a note\");\n }\n };\n\n triggerPropsUpdate = () => {\n if (this.pendingUIUpdates) return;\n\n this.pendingUIUpdates = true;\n this.sheduleTriggerUpdate();\n };\n\n private sheduleTriggerUpdate() {\n requestAnimationFrame(() => {\n this.engine._triggerPropsUpdate({\n id: this.id,\n moduleType: this.moduleType,\n voiceNo: this.voiceNo,\n name: this.name,\n props: this.props,\n });\n this.pendingUIUpdates = false;\n });\n }\n\n dispose() {\n this.inputs.unPlugAll();\n this.outputs.unPlugAll();\n }\n\n protected registerDefaultIOs(value: \"both\" | \"in\" | \"out\" = \"both\") {\n this.registerMidiInput({\n name: \"midi in\",\n onMidiEvent: this.onMidiEvent,\n });\n\n if (!this.audioNode) return;\n\n if (value === \"in\" || value === \"both\") {\n this.registerAudioInput({\n name: \"in\",\n getAudioNode: () => this.audioNode!,\n });\n }\n\n if (value === \"out\" || value === \"both\") {\n this.registerAudioOutput({\n name: \"out\",\n getAudioNode: () => this.audioNode!,\n });\n }\n }\n\n protected registerAudioInput(props: Omit<AudioInputProps, \"ioType\">) {\n return this.inputs.add({ ...props, ioType: IOType.AudioInput });\n }\n\n protected registerAudioOutput(props: Omit<AudioOutputProps, \"ioType\">) {\n return this.outputs.add({ ...props, ioType: IOType.AudioOutput });\n }\n\n protected registerMidiInput(props: Omit<MidiInputProps, \"ioType\">) {\n return this.inputs.add({ ...props, ioType: IOType.MidiInput });\n }\n\n protected registerMidiOutput(props: Omit<MidiOutputProps, \"ioType\">) {\n return this.outputs.add({\n ...props,\n ioType: IOType.MidiOutput,\n });\n }\n\n protected get engine() {\n return Engine.getById(this.engineId);\n }\n\n protected get context() {\n return this.engine.context;\n }\n}\n","import { assertNever } from \"@blibliki/utils\";\nimport { sortBy } from \"es-toolkit\";\nimport { ModuleType } from \"@/modules\";\nimport { Module } from \"../module\";\nimport { PolyModule } from \"../module/PolyModule\";\nimport {\n AudioInput,\n AudioInputProps,\n AudioOutput,\n AudioOutputProps,\n} from \"./AudioIO\";\nimport { Base, IOType } from \"./Base\";\nimport {\n MidiInput,\n MidiInputProps,\n MidiOutput,\n MidiOutputProps,\n} from \"./MidiIO\";\nimport {\n PolyAudioInput,\n PolyAudioInputProps,\n PolyAudioOutput,\n PolyAudioOutputProps,\n} from \"./PolyAudioIO\";\n\nexport enum CollectionType {\n Input = \"Input\",\n Output = \"Output\",\n}\n\ntype IMappedIOProps = {\n [CollectionType.Input]:\n | AudioInputProps\n | PolyAudioInputProps\n | MidiInputProps;\n [CollectionType.Output]:\n | AudioOutputProps\n | PolyAudioOutputProps\n | MidiOutputProps;\n};\n\ntype IIOTypeTOClass = {\n [IOType.AudioInput]: AudioInput;\n [IOType.AudioOutput]: AudioOutput;\n [IOType.PolyAudioInput]: PolyAudioInput;\n [IOType.PolyAudioOutput]: PolyAudioOutput;\n [IOType.MidiInput]: MidiInput;\n [IOType.MidiOutput]: MidiOutput;\n};\n\nexport default abstract class IOCollection<T extends CollectionType> {\n module: Module<ModuleType> | PolyModule<ModuleType>;\n collection: Base[] = [];\n collectionType: T;\n\n constructor(\n collectionType: T,\n module: Module<ModuleType> | PolyModule<ModuleType>,\n ) {\n this.collectionType = collectionType;\n this.module = module;\n }\n\n add<TT extends IMappedIOProps[T]>(props: TT): IIOTypeTOClass[TT[\"ioType\"]] {\n let io:\n | AudioInput\n | AudioOutput\n | PolyAudioInput\n | PolyAudioOutput\n | MidiInput\n | MidiOutput;\n this.validateUniqName(props.name);\n\n switch (props.ioType) {\n case IOType.AudioInput:\n if (this.module instanceof PolyModule) throw Error(\"Not compatible\");\n io = new AudioInput(this.module, props);\n break;\n case IOType.AudioOutput:\n if (this.module instanceof PolyModule) throw Error(\"Not compatible\");\n io = new AudioOutput(this.module, props);\n break;\n case IOType.PolyAudioInput:\n if (this.module instanceof Module) throw Error(\"Not compatible\");\n io = new PolyAudioInput(this.module, props);\n break;\n case IOType.PolyAudioOutput:\n if (this.module instanceof Module) throw Error(\"Not compatible\");\n io = new PolyAudioOutput(this.module, props);\n break;\n case IOType.MidiInput:\n io = new MidiInput(this.module, props);\n break;\n case IOType.MidiOutput:\n io = new MidiOutput(this.module, props);\n break;\n default:\n assertNever(props);\n }\n\n this.collection.push(io);\n\n return io as IIOTypeTOClass[TT[\"ioType\"]];\n }\n\n unPlugAll() {\n this.collection.forEach((io) => {\n io.unPlugAll();\n });\n }\n\n rePlugAll(callback?: () => void) {\n this.collection.forEach((io) => {\n io.rePlugAll(callback);\n });\n }\n\n find(id: string) {\n const io = this.collection.find((io) => io.id === id);\n if (!io) throw Error(`The io with id ${id} is not exists`);\n\n return io;\n }\n\n findByName(name: string) {\n const io = this.collection.find((io) => io.name === name);\n if (!io) throw Error(`The io with name ${name} is not exists`);\n\n return io;\n }\n\n serialize() {\n return sortBy(this.collection, [(io) => (io.isMidi() ? -1 : 1)]).map((io) =>\n io.serialize(),\n );\n }\n\n private validateUniqName(name: string) {\n if (this.collection.some((io) => io.name === name)) {\n throw Error(`An io with name ${name} is already exists`);\n }\n }\n}\n\nexport class InputCollection extends IOCollection<CollectionType.Input> {\n constructor(module: Module<ModuleType> | PolyModule<ModuleType>) {\n super(CollectionType.Input, module);\n }\n}\n\nexport class OutputCollection extends IOCollection<CollectionType.Output> {\n constructor(module: Module<ModuleType> | PolyModule<ModuleType>) {\n super(CollectionType.Output, module);\n }\n}\n","import { ContextTime } from \"@blibliki/transport\";\nimport { deterministicId, Optional, uuidv4 } from \"@blibliki/utils\";\nimport { Engine } from \"@/Engine\";\nimport { ModuleType, ModuleTypeToPropsMapping } from \"@/modules\";\nimport {\n IIOSerialize,\n InputCollection,\n IOType,\n MidiInputProps,\n MidiOutputProps,\n OutputCollection,\n} from \"../IO\";\nimport { PolyAudioInputProps, PolyAudioOutputProps } from \"../IO/PolyAudioIO\";\nimport MidiEvent from \"../midi/MidiEvent\";\nimport { IModule, IModuleConstructor, Module } from \"./Module\";\n\nexport type IPolyModule<T extends ModuleType> = Omit<IModule<T>, \"voiceNo\"> & {\n voices: number;\n};\n\nexport type IPolyModuleSerialize<T extends ModuleType> = IPolyModule<T> & {\n inputs: IIOSerialize[];\n outputs: IIOSerialize[];\n};\n\nexport type IPolyModuleConstructor<T extends ModuleType> = Optional<\n IPolyModule<T>,\n \"id\"\n> & {\n monoModuleConstructor: (\n engineId: string,\n params: IModuleConstructor<T>,\n ) => Module<T>;\n};\n\nexport abstract class PolyModule<T extends ModuleType>\n implements IPolyModule<T>\n{\n id: string;\n engineId: string;\n moduleType: T;\n audioModules!: Module<T>[];\n inputs: InputCollection;\n outputs: OutputCollection;\n protected monoModuleConstructor: IPolyModuleConstructor<T>[\"monoModuleConstructor\"];\n protected _props!: ModuleTypeToPropsMapping[T];\n private _voices!: number;\n private _name!: string;\n private pendingUIUpdates = false;\n\n constructor(engineId: string, params: IPolyModuleConstructor<T>) {\n const { id, name, moduleType, voices, monoModuleConstructor, props } =\n params;\n\n this.audioModules = [];\n\n this.monoModuleConstructor = monoModuleConstructor;\n this.id = id ?? uuidv4();\n this.engineId = engineId;\n this.name = name;\n this.moduleType = moduleType;\n this._props = props;\n\n this.inputs = new InputCollection(\n this as unknown as PolyModule<ModuleType>,\n );\n this.outputs = new OutputCollection(\n this as unknown as PolyModule<ModuleType>,\n );\n\n // Defer hook calls until after subclass is fully initialized\n queueMicrotask(() => {\n this.voices = voices || 1;\n this.props = props;\n });\n }\n\n get name() {\n return this._name;\n }\n\n set name(value: string) {\n this._name = value;\n this.audioModules.forEach((m) => (m.name = value));\n }\n\n get props(): ModuleTypeToPropsMapping[T] {\n return this._props;\n }\n\n set props(value: Partial<ModuleTypeToPropsMapping[T]>) {\n this._props = { ...this._props, ...value };\n this.audioModules.forEach((m) => (m.props = value));\n }\n\n get voices() {\n return this._voices;\n }\n\n set voices(value: number) {\n this._voices = value;\n this.adjustNumberOfModules();\n this.rePlugAll();\n }\n\n start(time: ContextTime): void {\n this.audioModules.forEach((m) => {\n m.start(time);\n });\n }\n\n stop(time: ContextTime): void {\n this.audioModules.forEach((m) => {\n m.stop(time);\n });\n }\n\n serialize(): IPolyModuleSerialize<T> {\n return {\n id: this.id,\n name: this.name,\n moduleType: this.moduleType,\n voices: this.voices,\n props: this.props,\n inputs: this.inputs.serialize(),\n outputs: this.outputs.serialize(),\n };\n }\n\n plug({\n audioModule,\n from,\n to,\n }: {\n audioModule: Module<ModuleType> | PolyModule<ModuleType>;\n from: string;\n to: string;\n }) {\n const output = this.outputs.findByName(from);\n const input = audioModule.inputs.findByName(to);\n\n output.plug(input);\n }\n\n rePlugAll(callback?: () => void) {\n this.inputs.rePlugAll(callback);\n this.outputs.rePlugAll(callback);\n }\n\n protected unPlugAll() {\n this.inputs.unPlugAll();\n this.outputs.unPlugAll();\n }\n\n dispose() {\n this.inputs.unPlugAll();\n this.outputs.unPlugAll();\n this.audioModules.forEach((m) => {\n m.dispose();\n });\n }\n\n onMidiEvent = (midiEvent: MidiEvent) => {\n const voiceNo = midiEvent.voiceNo ?? 0;\n const audioModule = this.findVoice(voiceNo);\n audioModule.onMidiEvent(midiEvent);\n };\n\n triggerPropsUpdate = () => {\n if (this.pendingUIUpdates) return;\n\n this.pendingUIUpdates = true;\n this.sheduleTriggerUpdate();\n };\n\n private sheduleTriggerUpdate() {\n requestAnimationFrame(() => {\n this.engine._triggerPropsUpdate({\n id: this.id,\n moduleType: this.moduleType,\n voices: this.voices,\n name: this.name,\n props: this.props,\n });\n this.pendingUIUpdates = false;\n });\n }\n\n findVoice(voiceNo: number) {\n const moduleByVoice = this.audioModules.find((m) => m.voiceNo === voiceNo);\n if (!moduleByVoice)\n throw Error(`Voice ${voiceNo} on module ${this.name} not found`);\n\n return moduleByVoice;\n }\n\n protected registerDefaultIOs(value: \"both\" | \"in\" | \"out\" = \"both\") {\n this.registerMidiInput({\n name: \"midi in\",\n onMidiEvent: this.onMidiEvent,\n });\n\n if (value === \"in\" || value === \"both\") {\n this.registerAudioInput({\n name: \"in\",\n });\n }\n\n if (value === \"out\" || value === \"both\") {\n this.registerAudioOutput({\n name: \"out\",\n });\n }\n }\n\n protected registerAudioInput(props: Omit<PolyAudioInputProps, \"ioType\">) {\n return this.inputs.add({ ...props, ioType: IOType.PolyAudioInput });\n }\n\n protected registerAudioOutput(props: Omit<PolyAudioOutputProps, \"ioType\">) {\n return this.outputs.add({ ...props, ioType: IOType.PolyAudioOutput });\n }\n\n protected registerMidiInput(props: Omit<MidiInputProps, \"ioType\">) {\n return this.inputs.add({ ...props, ioType: IOType.MidiInput });\n }\n\n protected registerMidiOutput(props: Omit<MidiOutputProps, \"ioType\">) {\n return this.outputs.add({\n ...props,\n ioType: IOType.MidiOutput,\n });\n }\n\n private adjustNumberOfModules() {\n if (this.audioModules.length === this.voices) return;\n\n if (this.audioModules.length > this.voices) {\n const audioModule = this.audioModules.pop();\n audioModule?.dispose();\n } else {\n const voiceNo = this.audioModules.length;\n const id = deterministicId(this.id, voiceNo.toString());\n\n const audioModule = this.monoModuleConstructor(this.engineId, {\n id,\n name: this.name,\n moduleType: this.moduleType,\n voiceNo,\n props: { ...this.props },\n });\n\n this.audioModules.push(audioModule);\n }\n\n this.adjustNumberOfModules();\n }\n\n protected get engine() {\n return Engine.getById(this.engineId);\n }\n\n protected get context() {\n return this.engine.context;\n }\n}\n","import { deterministicId } from \"@blibliki/utils\";\nimport { ModuleType } from \"@/modules\";\nimport { Module } from \"../module\";\nimport { PolyModule } from \"../module/PolyModule\";\nimport { AudioInput, AudioOutput } from \"./AudioIO\";\nimport { MidiInput, MidiOutput } from \"./MidiIO\";\nimport { PolyAudioInput, PolyAudioOutput } from \"./PolyAudioIO\";\n\nexport type IOProps = {\n name: string;\n ioType: IOType;\n};\n\nexport type IIOSerialize = IOProps & {\n id: string;\n moduleId: string;\n};\n\nexport enum IOType {\n AudioInput = \"audioInput\",\n AudioOutput = \"audioOutput\",\n PolyAudioInput = \"polyAudioInput\",\n PolyAudioOutput = \"polyAudioOutput\",\n MidiOutput = \"midiOutput\",\n MidiInput = \"midiInput\",\n}\n\nexport type IIO = {\n id: string;\n module: Module<ModuleType> | PolyModule<ModuleType>;\n} & IOProps;\n\nexport abstract class Base implements IIO {\n id: string;\n ioType: IOType;\n name: string;\n module: Module<ModuleType> | PolyModule<ModuleType>;\n connections: Base[];\n\n constructor(\n module: Module<ModuleType> | PolyModule<ModuleType>,\n props: IOProps,\n ) {\n this.module = module;\n this.name = props.name;\n this.ioType = props.ioType;\n this.id = deterministicId(this.module.id, this.name);\n this.connections = [];\n }\n\n plug(io: Base, plugOther = true) {\n this.connections.push(io);\n if (plugOther) io.plug(this, false);\n }\n\n unPlug(io: Base, plugOther = true) {\n this.connections = this.connections.filter(\n (currentIO) => currentIO.id !== io.id,\n );\n if (plugOther) io.unPlug(this, false);\n }\n\n rePlugAll(callback?: () => void) {\n const connections = this.connections;\n this.unPlugAll();\n if (callback) callback();\n\n connections.forEach((otherIO) => {\n this.plug(otherIO);\n });\n }\n\n unPlugAll() {\n this.connections.forEach((otherIO) => {\n this.unPlug(otherIO);\n });\n }\n\n isAudio(): this is\n | AudioInput\n | AudioOutput\n | PolyAudioInput\n | PolyAudioOutput {\n return (\n this.ioType === IOType.AudioInput ||\n this.ioType === IOType.AudioOutput ||\n this.ioType === IOType.PolyAudioInput ||\n this.ioType === IOType.PolyAudioOutput\n );\n }\n\n isMidi(): this is MidiInput | MidiOutput {\n return (\n this.ioType === IOType.MidiInput || this.ioType === IOType.MidiOutput\n );\n }\n\n serialize(): IIOSerialize {\n return {\n id: this.id,\n name: this.name,\n ioType: this.ioType,\n moduleId: this.module.id,\n };\n }\n}\n\nexport default abstract class IO<Connection extends Base> extends Base {\n declare connections: Connection[];\n\n plug(io: Connection, plugOther?: boolean): void {\n super.plug(io, plugOther);\n }\n\n unPlug(io: Connection, plugOther?: boolean): void {\n super.unPlug(io, plugOther);\n }\n}\n","import { ModuleType } from \"@/modules\";\nimport { PolyModule } from \"../module/PolyModule\";\nimport { AudioInput, AudioOutput } from \"./AudioIO\";\nimport IO, { IOProps, IOType } from \"./Base\";\n\nexport type PolyAudioIO = PolyAudioInput | PolyAudioOutput;\n\nexport type PolyAudioInputProps = IOProps & {\n ioType: IOType.PolyAudioInput;\n};\n\nexport type PolyAudioOutputProps = IOProps & {\n ioType: IOType.PolyAudioOutput;\n};\n\nexport class PolyAudioInput\n extends IO<PolyAudioOutput | AudioOutput>\n implements PolyAudioInputProps\n{\n declare ioType: IOType.PolyAudioInput;\n declare module: PolyModule<ModuleType>;\n\n plug(io: PolyAudioOutput | AudioOutput, plugOther = true) {\n super.plug(io, plugOther);\n if (!plugOther && io instanceof PolyAudioOutput) return;\n\n plugOrUnplug(this, io, true);\n }\n\n unPlug(io: PolyAudioOutput | AudioOutput, plugOther = true) {\n super.unPlug(io, plugOther);\n if (!plugOther && io instanceof PolyAudioOutput) return;\n\n plugOrUnplug(this, io, false);\n }\n\n findIOByVoice(voice: number): AudioInput {\n return this.module\n .findVoice(voice)\n .inputs.findByName(this.name) as AudioInput;\n }\n}\n\nexport class PolyAudioOutput\n extends IO<PolyAudioInput | AudioInput>\n implements PolyAudioOutputProps\n{\n declare ioType: IOType.PolyAudioOutput;\n declare module: PolyModule<ModuleType>;\n\n plug(io: PolyAudioInput | AudioInput, plugOther = true) {\n super.plug(io, plugOther);\n if (!plugOther && io instanceof PolyAudioInput) return;\n\n plugOrUnplug(this, io, true);\n }\n\n unPlug(io: PolyAudioInput | AudioInput, plugOther = true) {\n super.unPlug(io, plugOther);\n if (!plugOther && io instanceof PolyAudioInput) return;\n\n plugOrUnplug(this, io, false);\n }\n\n findIOByVoice(voice: number): AudioOutput {\n return this.module\n .findVoice(voice)\n .outputs.findByName(this.name) as AudioOutput;\n }\n}\n\nfunction plugOrUnplug(\n thisIO: PolyAudioInput,\n otherIO: PolyAudioOutput | AudioOutput,\n isPlug: boolean,\n): void;\nfunction plugOrUnplug(\n thisIO: PolyAudioOutput,\n otherIO: PolyAudioInput | AudioInput,\n isPlug: boolean,\n): void;\nfunction plugOrUnplug(\n thisIO: PolyAudioInput | PolyAudioOutput,\n otherIO: PolyAudioOutput | AudioOutput | PolyAudioInput | AudioInput,\n isPlug: boolean,\n) {\n if (otherIO instanceof PolyAudioInput || otherIO instanceof PolyAudioOutput) {\n const maxVoices = Math.max(thisIO.module.voices, otherIO.module.voices);\n\n for (let voice = 0; voice < maxVoices; voice++) {\n const thisMonoIO = thisIO.findIOByVoice(voice % thisIO.module.voices);\n const otherMonoIO = otherIO.findIOByVoice(voice % otherIO.module.voices);\n\n if (isPlug) {\n // @ts-expect-error: temp solution until guard this input plug to output\n thisMonoIO.plug(otherMonoIO);\n } else {\n // @ts-expect-error: temp solution until guard this input plug to output\n thisMonoIO.unPlug(otherMonoIO);\n }\n }\n } else {\n for (let voice = 0; voice < thisIO.module.voices; voice++) {\n const thisMonoIO = thisIO.findIOByVoice(voice);\n\n if (isPlug) {\n // @ts-expect-error: temp solution until guard this input plug to output\n thisMonoIO.plug(otherIO);\n } else {\n // @ts-expect-error: temp solution until guard this input plug to output\n thisMonoIO.unPlug(otherIO);\n }\n }\n }\n}\n","import { ModuleType } from \"@/modules\";\nimport { Module } from \"../module\";\nimport IO, { IOProps, IOType } from \"./Base\";\nimport { PolyAudioInput, PolyAudioOutput } from \"./PolyAudioIO\";\n\nexport type AudioIO = AudioInput | AudioOutput;\n\nexport type AudioInputProps = IOProps & {\n ioType: IOType.AudioInput;\n getAudioNode: () => AudioNode | AudioParam | AudioDestinationNode;\n};\n\nexport type AudioOutputProps = IOProps & {\n ioType: IOType.AudioOutput;\n getAudioNode: () => AudioNode;\n};\n\nexport class AudioInput\n extends IO<AudioOutput | PolyAudioOutput>\n implements AudioInputProps\n{\n declare ioType: IOType.AudioInput;\n getAudioNode: AudioInputProps[\"getAudioNode\"];\n\n constructor(module: Module<ModuleType>, props: AudioInputProps) {\n super(module, props);\n this.getAudioNode = props.getAudioNode;\n }\n}\n\nexport class AudioOutput\n extends IO<AudioInput | PolyAudioInput>\n implements AudioOutputProps\n{\n declare ioType: IOType.AudioOutput;\n getAudioNode!: AudioOutputProps[\"getAudioNode\"];\n\n constructor(module: Module<ModuleType>, props: AudioOutputProps) {\n super(module, props);\n this.getAudioNode = props.getAudioNode;\n }\n\n plug(io: AudioInput | PolyAudioInput, plugOther = true) {\n super.plug(io, plugOther);\n if (io instanceof PolyAudioInput) return;\n\n const input = io.getAudioNode();\n\n if (input instanceof AudioParam) {\n this.getAudioNode().connect(input);\n } else {\n this.getAudioNode().connect(input);\n }\n }\n\n unPlug(io: AudioInput | PolyAudioInput, plugOther = true) {\n super.unPlug(io, plugOther);\n if (io instanceof PolyAudioInput) return;\n\n const input = io.getAudioNode();\n\n try {\n if (input instanceof AudioParam) {\n this.getAudioNode().disconnect(input);\n } else {\n this.getAudioNode().disconnect(input);\n }\n } catch {\n // Ignore disconnect errors\n }\n }\n}\n","import { ModuleType } from \"@/modules\";\nimport MidiEvent from \"../midi/MidiEvent\";\nimport { Module } from \"../module\";\nimport { PolyModule } from \"../module/PolyModule\";\nimport IO, { IOProps, IOType } from \"./Base\";\n\nexport type MidiIO = MidiInput | MidiOutput;\n\nexport type MidiInputProps = IOProps & {\n ioType: IOType.MidiInput;\n onMidiEvent: (event: MidiEvent) => void;\n};\n\nexport type MidiOutputProps = IOProps & {\n ioType: IOType.MidiOutput;\n};\n\nexport class MidiInput extends IO<MidiOutput> implements MidiInputProps {\n declare ioType: IOType.MidiInput;\n onMidiEvent: MidiInputProps[\"onMidiEvent\"];\n\n constructor(\n module: Module<ModuleType> | PolyModule<ModuleType>,\n props: MidiInputProps,\n ) {\n super(module, props);\n this.onMidiEvent = props.onMidiEvent;\n }\n}\n\nexport class MidiOutput extends IO<MidiInput> implements MidiOutputProps {\n declare ioType: IOType.MidiOutput;\n\n onMidiEvent = (event: MidiEvent) => {\n this.midiConnections.forEach((input) => {\n input.onMidiEvent(event);\n });\n };\n\n private get midiConnections() {\n return this.connections.filter((input) => input instanceof MidiInput);\n }\n}\n","/**\n * Simple wrapper around MIDI message data (Uint8Array)\n * Replaces the webmidi Message class with native Web MIDI API data\n */\nexport default class Message {\n public readonly data: Uint8Array;\n\n constructor(data: Uint8Array) {\n this.data = data;\n }\n\n /**\n * Returns the data bytes (excluding the status byte)\n */\n get dataBytes(): number[] {\n return Array.from(this.data.slice(1));\n }\n\n /**\n * Returns the MIDI message type based on the status byte\n */\n get type(): string {\n const statusByte = this.data[0];\n const messageType = statusByte & 0xf0;\n\n switch (messageType) {\n case 0x90: // Note On\n // Check if velocity is 0 (which is actually Note Off)\n return this.data[2] === 0 ? \"noteoff\" : \"noteon\";\n case 0x80: // Note Off\n return \"noteoff\";\n case 0xb0: // Control Change\n return \"controlchange\";\n case 0xe0: // Pitch Bend\n return \"pitchbend\";\n case 0xd0: // Channel Pressure (Aftertouch)\n return \"channelaftertouch\";\n case 0xa0: // Polyphonic Key Pressure\n return \"keyaftertouch\";\n case 0xc0: // Program Change\n return \"programchange\";\n default:\n return \"unknown\";\n }\n }\n}\n","const frequencyTable = new Map<string, number>([\n [\"C0\", 16.35],\n [\"C#0\", 17.32],\n [\"Db0\", 17.32],\n [\"D0\", 18.35],\n [\"D#0\", 19.45],\n [\"Eb0\", 19.45],\n [\"E0\", 20.6],\n [\"F0\", 21.83],\n [\"F#0\", 23.12],\n [\"Gb0\", 23.12],\n [\"G0\", 24.5],\n [\"G#0\", 25.96],\n [\"Ab0\", 25.96],\n [\"A0\", 27.5],\n [\"A#0\", 29.14],\n [\"Bb0\", 29.14],\n [\"B0\", 30.87],\n [\"C1\", 32.7],\n [\"C#1\", 34.65],\n [\"Db1\", 34.65],\n [\"D1\", 36.71],\n [\"D#1\", 38.89],\n [\"Eb1\", 38.89],\n [\"E1\", 41.2],\n [\"F1\", 43.65],\n [\"F#1\", 46.25],\n [\"Gb1\", 46.25],\n [\"G1\", 49.0],\n [\"G#1\", 51.91],\n [\"Ab1\", 51.91],\n [\"A1\", 55.0],\n [\"A#1\", 58.27],\n [\"Bb1\", 58.27],\n [\"B1\", 61.74],\n [\"C2\", 65.41],\n [\"C#2\", 69.3],\n [\"Db2\", 69.3],\n [\"D2\", 73.42],\n [\"D#2\", 77.78],\n [\"Eb2\", 77.78],\n [\"E2\", 82.41],\n [\"F2\", 87.31],\n [\"F#2\", 92.5],\n [\"Gb2\", 92.5],\n [\"G2\", 98.0],\n [\"G#2\", 103.83],\n [\"Ab2\", 103.83],\n [\"A2\", 110.0],\n [\"A#2\", 116.54],\n [\"Bb2\", 116.54],\n [\"B2\", 123.47],\n [\"C3\", 130.81],\n [\"C#3\", 138.59],\n [\"Db3\", 138.59],\n [\"D3\", 146.83],\n [\"D#3\", 155.56],\n [\"Eb3\", 155.56],\n [\"E3\", 164.81],\n [\"F3\", 174.61],\n [\"F#3\", 185.0],\n [\"Gb3\", 185.0],\n [\"G3\", 196.0],\n [\"G#3\", 207.65],\n [\"Ab3\", 207.65],\n [\"A3\", 220.0],\n [\"A#3\", 233.08],\n [\"Bb3\", 233.08],\n [\"B3\", 246.94],\n [\"C4\", 261.63],\n [\"C#4\", 277.18],\n [\"Db4\", 277.18],\n [\"D4\", 293.66],\n [\"D#4\", 311.13],\n [\"Eb4\", 311.13],\n [\"E4\", 329.63],\n [\"F4\", 349.23],\n [\"F#4\", 369.99],\n [\"Gb4\", 369.99],\n [\"G4\", 392.0],\n [\"G#4\", 415.3],\n [\"Ab4\", 415.3],\n [\"A4\", 440.0],\n [\"A#4\", 466.16],\n [\"Bb4\", 466.16],\n [\"B4\", 493.88],\n [\"C5\", 523.25],\n [\"C#5\", 554.37],\n [\"Db5\", 554.37],\n [\"D5\", 587.33],\n [\"D#5\", 622.25],\n [\"Eb5\", 622.25],\n [\"E5\", 659.26],\n [\"F5\", 698.46],\n [\"F#5\", 739.99],\n [\"Gb5\", 739.99],\n [\"G5\", 783.99],\n [\"G#5\", 830.61],\n [\"Ab5\", 830.61],\n [\"A5\", 880.0],\n [\"A#5\", 932.33],\n [\"Bb5\", 932.33],\n [\"B5\", 987.77],\n [\"C6\", 1046.5],\n [\"C#6\", 1108.73],\n [\"Db6\", 1108.73],\n [\"D6\", 1174.66],\n [\"D#6\", 1244.51],\n [\"Eb6\", 1244.51],\n [\"E6\", 1318.51],\n [\"F6\", 1396.91],\n [\"F#6\", 1479.98],\n [\"Gb6\", 1479.98],\n [\"G6\", 1567.98],\n [\"G#6\", 1661.22],\n [\"Ab6\", 1661.22],\n [\"A6\", 1760.0],\n [\"A#6\", 1864.66],\n [\"Bb6\", 1864.66],\n [\"B6\", 1975.53],\n [\"C7\", 2093.0],\n [\"C#7\", 2217.46],\n [\"Db7\", 2217.46],\n [\"D7\", 2349.32],\n [\"D#7\", 2489.02],\n [\"Eb7\", 2489.02],\n [\"E7\", 2637.02],\n [\"F7\", 2793.83],\n [\"F#7\", 2959.96],\n [\"Gb7\", 2959.96],\n [\"G7\", 3135.96],\n [\"G#7\", 3322.44],\n [\"Ab7\", 3322.44],\n [\"A7\", 3520.0],\n [\"A#7\", 3729.31],\n [\"Bb7\", 3729.31],\n [\"B7\", 3951.07],\n [\"C8\", 4186.01],\n [\"C#8\", 4434.92],\n [\"Db8\", 4434.92],\n [\"D8\", 4698.64],\n [\"D#8\", 4978.03],\n [\"Eb8\", 4978.03],\n]);\n\nexport default frequencyTable;\n","import { Seconds } from \"@blibliki/transport\";\nimport Message from \"../midi/Message\";\nimport frequencyTable from \"./frequencyTable\";\n\nconst Notes = [\"C\", \"C#\", \"D\", \"D#\", \"E\", \"F\", \"F#\", \"G\", \"G#\", \"A\", \"A#\", \"B\"];\n\nconst MIDI_OCTAVE_SYTSTEM = 2;\n\nexport type INote = {\n name: string;\n octave: number;\n frequency: number;\n duration?: Seconds;\n velocity?: number;\n};\n\nexport default class Note implements INote {\n static _notes: Note[];\n name!: string;\n octave!: number;\n velocity = 1;\n duration?: Seconds;\n\n static fromFrequency(frequency: number) {\n let noteName: string | undefined;\n\n for (const [note, freq] of frequencyTable) {\n if (freq !== frequency) continue;\n\n noteName = note;\n break;\n }\n\n if (!noteName) throw Error(\"Not matching frequency with a note\");\n\n return new Note(noteName);\n }\n\n static fromEvent(message: Message) {\n const name = Notes[message.data[1] % 12];\n const octave = Math.floor(message.data[1] / 12) - 2;\n\n return new Note(`${name}${octave}`);\n }\n\n static notes(octave = 3) {\n return Notes.map((note: string) => new Note(`${note}${octave}`));\n }\n\n constructor(note: Omit<INote, \"frequency\"> | string) {\n if (typeof note === \"string\") {\n this.fromString(note);\n } else {\n this.fromProps(note);\n }\n }\n\n get isSemi() {\n return this.name.endsWith(\"#\");\n }\n\n get fullName() {\n return `${this.name}${this.octave}`;\n }\n\n get frequency(): number {\n return frequencyTable.get(`${this.name}${this.octave}`)!;\n }\n\n midiData(noteOn = true): Uint8Array {\n const statusByte = noteOn ? 0x90 : 0x80;\n return new Uint8Array([statusByte, this.midiNumber, this.velocity * 100]);\n }\n\n get midiNumber(): number {\n return (this.octave + MIDI_OCTAVE_SYTSTEM) * 12 + this.noteIndex;\n }\n\n get noteIndex(): number {\n return Notes.indexOf(this.name);\n }\n\n valueOf() {\n return this.fullName;\n }\n\n serialize(): INote {\n return {\n name: this.name,\n octave: this.octave,\n frequency: this.frequency,\n velocity: this.velocity,\n duration: this.duration,\n };\n }\n\n private fromString(string: string) {\n const matches = /(\\w#?)(\\d)?/.exec(string) ?? [];\n\n this.name = matches[1];\n this.octave = matches[2] ? parseInt(matches[2]) : 1;\n }\n\n private fromProps(props: Omit<INote, \"frequency\">) {\n Object.assign(this, props);\n }\n}\n","import { ContextTime } from \"@blibliki/transport\";\nimport Message from \"./Message\";\nimport Note, { INote } from \"../Note\";\n\nexport enum MidiEventType {\n noteOn = \"noteon\",\n noteOff = \"noteoff\",\n cc = \"controlchange\",\n}\n\nexport default class MidiEvent {\n note?: Note;\n voiceNo?: number;\n readonly triggeredAt: ContextTime;\n private message: Message;\n\n static fromNote(\n noteName: string | Note | Omit<INote, \"frequency\">,\n noteOn = true,\n triggeredAt: ContextTime,\n ): MidiEvent {\n const note = noteName instanceof Note ? noteName : new Note(noteName);\n\n return new MidiEvent(new Message(note.midiData(noteOn)), triggeredAt);\n }\n\n static fromCC(\n cc: number,\n value: number,\n triggeredAt: ContextTime,\n ): MidiEvent {\n return new MidiEvent(\n new Message(new Uint8Array([0xb0, cc, value])),\n triggeredAt,\n );\n }\n\n constructor(message: Message, triggeredAt: ContextTime) {\n this.message = message;\n this.triggeredAt = triggeredAt;\n this.defineNotes();\n }\n\n get type() {\n return this.message.type as MidiEventType;\n }\n\n get isNote() {\n return (\n this.type === MidiEventType.noteOn || this.type === MidiEventType.noteOff\n );\n }\n\n get isCC() {\n return this.type === MidiEventType.cc;\n }\n\n get cc(): number | undefined {\n if (!this.isCC) return;\n\n return this.message.dataBytes[0];\n }\n\n get ccValue(): number | undefined {\n if (!this.isCC) return;\n\n return this.message.dataBytes[1];\n }\n\n defineNotes() {\n if (!this.isNote) return;\n if (this.note) return;\n\n this.note = Note.fromEvent(this.message);\n }\n\n get rawMessage() {\n return this.message;\n }\n\n clone(voiceNo?: number) {\n const newEvent = new MidiEvent(this.message, this.triggeredAt);\n newEvent.voiceNo = voiceNo;\n\n return newEvent;\n }\n}\n","import { Optional, uuidv4 } from \"@blibliki/utils\";\nimport { Engine } from \"@/Engine\";\n\ntype IPlug = {\n moduleId: string;\n ioName: string;\n};\n\nexport type IRoute = {\n id: string;\n source: IPlug;\n destination: IPlug;\n};\n\nexport class Routes {\n engine: Engine;\n routes: Map<string, IRoute>;\n\n constructor(engine: Engine) {\n this.engine = engine;\n this.routes = new Map();\n }\n\n addRoute(props: Optional<IRoute, \"id\">): IRoute {\n const id = props.id ?? uuidv4();\n const route = { ...props, id };\n this.routes.set(id, route);\n\n this.plug(id);\n\n return route;\n }\n\n removeRoute(id: string) {\n this.unPlug(id);\n this.routes.delete(id);\n }\n\n clear() {\n this.routes.forEach((_, id) => {\n this.removeRoute(id);\n });\n }\n\n replug() {\n this.routes.forEach((_, id) => {\n const { sourceIO, destinationIO } = this.getIOs(id);\n sourceIO.rePlugAll();\n destinationIO.rePlugAll();\n });\n }\n\n serialize(): IRoute[] {\n return Array.from(this.routes.values());\n }\n\n private plug(id: string) {\n const { sourceIO, destinationIO } = this.getIOs(id);\n sourceIO.plug(destinationIO);\n }\n\n private unPlug(id: string) {\n const { sourceIO, destinationIO } = this.getIOs(id);\n sourceIO.unPlug(destinationIO);\n }\n\n private find(id: string): IRoute {\n const route = this.routes.get(id);\n if (!route) throw Error(`Route with id ${id} not found`);\n\n return route;\n }\n\n private getIOs(id: string) {\n const route = this.find(id);\n const { source, destination } = route;\n\n const sourceIO = this.engine.findIO(\n source.moduleId,\n source.ioName,\n \"output\",\n );\n const destinationIO = this.engine.findIO(\n destination.moduleId,\n destination.ioName,\n \"input\",\n );\n\n return { sourceIO, destinationIO };\n }\n}\n","import { Context } from \"@blibliki/utils\";\nimport JZZ from \"jzz\";\nimport type { JZZ as JZZType, JZZInputInfo, JZZPort } from \"./jzz.types\";\nimport ComputerKeyboardDevice from \"./ComputerKeyboardDevice\";\nimport MidiDevice from \"./MidiDevice\";\n\ntype ListenerCallback = (device: MidiDevice) => void;\n\nexport default class MidiDeviceManager {\n devices = new Map<string, MidiDevice | ComputerKeyboardDevice>();\n private initialized = false;\n private listeners: ListenerCallback[] = [];\n private context: Readonly<Context>;\n private jzz: JZZType | null = null;\n\n constructor(context: Context) {\n this.context = context;\n this.addComputerKeyboard();\n }\n\n async initialize() {\n await this.initializeDevices();\n\n this.listenChanges();\n this.initialized = true;\n }\n\n find(id: string): MidiDevice | ComputerKeyboardDevice | undefined {\n return this.devices.get(id);\n }\n\n findByName(name: string): MidiDevice | ComputerKeyboardDevice | undefined {\n return Array.from(this.devices.values()).find((d) => d.name === name);\n }\n\n addListener(callback: ListenerCallback) {\n this.listeners.push(callback);\n }\n\n private async initializeDevices() {\n if (this.initialized) return;\n\n try {\n const jzz: JZZType = (await JZZ()) as unknown as JZZType;\n this.jzz = jzz;\n const info = jzz.info();\n\n // Get all MIDI input devices\n for (const inputInfo of info.inputs ?? []) {\n const id: string = inputInfo.id ?? inputInfo.name;\n if (!this.devices.has(id)) {\n const port = (await jzz.openMidiIn(inputInfo.name)) as unknown as JZZPort;\n const device = new MidiDevice(port, id, inputInfo.name, this.context);\n this.devices.set(id, device);\n }\n }\n } catch (err) {\n console.error(\"Error enabling JZZ MIDI:\", err);\n }\n }\n\n private addComputerKeyboard() {\n if (typeof document === \"undefined\") return;\n\n const computerKeyboardDevice = new ComputerKeyboardDevice(this.context);\n this.devices.set(computerKeyboardDevice.id, computerKeyboardDevice);\n }\n\n private listenChanges() {\n if (!this.jzz) return;\n\n // JZZ watch for MIDI device changes\n this.jzz.onChange(() => {\n if (!this.jzz) return;\n\n const info = this.jzz.info();\n const currentInputIds = new Set<string>(\n (info.inputs ?? []).map((i: JZZInputInfo) => i.id ?? i.name),\n );\n\n // Check for new devices\n for (const inputInfo of info.inputs ?? []) {\n const id: string = inputInfo.id ?? inputInfo.name;\n if (!this.devices.has(id)) {\n // New device connected\n void this.jzz\n .openMidiIn(inputInfo.name)\n .then((port: unknown) => {\n const jzzPort = port as JZZPort;\n const device = new MidiDevice(\n jzzPort,\n id,\n inputInfo.name,\n this.context,\n );\n this.devices.set(id, device);\n\n this.listeners.forEach((listener) => {\n listener(device);\n });\n });\n }\n }\n\n // Check for removed devices\n for (const [id, device] of this.devices) {\n if (device instanceof ComputerKeyboardDevice) continue;\n if (!currentInputIds.has(id)) {\n // Device disconnected\n device.disconnect();\n this.devices.delete(id);\n\n this.listeners.forEach((listener) => {\n listener(device);\n });\n }\n }\n });\n }\n}\n","import { Context } from \"@blibliki/utils\";\nimport type { JZZMidiMessage, JZZPort } from \"./jzz.types\";\nimport MidiEvent, { MidiEventType } from \"./MidiEvent\";\nimport Message from \"./Message\";\n\nexport enum MidiPortState {\n connected = \"connected\",\n disconnected = \"disconnected\",\n}\n\nexport type IMidiDevice = {\n id: string;\n name: string;\n state: MidiPortState;\n};\n\nexport type IMidiInput = IMidiDevice & {\n eventListerCallbacks: EventListerCallback[];\n};\n\nexport type EventListerCallback = (event: MidiEvent) => void;\n\nexport default class MidiDevice implements IMidiDevice {\n id: string;\n name: string;\n eventListerCallbacks: EventListerCallback[] = [];\n\n private context: Readonly<Context>;\n private input: JZZPort;\n private _state: MidiPortState = MidiPortState.connected;\n\n constructor(input: JZZPort, id: string, name: string, context: Context) {\n this.id = id;\n this.name = name || `Device ${id}`;\n this.input = input;\n this.context = context;\n\n this.connect();\n }\n\n get state() {\n return this._state;\n }\n\n connect() {\n // JZZ uses a callback function to receive MIDI messages\n this.input.connect((msg: JZZMidiMessage) => {\n this.processEvent(msg);\n });\n }\n\n disconnect() {\n this.input.close();\n this._state = MidiPortState.disconnected;\n }\n\n serialize() {\n const { id, name, state } = this;\n\n return { id, name, state };\n }\n\n addEventListener(callback: EventListerCallback) {\n this.eventListerCallbacks.push(callback);\n }\n\n removeEventListener(callback: EventListerCallback) {\n this.eventListerCallbacks = this.eventListerCallbacks.filter(\n (c) => c !== callback,\n );\n }\n\n private processEvent(msg: JZZMidiMessage) {\n // Convert JZZ MIDI message to Uint8Array\n const data = new Uint8Array(msg.slice());\n const message = new Message(data);\n\n // Use current time as timestamp since JZZ doesn't provide precise timestamps\n const timestamp = performance.now();\n const midiEvent = new MidiEvent(\n message,\n this.context.browserToContextTime(timestamp),\n );\n\n switch (midiEvent.type) {\n case MidiEventType.noteOn:\n case MidiEventType.noteOff:\n case MidiEventType.cc:\n this.eventListerCallbacks.forEach((callback) => {\n callback(midiEvent);\n });\n }\n }\n}\n","import { Context } from \"@blibliki/utils\";\nimport Note from \"../Note\";\nimport { EventListerCallback, IMidiInput, MidiPortState } from \"./MidiDevice\";\nimport MidiEvent from \"./MidiEvent\";\n\nconst MAP_KEYS: Record<string, Note> = {\n a: new Note(\"C3\"),\n s: new Note(\"D3\"),\n d: new Note(\"E3\"),\n f: new Note(\"F3\"),\n g: new Note(\"G3\"),\n h: new Note(\"A3\"),\n j: new Note(\"B3\"),\n k: new Note(\"C4\"),\n l: new Note(\"D4\"),\n w: new Note(\"C#3\"),\n e: new Note(\"D#3\"),\n t: new Note(\"F#3\"),\n y: new Note(\"G#3\"),\n u: new Note(\"A#3\"),\n o: new Note(\"C#4\"),\n p: new Note(\"D#4\"),\n};\n\nconst computerKeyboardData = () => ({\n id: \"computer_keyboard\",\n name: \"Computer Keyboard\",\n state: MidiPortState.connected,\n});\n\nexport default class ComputerKeyboardInput implements IMidiInput {\n id: string;\n name: string;\n state: MidiPortState;\n eventListerCallbacks: EventListerCallback[] = [];\n private context: Readonly<Context>;\n\n constructor(context: Context) {\n const { id, name, state } = computerKeyboardData();\n this.id = id;\n this.name = name;\n this.state = state;\n this.context = context;\n\n document.addEventListener(\"keydown\", this.onKeyTrigger(true));\n document.addEventListener(\"keyup\", this.onKeyTrigger(false));\n }\n\n addEventListener(callback: EventListerCallback) {\n this.eventListerCallbacks.push(callback);\n }\n\n removeEventListener(callback: EventListerCallback) {\n this.eventListerCallbacks = this.eventListerCallbacks.filter(\n (c) => c !== callback,\n );\n }\n\n serialize() {\n const { id, name, state } = this;\n\n return { id, name, state };\n }\n\n onKeyTrigger = (noteOn: boolean) => (event: KeyboardEvent) => {\n const note = this.extractNote(event);\n if (!note) return;\n\n const midiEvent = MidiEvent.fromNote(\n note,\n noteOn,\n this.context.browserToContextTime(event.timeStamp),\n );\n this.eventListerCallbacks.forEach((callback) => {\n callback(midiEvent);\n });\n };\n\n private extractNote(event: KeyboardEvent): Note | undefined {\n if (event.repeat) return;\n\n return MAP_KEYS[event.key];\n }\n}\n","import { assertNever } from \"@blibliki/utils\";\nimport { IModule, Module } from \"@/core\";\nimport { IPolyModuleConstructor } from \"@/core/module/PolyModule\";\nimport VoiceScheduler, {\n IVoiceSchedulerProps,\n voiceSchedulerPropSchema,\n} from \"@/core/module/VoiceScheduler\";\nimport Constant, { constantPropSchema, IConstantProps } from \"./Constant\";\nimport Envelope, { envelopePropSchema, IEnvelopeProps } from \"./Envelope\";\nimport Filter, { filterPropSchema, IFilterProps } from \"./Filter\";\nimport Gain, { gainPropSchema, IGainProps } from \"./Gain\";\nimport Inspector, { IInspectorProps, inspectorPropSchema } from \"./Inspector\";\nimport Master, { IMasterProps, masterPropSchema } from \"./Master\";\nimport MidiMapper, {\n IMidiMapperProps,\n midiMapperPropSchema,\n} from \"./MidiMapper\";\nimport MidiSelector, {\n IMidiSelectorProps,\n midiSelectorPropSchema,\n} from \"./MidiSelector\";\nimport Oscillator, {\n IOscillatorProps,\n oscillatorPropSchema,\n} from \"./Oscillator\";\nimport Scale, { IScaleProps, scalePropSchema } from \"./Scale\";\nimport StepSequencer, {\n IStepSequencerProps,\n stepSequencerPropSchema,\n} from \"./StepSequencer\";\nimport StereoPanner, {\n IStereoPannerProps,\n stereoPannerPropSchema,\n} from \"./StereoPanner\";\nimport VirtualMidi, {\n IVirtualMidiProps,\n virtualMidiPropSchema,\n} from \"./VirtualMidi\";\n\nexport enum ModuleType {\n Master = \"Master\",\n Oscillator = \"Oscillator\",\n Gain = \"Gain\",\n MidiSelector = \"MidiSelector\",\n Envelope = \"Envelope\",\n Filter = \"Filter\",\n Scale = \"Scale\",\n StereoPanner = \"StereoPanner\",\n Inspector = \"Inspector\",\n Constant = \"Constant\",\n MidiMapper = \"MidiMapper\",\n VirtualMidi = \"VirtualMidi\",\n StepSequencer = \"StepSequencer\",\n VoiceScheduler = \"VoiceScheduler\",\n}\n\nexport type ModuleTypeToPropsMapping = {\n [ModuleType.Oscillator]: IOscillatorProps;\n [ModuleType.Gain]: IGainProps;\n [ModuleType.Master]: IMasterProps;\n [ModuleType.MidiSelector]: IMidiSelectorProps;\n [ModuleType.Envelope]: IEnvelopeProps;\n [ModuleType.Filter]: IFilterProps;\n [ModuleType.Scale]: IScaleProps;\n [ModuleType.StereoPanner]: IStereoPannerProps;\n [ModuleType.Inspector]: IInspectorProps;\n [ModuleType.Constant]: IConstantProps;\n [ModuleType.MidiMapper]: IMidiMapperProps;\n [ModuleType.VirtualMidi]: IVirtualMidiProps;\n [ModuleType.StepSequencer]: IStepSequencerProps;\n [ModuleType.VoiceScheduler]: IVoiceSchedulerProps;\n};\n\nexport type ModuleTypeToModuleMapping = {\n [ModuleType.Oscillator]: Oscillator;\n [ModuleType.Gain]: Gain;\n [ModuleType.Master]: Master;\n [ModuleType.MidiSelector]: MidiSelector;\n [ModuleType.Envelope]: Envelope;\n [ModuleType.Filter]: Filter;\n [ModuleType.Scale]: Scale;\n [ModuleType.StereoPanner]: StereoPanner;\n [ModuleType.Inspector]: Inspector;\n [ModuleType.Constant]: Constant;\n [ModuleType.MidiMapper]: MidiMapper;\n [ModuleType.VirtualMidi]: VirtualMidi;\n [ModuleType.StepSequencer]: StepSequencer;\n [ModuleType.VoiceScheduler]: VoiceScheduler;\n};\n\nexport const moduleSchemas = {\n [ModuleType.Oscillator]: oscillatorPropSchema,\n [ModuleType.Gain]: gainPropSchema,\n [ModuleType.Master]: masterPropSchema,\n [ModuleType.MidiSelector]: midiSelectorPropSchema,\n [ModuleType.Envelope]: envelopePropSchema,\n [ModuleType.Filter]: filterPropSchema,\n [ModuleType.Scale]: scalePropSchema,\n [ModuleType.StereoPanner]: stereoPannerPropSchema,\n [ModuleType.Inspector]: inspectorPropSchema,\n [ModuleType.Constant]: constantPropSchema,\n [ModuleType.MidiMapper]: midiMapperPropSchema,\n [ModuleType.VirtualMidi]: virtualMidiPropSchema,\n [ModuleType.StepSequencer]: stepSequencerPropSchema,\n [ModuleType.VoiceScheduler]: voiceSchedulerPropSchema,\n};\n\nexport type { IOscillator } from \"./Oscillator\";\nexport { OscillatorWave } from \"./Oscillator\";\nexport type { IGain } from \"./Gain\";\nexport type { IMaster } from \"./Master\";\nexport type { IMidiSelector } from \"./MidiSelector\";\nexport type { IStereoPanner } from \"./StereoPanner\";\nexport type {\n IStepSequencer,\n IStepSequencerProps,\n ISequence,\n} from \"./StepSequencer\";\nexport type { IMidiMapper, IMidiMapperProps, MidiMapping } from \"./MidiMapper\";\nexport { MidiMappingMode } from \"./MidiMapper\";\n\nexport type AnyModule = Module<ModuleType>;\nexport type IAnyModule = IModule<ModuleType>;\n\nexport type ICreateModule<T extends ModuleType> = {\n id?: string;\n name: string;\n moduleType: T;\n props: Partial<ModuleTypeToPropsMapping[T]>;\n};\n\nexport type ModuleParams = {\n [K in ModuleType]: K extends\n | ModuleType.Oscillator\n | ModuleType.Gain\n | ModuleType.Envelope\n | ModuleType.Filter\n | ModuleType.StereoPanner\n | ModuleType.VoiceScheduler\n ? IPolyModuleConstructor<K>\n : ICreateModule<K>;\n}[ModuleType];\n\nexport function createModule(\n engineId: string,\n params: ModuleParams,\n): ModuleTypeToModuleMapping[keyof ModuleTypeToModuleMapping] {\n switch (params.moduleType) {\n case ModuleType.Oscillator:\n return new Oscillator(engineId, params);\n case ModuleType.Gain:\n return new Gain(engineId, params);\n case ModuleType.Master:\n return new Master(engineId, params);\n case ModuleType.MidiSelector:\n return new MidiSelector(engineId, params);\n case ModuleType.Envelope:\n return new Envelope(engineId, params);\n case ModuleType.Filter:\n return new Filter(engineId, params);\n case ModuleType.Scale:\n return new Scale(engineId, params);\n case ModuleType.StereoPanner:\n return new StereoPanner(engineId, params);\n case ModuleType.Inspector:\n return new Inspector(engineId, params);\n case ModuleType.Constant:\n return new Constant(engineId, params);\n case ModuleType.MidiMapper:\n return new MidiMapper(engineId, params);\n case ModuleType.VirtualMidi:\n return new VirtualMidi(engineId, params);\n case ModuleType.StepSequencer:\n return new StepSequencer(engineId, params);\n case ModuleType.VoiceScheduler:\n return new VoiceScheduler(engineId, params);\n default:\n assertNever(params);\n }\n}\n","import { ContextTime } from \"@blibliki/transport\";\nimport { EmptyObject } from \"@blibliki/utils\";\nimport { ICreateModule, ModuleType } from \"@/modules\";\nimport { MidiOutput } from \"../IO\";\nimport MidiEvent, { MidiEventType } from \"../midi/MidiEvent\";\nimport { ModulePropSchema } from \"../schema\";\nimport { IModuleConstructor, Module } from \"./Module\";\nimport { IPolyModuleConstructor, PolyModule } from \"./PolyModule\";\n\nexport type IVoiceSchedulerProps = EmptyObject;\nexport const voiceSchedulerPropSchema: ModulePropSchema<IVoiceSchedulerProps> =\n {};\nconst DEFAULT_PROPS = {};\n\nclass Voice extends Module<ModuleType.VoiceScheduler> {\n declare audioNode: undefined;\n activeNote: string | null = null;\n triggeredAt: ContextTime = 0;\n\n constructor(\n engineId: string,\n params: ICreateModule<ModuleType.VoiceScheduler>,\n ) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n\n super(engineId, {\n ...params,\n props,\n });\n }\n\n midiTriggered = (midiEvent: MidiEvent) => {\n const { triggeredAt, note, type } = midiEvent;\n\n if (!note) return;\n const noteName = note.fullName;\n\n switch (type) {\n case MidiEventType.noteOn:\n this.activeNote = noteName;\n this.triggeredAt = triggeredAt;\n\n break;\n case MidiEventType.noteOff:\n this.activeNote = null;\n break;\n default:\n throw Error(\"This type is not a note\");\n }\n };\n}\n\nexport default class VoiceScheduler extends PolyModule<ModuleType.VoiceScheduler> {\n declare audioModules: Voice[];\n midiOutput!: MidiOutput;\n\n constructor(\n engineId: string,\n params: IPolyModuleConstructor<ModuleType.VoiceScheduler>,\n ) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const monoModuleConstructor = (\n engineId: string,\n params: IModuleConstructor<ModuleType.VoiceScheduler>,\n ) => new Voice(engineId, params);\n\n super(engineId, {\n ...params,\n props,\n monoModuleConstructor,\n });\n\n this.registerInputs();\n this.registerOutputs();\n }\n\n onMidiEvent = (midiEvent: MidiEvent) => {\n let voice: Voice | undefined;\n\n switch (midiEvent.type) {\n case MidiEventType.noteOn:\n voice = this.findFreeVoice();\n\n break;\n case MidiEventType.noteOff:\n voice = this.audioModules.find(\n (v) => v.activeNote === midiEvent.note!.fullName,\n );\n break;\n default:\n throw Error(\"This type is not a note\");\n }\n\n if (!voice) return;\n\n voice.midiTriggered(midiEvent);\n midiEvent.voiceNo = voice.voiceNo;\n this.midiOutput.onMidiEvent(midiEvent);\n };\n\n private findFreeVoice(): Voice {\n let voice = this.audioModules.find((v) => !v.activeNote);\n\n // If no available voice, get the one with the lowest triggeredAt\n voice ??= this.audioModules.sort((a, b) => {\n return a.triggeredAt - b.triggeredAt;\n })[0];\n\n return voice;\n }\n\n private registerInputs() {\n this.registerMidiInput({\n name: \"midi in\",\n onMidiEvent: this.onMidiEvent,\n });\n }\n\n private registerOutputs() {\n this.midiOutput = this.registerMidiOutput({ name: \"midi out\" });\n }\n}\n","import { ContextTime } from \"@blibliki/transport\";\nimport { Context } from \"@blibliki/utils\";\nimport { IModule, Module, ModulePropSchema, SetterHooks } from \"@/core\";\nimport Note from \"@/core/Note\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IConstant = IModule<ModuleType.Constant>;\nexport type IConstantProps = {\n value: number;\n};\n\nexport const constantPropSchema: ModulePropSchema<IConstantProps> = {\n value: {\n kind: \"number\",\n min: -Infinity,\n max: Infinity,\n step: 0.01,\n label: \"Value\",\n },\n};\n\nconst DEFAULT_PROPS: IConstantProps = { value: 1 };\n\nexport default class Constant\n extends Module<ModuleType.Constant>\n implements Pick<SetterHooks<IConstantProps>, \"onAfterSetValue\">\n{\n declare audioNode: ConstantSourceNode;\n isStated = false;\n\n constructor(engineId: string, params: ICreateModule<ModuleType.Constant>) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const audioNodeConstructor = (context: Context) =>\n new ConstantSourceNode(context.audioContext);\n\n super(engineId, {\n ...params,\n props,\n audioNodeConstructor,\n });\n\n this.registerDefaultIOs(\"out\");\n }\n\n onAfterSetValue: SetterHooks<IConstantProps>[\"onAfterSetValue\"] = (value) => {\n this.audioNode.offset.value = value;\n };\n\n start(time: ContextTime) {\n if (this.isStated) return;\n\n this.isStated = true;\n this.audioNode.start(time);\n }\n\n stop(time: ContextTime) {\n if (!this.isStated) return;\n\n this.audioNode.stop(time);\n this.rePlugAll(() => {\n this.audioNode = new ConstantSourceNode(this.context.audioContext, {\n offset: this.props.value,\n });\n });\n\n this.isStated = false;\n }\n\n triggerAttack = (note: Note, triggeredAt: ContextTime) => {\n this.audioNode.offset.setValueAtTime(note.frequency, triggeredAt);\n this.start(triggeredAt);\n };\n\n triggerRelease = () => {\n // Do nothing\n };\n}\n","import { ContextTime } from \"@blibliki/transport\";\nimport { Context, cancelAndHoldAtTime } from \"@blibliki/utils\";\nimport { Module } from \"@/core\";\nimport Note from \"@/core/Note\";\nimport { IModuleConstructor } from \"@/core/module/Module\";\nimport { IPolyModuleConstructor, PolyModule } from \"@/core/module/PolyModule\";\nimport { ModulePropSchema } from \"@/core/schema\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IEnvelopeProps = {\n attack: number;\n decay: number;\n sustain: number;\n release: number;\n};\n\nconst DEFAULT_PROPS: IEnvelopeProps = {\n attack: 0.01,\n decay: 0,\n sustain: 1,\n release: 0,\n};\n\nexport const envelopePropSchema: ModulePropSchema<IEnvelopeProps> = {\n attack: {\n kind: \"number\",\n min: 0.0001,\n max: 20,\n step: 0.01,\n exp: 3,\n label: \"Attack\",\n },\n decay: {\n kind: \"number\",\n min: 0,\n max: 20,\n step: 0.01,\n exp: 3,\n label: \"Decay\",\n },\n sustain: {\n kind: \"number\",\n min: 0,\n max: 1,\n step: 0.01,\n label: \"Sustain\",\n },\n release: {\n kind: \"number\",\n min: 0,\n max: 20,\n step: 0.01,\n exp: 3,\n label: \"Release\",\n },\n};\n\nclass MonoEnvelope extends Module<ModuleType.Envelope> {\n declare audioNode: GainNode;\n\n constructor(engineId: string, params: ICreateModule<ModuleType.Envelope>) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const audioNodeConstructor = (context: Context) => {\n const audioNode = new GainNode(context.audioContext);\n audioNode.gain.value = 0;\n return audioNode;\n };\n\n super(engineId, {\n ...params,\n props,\n audioNodeConstructor,\n });\n\n this.registerDefaultIOs();\n }\n\n triggerAttack(note: Note, triggeredAt: ContextTime) {\n super.triggerAttack(note, triggeredAt);\n\n const attack = this.props.attack;\n const decay = this.props.decay;\n const sustain = this.props.sustain;\n\n cancelAndHoldAtTime(this.audioNode.gain, triggeredAt);\n\n // Always start from a tiny value, can't ramp from 0\n if (this.audioNode.gain.value === 0) {\n this.audioNode.gain.setValueAtTime(0.001, triggeredAt);\n }\n\n // Attack\n this.audioNode.gain.exponentialRampToValueAtTime(1.0, triggeredAt + attack);\n\n // Decay\n if (sustain > 0) {\n this.audioNode.gain.exponentialRampToValueAtTime(\n sustain,\n triggeredAt + attack + decay,\n );\n // Do not set to zero or anything else!\n } else {\n this.audioNode.gain.exponentialRampToValueAtTime(\n 0.001,\n triggeredAt + attack + decay,\n );\n }\n }\n\n triggerRelease(note: Note, triggeredAt: ContextTime) {\n super.triggerRelease(note, triggeredAt);\n if (this.activeNotes.length > 0) return;\n\n const release = this.props.release;\n\n // Cancel scheduled automations and set gain to the ACTUAL value at this moment\n const currentGainValue = cancelAndHoldAtTime(\n this.audioNode.gain,\n triggeredAt,\n );\n\n if (currentGainValue >= 0.0001) {\n // Always set the value at the release time to ensure a smooth ramp from here\n this.audioNode.gain.setValueAtTime(currentGainValue, triggeredAt);\n // Exponential ramp to a tiny value\n this.audioNode.gain.exponentialRampToValueAtTime(\n 0.0001,\n triggeredAt + release - 0.0001,\n );\n }\n\n // Set to zero at the very end\n this.audioNode.gain.setValueAtTime(0, triggeredAt + release);\n }\n}\n\nexport default class Envelope extends PolyModule<ModuleType.Envelope> {\n constructor(\n engineId: string,\n params: IPolyModuleConstructor<ModuleType.Envelope>,\n ) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const monoModuleConstructor = (\n engineId: string,\n params: IModuleConstructor<ModuleType.Envelope>,\n ) => new MonoEnvelope(engineId, params);\n\n super(engineId, {\n ...params,\n props,\n monoModuleConstructor,\n });\n\n this.registerDefaultIOs();\n }\n}\n","import { Context } from \"@blibliki/utils\";\nimport { IModule, Module, ModulePropSchema, SetterHooks } from \"@/core\";\nimport { IModuleConstructor } from \"@/core/module/Module\";\nimport { IPolyModuleConstructor, PolyModule } from \"@/core/module/PolyModule\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IGain = IModule<ModuleType.Gain>;\nexport type IGainProps = {\n gain: number;\n};\n\nexport const gainPropSchema: ModulePropSchema<IGainProps> = {\n gain: {\n kind: \"number\",\n min: 0,\n max: Infinity,\n step: 0.01,\n label: \"Gain\",\n },\n};\n\nconst DEFAULT_PROPS: IGainProps = { gain: 1 };\n\nexport class MonoGain\n extends Module<ModuleType.Gain>\n implements Pick<SetterHooks<IGainProps>, \"onAfterSetGain\">\n{\n declare audioNode: GainNode;\n\n constructor(engineId: string, params: ICreateModule<ModuleType.Gain>) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const audioNodeConstructor = (context: Context) =>\n new GainNode(context.audioContext);\n\n super(engineId, {\n ...params,\n audioNodeConstructor,\n props,\n });\n\n this.registerDefaultIOs();\n this.registerAdditionalInputs();\n }\n\n onAfterSetGain: SetterHooks<IGainProps>[\"onAfterSetGain\"] = (value) => {\n this.audioNode.gain.value = value;\n };\n\n private registerAdditionalInputs() {\n this.registerAudioInput({\n name: \"gain\",\n getAudioNode: () => this.audioNode.gain,\n });\n }\n}\n\nexport default class Gain extends PolyModule<ModuleType.Gain> {\n constructor(\n engineId: string,\n params: IPolyModuleConstructor<ModuleType.Gain>,\n ) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const monoModuleConstructor = (\n engineId: string,\n params: IModuleConstructor<ModuleType.Gain>,\n ) => new MonoGain(engineId, params);\n\n super(engineId, {\n ...params,\n props,\n monoModuleConstructor,\n });\n\n this.registerAdditionalInputs();\n this.registerDefaultIOs();\n }\n\n private registerAdditionalInputs() {\n this.registerAudioInput({ name: \"gain\" });\n }\n}\n","import { Context } from \"@blibliki/utils\";\nimport { EnumProp, ModulePropSchema } from \"@/core\";\nimport { IModuleConstructor, Module, SetterHooks } from \"@/core/module/Module\";\nimport { IPolyModuleConstructor, PolyModule } from \"@/core/module/PolyModule\";\nimport { createModule, ICreateModule, ModuleType } from \".\";\nimport { MonoGain } from \"./Gain\";\nimport Scale from \"./Scale\";\n\nexport type IFilterProps = {\n cutoff: number;\n envelopeAmount: number;\n type: BiquadFilterType;\n Q: number;\n};\n\nconst MIN_FREQ = 20;\nconst MAX_FREQ = 20000;\n\nconst DEFAULT_PROPS: IFilterProps = {\n cutoff: MAX_FREQ,\n envelopeAmount: 0,\n type: \"lowpass\",\n Q: 1,\n};\n\nexport const filterPropSchema: ModulePropSchema<\n IFilterProps,\n {\n type: EnumProp<BiquadFilterType>;\n }\n> = {\n cutoff: {\n kind: \"number\",\n min: MIN_FREQ,\n max: MAX_FREQ,\n step: 1,\n exp: 5,\n label: \"Cutoff\",\n },\n envelopeAmount: {\n kind: \"number\",\n min: -1,\n max: 1,\n step: 0.01,\n label: \"Envelope Amount\",\n },\n type: {\n kind: \"enum\",\n options: [\"lowpass\", \"highpass\", \"bandpass\"] satisfies BiquadFilterType[],\n label: \"Type\",\n },\n Q: {\n kind: \"number\",\n min: 0.0001,\n max: 1000,\n step: 0.1,\n exp: 5,\n label: \"Q\",\n },\n};\n\nclass MonoFilter\n extends Module<ModuleType.Filter>\n implements\n Pick<\n SetterHooks<IFilterProps>,\n | \"onAfterSetType\"\n | \"onAfterSetCutoff\"\n | \"onAfterSetQ\"\n | \"onAfterSetEnvelopeAmount\"\n >\n{\n declare audioNode: BiquadFilterNode;\n private scale: Scale;\n private amount: MonoGain;\n\n constructor(engineId: string, params: ICreateModule<ModuleType.Filter>) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n\n const audioNodeConstructor = (context: Context) =>\n new BiquadFilterNode(context.audioContext, {\n type: props.type,\n frequency: 0,\n Q: props.Q,\n });\n\n super(engineId, {\n ...params,\n props,\n audioNodeConstructor,\n });\n\n this.amount = new MonoGain(engineId, {\n name: \"amount\",\n moduleType: ModuleType.Gain,\n props: { gain: props.envelopeAmount },\n });\n\n this.scale = createModule(engineId, {\n name: \"scale\",\n moduleType: ModuleType.Scale,\n props: { min: MIN_FREQ, max: MAX_FREQ, current: this.props.cutoff },\n }) as Scale;\n\n this.amount.plug({ audioModule: this.scale, from: \"out\", to: \"in\" });\n this.scale.audioNode.connect(this.audioNode.frequency);\n\n this.registerDefaultIOs();\n this.registerInputs();\n }\n\n onAfterSetType: SetterHooks<IFilterProps>[\"onAfterSetType\"] = (value) => {\n this.audioNode.type = value;\n };\n\n onAfterSetCutoff: SetterHooks<IFilterProps>[\"onAfterSetCutoff\"] = (value) => {\n this.scale.props = { current: value };\n };\n\n onAfterSetQ: SetterHooks<IFilterProps>[\"onAfterSetQ\"] = (value) => {\n this.audioNode.Q.value = value;\n };\n\n onAfterSetEnvelopeAmount: SetterHooks<IFilterProps>[\"onAfterSetEnvelopeAmount\"] =\n (value) => {\n this.amount.props = { gain: value };\n };\n\n private registerInputs() {\n this.registerAudioInput({\n name: \"cutoff\",\n getAudioNode: () => this.audioNode.frequency,\n });\n\n this.registerAudioInput({\n name: \"cutoffMod\",\n getAudioNode: () => this.amount.audioNode,\n });\n\n this.registerAudioInput({\n name: \"Q\",\n getAudioNode: () => this.audioNode.Q,\n });\n }\n}\n\nexport default class Filter extends PolyModule<ModuleType.Filter> {\n constructor(\n engineId: string,\n params: IPolyModuleConstructor<ModuleType.Filter>,\n ) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const monoModuleConstructor = (\n engineId: string,\n params: IModuleConstructor<ModuleType.Filter>,\n ) => new MonoFilter(engineId, params);\n\n super(engineId, {\n ...params,\n props,\n monoModuleConstructor,\n });\n\n this.registerInputs();\n this.registerDefaultIOs();\n }\n\n private registerInputs() {\n this.registerAudioInput({ name: \"cutoff\" });\n this.registerAudioInput({ name: \"cutoffMod\" });\n this.registerAudioInput({ name: \"Q\" });\n }\n}\n","import { Context } from \"@blibliki/utils\";\nimport { IModule, Module, SetterHooks } from \"@/core\";\nimport { EnumProp, ModulePropSchema } from \"@/core/schema\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IInspector = IModule<ModuleType.Inspector>;\nexport type IInspectorProps = {\n fftSize: number;\n};\n\nexport const inspectorPropSchema: ModulePropSchema<\n IInspectorProps,\n {\n fftSize: EnumProp<number>;\n }\n> = {\n fftSize: {\n kind: \"enum\",\n options: [32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768],\n label: \"FFT size\",\n },\n};\n\nconst DEFAULT_PROPS: IInspectorProps = { fftSize: 512 };\n\nexport default class Inspector\n extends Module<ModuleType.Inspector>\n implements Pick<SetterHooks<IInspectorProps>, \"onAfterSetFftSize\">\n{\n declare audioNode: AnalyserNode;\n private _buffer?: Float32Array<ArrayBuffer>;\n\n constructor(engineId: string, params: ICreateModule<ModuleType.Inspector>) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const audioNodeConstructor = (context: Context) =>\n new AnalyserNode(context.audioContext);\n\n super(engineId, {\n ...params,\n props,\n audioNodeConstructor,\n });\n\n this.registerDefaultIOs(\"in\");\n }\n\n onAfterSetFftSize: SetterHooks<IInspectorProps>[\"onAfterSetFftSize\"] = (\n value,\n ) => {\n this._buffer = new Float32Array(value);\n };\n\n get buffer() {\n if (this._buffer) return this._buffer;\n\n this._buffer = new Float32Array(this.props.fftSize);\n\n return this._buffer;\n }\n\n getValue(): number {\n return this.getValues()[0];\n }\n\n getValues(): Float32Array {\n this.audioNode.getFloatTimeDomainData(this.buffer);\n\n return this.buffer;\n }\n}\n","import { Context, EmptyObject } from \"@blibliki/utils\";\nimport { IModule, Module, ModulePropSchema } from \"@/core\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IMaster = IModule<ModuleType.Master>;\nexport type IMasterProps = EmptyObject;\n\nconst DEFAULT_PROPS: IMasterProps = {};\n\nexport const masterPropSchema: ModulePropSchema<IMasterProps> = {};\n\nexport default class Master extends Module<ModuleType.Master> {\n declare audioNode: AudioDestinationNode;\n\n constructor(engineId: string, params: ICreateModule<ModuleType.Master>) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const audioNodeConstructor = (context: Context) => context.destination;\n\n super(engineId, { ...params, audioNodeConstructor, props });\n\n this.registerDefaultIOs(\"in\");\n }\n}\n","import { ContextTime } from \"@blibliki/transport\";\nimport { IModule, MidiEvent, Module, SetterHooks } from \"@/core\";\nimport { ModulePropSchema, NumberProp, PropSchema } from \"@/core/schema\";\nimport { ICreateModule, moduleSchemas, ModuleType } from \".\";\n\nexport type IMidiMapper = IModule<ModuleType.MidiMapper>;\nexport type IMidiMapperProps = {\n pages: MidiMappingPage[];\n activePage: number;\n globalMappings: MidiMapping<ModuleType>[];\n};\n\nexport type MidiMappingPage = {\n name?: string;\n mappings: MidiMapping<ModuleType>[];\n};\n\nexport enum MidiMappingMode {\n direct = \"direct\",\n directRev = \"directRev\",\n toggleInc = \"toggleInc\",\n toggleDec = \"toggleDec\",\n incDec = \"incDec\",\n incDecRev = \"incDecRev\",\n}\n\nexport type MidiMapping<T extends ModuleType> = {\n cc?: number;\n moduleId?: string;\n moduleType?: T;\n propName?: string;\n autoAssign?: boolean;\n mode?: MidiMappingMode;\n threshold?: number; // For incDec mode (default: 64)\n step?: number;\n};\n\nexport const midiMapperPropSchema: ModulePropSchema<IMidiMapperProps> = {\n pages: {\n kind: \"array\",\n label: \"Midi mapping pages\",\n },\n activePage: {\n kind: \"number\",\n label: \"Active page\",\n min: 0,\n max: 100,\n step: 1,\n },\n globalMappings: {\n kind: \"array\",\n label: \"Global midi mappings\",\n },\n};\n\nconst DEFAULT_PROPS: IMidiMapperProps = {\n pages: [{ name: \"Page 1\", mappings: [{}] }],\n activePage: 0,\n globalMappings: [{}],\n};\n\nfunction getMidiFromMappedValue({\n value,\n midiValue,\n propSchema,\n mapping,\n}: {\n value: number;\n propSchema: NumberProp;\n midiValue: number;\n mapping: MidiMapping<ModuleType>;\n}): number {\n const min = propSchema.min ?? 0;\n const max = propSchema.max ?? 1;\n const exp = propSchema.exp ?? 1;\n\n const { threshold = 64, mode } = mapping;\n\n // Reverse the range mapping: get curvedValue\n const curvedValue = (value - min) / (max - min);\n\n // Reverse the exponential curve: get normalizedMidi\n const normalizedMidi = Math.pow(curvedValue, 1 / exp);\n\n // Reverse the MIDI normalization: get midiValue\n let newMidiValue = normalizedMidi * 127;\n newMidiValue =\n (midiValue >= threshold && mode === MidiMappingMode.incDec) ||\n (midiValue <= threshold && mode === MidiMappingMode.incDecRev)\n ? newMidiValue + 1\n : newMidiValue - 1;\n return Math.round(Math.max(0, Math.min(127, newMidiValue))); // Valid MIDI range\n}\n\ntype MidiMapperSetterHooks = Pick<\n SetterHooks<IMidiMapperProps>,\n \"onSetActivePage\"\n>;\n\nexport default class MidiMapper\n extends Module<ModuleType.MidiMapper>\n implements MidiMapperSetterHooks\n{\n declare audioNode: undefined;\n\n constructor(engineId: string, params: ICreateModule<ModuleType.MidiMapper>) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n\n super(engineId, {\n ...params,\n props,\n });\n\n this.registerMidiInput({\n name: \"midi in\",\n onMidiEvent: this.onMidiEvent,\n });\n }\n\n onSetActivePage: MidiMapperSetterHooks[\"onSetActivePage\"] = (value) => {\n return Math.max(Math.min(value, this.props.pages.length - 1), 0);\n };\n\n handleCC = (event: MidiEvent, triggeredAt: ContextTime) => {\n this.checkAutoAssign(event);\n\n const activePage = this.props.pages[this.props.activePage];\n\n [\n ...this.props.globalMappings.filter((m) => m.cc === event.cc),\n ...activePage.mappings.filter((m) => m.cc === event.cc),\n ].forEach((mapping) => {\n this.forwardMapping(event, mapping, triggeredAt);\n });\n };\n\n forwardMapping = (\n event: MidiEvent,\n mapping: MidiMapping<ModuleType>,\n _triggeredAt: ContextTime,\n ) => {\n if (\n mapping.moduleId === undefined ||\n mapping.moduleType === undefined ||\n mapping.propName === undefined\n )\n return;\n\n const propName = mapping.propName;\n let midiValue = event.ccValue;\n if (midiValue === undefined) return;\n\n const mode = mapping.mode ?? \"direct\";\n\n // Toggle mode: only respond to 127 (button press), ignore 0\n if (\n (mode === MidiMappingMode.toggleInc ||\n mode === MidiMappingMode.toggleDec) &&\n midiValue !== 127\n ) {\n return;\n }\n\n const mappedModule = this.engine.findModule(mapping.moduleId);\n // @ts-expect-error TS7053 ignore this error\n const propSchema = moduleSchemas[mappedModule.moduleType][\n propName\n ] as PropSchema;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let mappedValue: any;\n\n // Direct mode (default) or Toggle mode: map value directly\n switch (propSchema.kind) {\n case \"number\": {\n // @ts-expect-error TS7053 ignore this error\n const currentValue = mappedModule.props[propName] as number;\n\n if (\n mode === MidiMappingMode.incDec ||\n mode === MidiMappingMode.incDecRev\n ) {\n midiValue = getMidiFromMappedValue({\n value: currentValue,\n propSchema,\n mapping,\n midiValue,\n });\n } else if (mode === MidiMappingMode.directRev) {\n midiValue = 127 - midiValue;\n }\n\n if (mode === MidiMappingMode.toggleInc) {\n mappedValue = currentValue + (propSchema.step ?? 1);\n } else if (mode === MidiMappingMode.toggleDec) {\n mappedValue = currentValue - (propSchema.step ?? 1);\n } else {\n const min = propSchema.min ?? 0;\n const max = propSchema.max ?? 1;\n const normalizedMidi = midiValue / 127;\n const curvedValue = Math.pow(normalizedMidi, propSchema.exp ?? 1);\n mappedValue = min + curvedValue * (max - min);\n\n // Round to step if defined\n if (\n propSchema.step !== undefined &&\n (!propSchema.exp || propSchema.exp === 1)\n ) {\n const steps = Math.round((mappedValue - min) / propSchema.step);\n mappedValue = min + steps * propSchema.step;\n }\n }\n\n break;\n }\n case \"enum\": {\n const optionIndex = Math.floor(\n (midiValue / 127) * propSchema.options.length,\n );\n const clampedIndex = Math.min(\n optionIndex,\n propSchema.options.length - 1,\n );\n mappedValue = propSchema.options[clampedIndex];\n break;\n }\n case \"boolean\":\n mappedValue = midiValue >= 64;\n break;\n case \"string\":\n throw Error(\"MidiMapper not support string type of values\");\n case \"array\":\n throw Error(\"MidiMapper not support array type of values\");\n\n default:\n throw Error(\"MidiMapper unknown type\");\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n mappedModule.props = { [propName]: mappedValue };\n mappedModule.triggerPropsUpdate();\n };\n\n private checkAutoAssign(event: MidiEvent) {\n if (event.cc === undefined) return;\n\n const activePage = this.props.pages[this.props.activePage];\n const hasGlobalAutoAssign = this.props.globalMappings.some(\n ({ autoAssign }) => autoAssign,\n );\n const hasPageAutoAssign = activePage.mappings.some(\n ({ autoAssign }) => autoAssign,\n );\n\n if (!hasGlobalAutoAssign && !hasPageAutoAssign) return;\n\n // Update global mappings if needed\n const updatedGlobalMappings = hasGlobalAutoAssign\n ? this.props.globalMappings.map((mapping) => {\n if (!mapping.autoAssign) return mapping;\n\n return {\n ...mapping,\n cc: event.cc,\n autoAssign: false,\n };\n })\n : this.props.globalMappings;\n\n // Update page mappings if needed\n const updatedPageMappings = hasPageAutoAssign\n ? activePage.mappings.map((mapping) => {\n if (!mapping.autoAssign) return mapping;\n\n return {\n ...mapping,\n cc: event.cc,\n autoAssign: false,\n };\n })\n : activePage.mappings;\n\n const updatedPages = this.props.pages.map((page, index) =>\n index === this.props.activePage\n ? { ...page, mappings: updatedPageMappings }\n : page,\n );\n\n this.props = { pages: updatedPages, globalMappings: updatedGlobalMappings };\n this.triggerPropsUpdate();\n }\n}\n","import { IModule, Module, MidiOutput, SetterHooks, MidiDevice } from \"@/core\";\nimport ComputerKeyboardInput from \"@/core/midi/ComputerKeyboardDevice\";\nimport MidiEvent from \"@/core/midi/MidiEvent\";\nimport { ModulePropSchema } from \"@/core/schema\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IMidiSelector = IModule<ModuleType.MidiSelector>;\nexport type IMidiSelectorProps = {\n selectedId: string | undefined | null;\n selectedName: string | undefined | null;\n};\n\nexport const midiSelectorPropSchema: ModulePropSchema<IMidiSelectorProps> = {\n selectedId: {\n kind: \"string\",\n label: \"Midi device ID\",\n },\n selectedName: {\n kind: \"string\",\n label: \"Midi device name\",\n },\n};\n\nconst DEFAULT_PROPS: IMidiSelectorProps = {\n selectedId: undefined,\n selectedName: undefined,\n};\n\nexport default class MidiSelector\n extends Module<ModuleType.MidiSelector>\n implements Pick<SetterHooks<IMidiSelectorProps>, \"onSetSelectedId\">\n{\n declare audioNode: undefined;\n midiOutput!: MidiOutput;\n _forwardMidiEvent?: (midiEvent: MidiEvent) => void;\n\n constructor(\n engineId: string,\n params: ICreateModule<ModuleType.MidiSelector>,\n ) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n\n super(engineId, {\n ...params,\n props,\n });\n\n const midiDevice =\n (this.props.selectedId &&\n this.engine.findMidiDevice(this.props.selectedId)) ??\n (this.props.selectedName &&\n this.engine.findMidiDeviceByName(this.props.selectedName));\n\n if (midiDevice) {\n this.addEventListener(midiDevice);\n }\n\n this.registerOutputs();\n }\n\n onSetSelectedId: SetterHooks<IMidiSelectorProps>[\"onSetSelectedId\"] = (\n value,\n ) => {\n this.removeEventListener();\n if (!value) return value;\n\n const midiDevice = this.engine.findMidiDevice(value);\n if (!midiDevice) return value;\n\n this.props = { selectedName: midiDevice.name };\n this.addEventListener(midiDevice);\n\n return value;\n };\n\n private get forwardMidiEvent() {\n if (this._forwardMidiEvent) return this._forwardMidiEvent;\n\n this._forwardMidiEvent = (midiEvent: MidiEvent) => {\n this.midiOutput.onMidiEvent(midiEvent);\n };\n\n return this._forwardMidiEvent;\n }\n\n private addEventListener(midiDevice: MidiDevice | ComputerKeyboardInput) {\n midiDevice.addEventListener(this.forwardMidiEvent);\n }\n\n private removeEventListener() {\n if (!this.props.selectedId) return;\n\n const midiDevice = this.engine.findMidiDevice(this.props.selectedId);\n midiDevice?.removeEventListener(this.forwardMidiEvent);\n }\n\n private registerOutputs() {\n this.midiOutput = this.registerMidiOutput({ name: \"midi out\" });\n }\n}\n","import { ContextTime } from \"@blibliki/transport\";\nimport { Context, dbToGain } from \"@blibliki/utils\";\nimport { IModule, Module } from \"@/core\";\nimport Note from \"@/core/Note\";\nimport { IModuleConstructor, SetterHooks } from \"@/core/module/Module\";\nimport { IPolyModuleConstructor, PolyModule } from \"@/core/module/PolyModule\";\nimport { EnumProp, ModulePropSchema } from \"@/core/schema\";\nimport { ICreateModule, ModuleType } from \".\";\n\nconst LOW_GAIN = -18;\n\nexport type IOscillator = IModule<ModuleType.Oscillator>;\n\nexport enum OscillatorWave {\n sine = \"sine\",\n triangle = \"triangle\",\n square = \"square\",\n sawtooth = \"sawtooth\",\n}\n\n/**\n * Props for the Oscillator module.\n *\n * @property wave - Waveform shape of the oscillator.\n * One of: \"sine\", \"square\", \"sawtooth\", \"triangle\", or \"custom\".\n * @property frequency - Base frequency in Hz (e.g. 440 for A4).\n * @property fine - Fine tuning factor in the range [-1, 1], where ±1 represents ±1 semitone.\n * @property coarse - Coarse tuning factor in the range [-1, 1], scaled to ±12 semitones.\n * @property octave - Octave transposition value (e.g. +1 for one octave up, -2 for two octaves down).\n * @property lowGain - Whether to gain reduction (-18dB). When false, oscillator runs at full gain.\n */\nexport type IOscillatorProps = {\n wave: OscillatorWave;\n frequency: number;\n fine: number;\n coarse: number;\n octave: number;\n lowGain: boolean;\n};\n\nexport const oscillatorPropSchema: ModulePropSchema<\n IOscillatorProps,\n {\n wave: EnumProp<OscillatorWave>;\n }\n> = {\n wave: {\n kind: \"enum\",\n options: Object.values(OscillatorWave),\n label: \"Waveform\",\n },\n frequency: {\n kind: \"number\",\n min: 0,\n max: 25000,\n step: 1,\n label: \"Frequency\",\n },\n fine: {\n kind: \"number\",\n min: -1,\n max: 1,\n step: 0.01,\n label: \"Fine\",\n },\n coarse: {\n kind: \"number\",\n min: -12,\n max: 12,\n step: 1,\n label: \"Coarse\",\n },\n octave: {\n kind: \"number\",\n min: -1,\n max: 2,\n step: 1,\n label: \"Octave\",\n },\n lowGain: {\n kind: \"boolean\",\n label: `Use ${LOW_GAIN}db Gain`,\n },\n};\n\nconst DEFAULT_PROPS: IOscillatorProps = {\n wave: OscillatorWave.sine,\n frequency: 440,\n fine: 0,\n coarse: 0,\n octave: 0,\n lowGain: false,\n};\n\ntype OscillatorSetterHooks = Pick<\n SetterHooks<IOscillatorProps>,\n | \"onAfterSetWave\"\n | \"onAfterSetFrequency\"\n | \"onAfterSetFine\"\n | \"onAfterSetCoarse\"\n | \"onAfterSetOctave\"\n | \"onAfterSetLowGain\"\n>;\n\nexport class MonoOscillator\n extends Module<ModuleType.Oscillator>\n implements OscillatorSetterHooks\n{\n declare audioNode: OscillatorNode;\n isStated = false;\n outputGain: GainNode;\n detuneGain!: GainNode;\n\n constructor(engineId: string, params: ICreateModule<ModuleType.Oscillator>) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const audioNodeConstructor = (context: Context) =>\n new OscillatorNode(context.audioContext);\n\n super(engineId, {\n ...params,\n props,\n audioNodeConstructor,\n });\n\n this.outputGain = new GainNode(this.context.audioContext, {\n gain: dbToGain(LOW_GAIN),\n });\n\n this.applyOutputGain();\n this.initializeGainDetune();\n this.registerInputs();\n this.registerOutputs();\n }\n\n onAfterSetWave: OscillatorSetterHooks[\"onAfterSetWave\"] = (value) => {\n this.audioNode.type = value;\n };\n\n onAfterSetFrequency: OscillatorSetterHooks[\"onAfterSetFrequency\"] = () => {\n this.updateFrequency();\n };\n\n onAfterSetFine: OscillatorSetterHooks[\"onAfterSetFine\"] = () => {\n this.updateFrequency();\n };\n\n onAfterSetCoarse: OscillatorSetterHooks[\"onAfterSetCoarse\"] = () => {\n this.updateFrequency();\n };\n\n onAfterSetOctave: OscillatorSetterHooks[\"onAfterSetOctave\"] = () => {\n this.updateFrequency();\n };\n\n onAfterSetLowGain: OscillatorSetterHooks[\"onAfterSetLowGain\"] = (lowGain) => {\n this.outputGain.gain.value = lowGain ? dbToGain(LOW_GAIN) : 1;\n };\n\n start(time: ContextTime) {\n if (this.isStated) return;\n\n this.isStated = true;\n this.audioNode.start(time);\n }\n\n stop(time: ContextTime) {\n if (!this.isStated) return;\n\n this.audioNode.stop(time);\n this.rePlugAll(() => {\n this.audioNode = new OscillatorNode(this.context.audioContext, {\n type: this.props.wave,\n frequency: this.finalFrequency,\n });\n this.applyOutputGain();\n this.detuneGain.connect(this.audioNode.detune);\n });\n\n this.isStated = false;\n }\n\n triggerAttack = (note: Note, triggeredAt: ContextTime) => {\n super.triggerAttack(note, triggeredAt);\n\n this.props = { frequency: note.frequency };\n this.updateFrequency(triggeredAt);\n this.start(triggeredAt);\n };\n\n triggerRelease(note: Note, triggeredAt: ContextTime) {\n super.triggerRelease(note, triggeredAt);\n\n const lastNote = this.activeNotes.length\n ? this.activeNotes[this.activeNotes.length - 1]\n : null;\n if (!lastNote) return;\n\n this.props = { frequency: lastNote.frequency };\n this.updateFrequency(triggeredAt);\n }\n\n private get finalFrequency(): number | undefined {\n const { frequency, coarse, octave, fine } = this.props;\n\n const transposed =\n frequency * Math.pow(2, coarse / 12 + octave + fine / 12);\n return transposed;\n }\n\n private updateFrequency(actionAt?: ContextTime) {\n if (this.finalFrequency === undefined) return;\n\n if (actionAt) {\n this.audioNode.frequency.setValueAtTime(this.finalFrequency, actionAt);\n } else {\n this.audioNode.frequency.value = this.finalFrequency;\n }\n }\n\n private applyOutputGain() {\n this.audioNode.connect(this.outputGain);\n }\n\n private initializeGainDetune() {\n this.detuneGain = new GainNode(this.context.audioContext, { gain: 100 });\n this.detuneGain.connect(this.audioNode.detune);\n }\n\n private registerInputs() {\n this.registerAudioInput({\n name: \"detune\",\n getAudioNode: () => this.detuneGain,\n });\n }\n\n private registerOutputs() {\n this.registerAudioOutput({\n name: \"out\",\n getAudioNode: () => this.outputGain,\n });\n }\n}\n\nexport default class Oscillator extends PolyModule<ModuleType.Oscillator> {\n constructor(\n engineId: string,\n params: IPolyModuleConstructor<ModuleType.Oscillator>,\n ) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const monoModuleConstructor = (\n engineId: string,\n params: IModuleConstructor<ModuleType.Oscillator>,\n ) => new MonoOscillator(engineId, params);\n\n super(engineId, {\n ...params,\n props,\n monoModuleConstructor,\n });\n\n this.registerInputs();\n this.registerDefaultIOs(\"out\");\n }\n\n start(time: ContextTime) {\n this.audioModules.forEach((audioModule) => {\n audioModule.start(time);\n });\n }\n\n stop(time: ContextTime) {\n this.audioModules.forEach((audioModule) => {\n audioModule.stop(time);\n });\n }\n\n private registerInputs() {\n this.registerAudioInput({ name: \"detune\" });\n }\n}\n","import { assertNever, Context } from \"@blibliki/utils\";\nimport { filterProcessorURL } from \"./filter-processor\";\nimport { scaleProcessorURL } from \"./scale-processor\";\n\nexport enum CustomWorklet {\n ScaleProcessor = \"ScaleProcessor\",\n FilterProcessor = \"FilterProcessor\",\n}\n\nexport async function loadProcessors(context: Context) {\n await context.addModule(scaleProcessorURL);\n await context.addModule(filterProcessorURL);\n}\n\nexport function newAudioWorklet(context: Context, worklet: CustomWorklet) {\n switch (worklet) {\n case CustomWorklet.ScaleProcessor:\n return context.newAudioWorklet(\"scale-processor\");\n case CustomWorklet.FilterProcessor:\n return context.newAudioWorklet(\"filter-processor\");\n default:\n assertNever(worklet);\n }\n}\n","export const filterProcessorURL = URL.createObjectURL(\n new Blob(\n [\n \"(\",\n (() => {\n class FilterProcessor extends AudioWorkletProcessor {\n s0: number;\n s1: number;\n\n constructor() {\n super();\n this.s0 = 0;\n this.s1 = 0;\n }\n\n static get parameterDescriptors() {\n return [\n {\n name: \"cutoff\",\n defaultValue: 1000,\n minValue: 20,\n maxValue: 20000,\n },\n {\n name: \"resonance\",\n defaultValue: 0.0,\n minValue: 0.0,\n maxValue: 4.0,\n },\n ];\n }\n\n process(\n inputs: Float32Array[][],\n outputs: Float32Array[][],\n parameters: Record<string, Float32Array>,\n ): boolean {\n const input = inputs[0];\n const output = outputs[0];\n\n const cutoff = parameters.cutoff;\n const resonance = parameters.resonance;\n\n for (let channelNum = 0; channelNum < input.length; channelNum++) {\n const inputChannel = input[channelNum];\n const outputChannel = output[channelNum];\n\n for (let i = 0; i < inputChannel.length; i++) {\n const s = inputChannel[i];\n // Convert Hz to normalized frequency using logarithmic scale\n // This better matches human hearing perception\n const cutoffHz = cutoff.length > 1 ? cutoff[i] : cutoff[0];\n const clampedHz = Math.max(20, Math.min(20000, cutoffHz));\n const normalizedCutoff =\n Math.log(clampedHz / 20) / Math.log(20000 / 20);\n const c = Math.pow(0.5, (1 - normalizedCutoff) / 0.125);\n const r = Math.pow(\n 0.5,\n ((resonance.length > 1 ? resonance[i] : resonance[0]) +\n 0.125) /\n 0.125,\n );\n const mrc = 1 - r * c;\n\n this.s0 = mrc * this.s0 - c * this.s1 + c * s;\n this.s1 = mrc * this.s1 + c * this.s0;\n\n outputChannel[i] = this.s1;\n }\n }\n\n return true;\n }\n }\n\n registerProcessor(\"filter-processor\", FilterProcessor);\n }).toString(),\n \")()\",\n ],\n { type: \"application/javascript\" },\n ),\n);\n","export const scaleProcessorURL = URL.createObjectURL(\n new Blob(\n [\n \"(\",\n (() => {\n class ScaleProcessor extends AudioWorkletProcessor {\n static get parameterDescriptors() {\n return [\n {\n name: \"min\",\n defaultValue: 1e-10,\n },\n {\n name: \"max\",\n defaultValue: 1,\n },\n {\n name: \"current\",\n defaultValue: 0.5,\n },\n ];\n }\n\n process(\n inputs: Float32Array[][],\n outputs: Float32Array[][],\n parameters: Record<string, Float32Array>,\n ) {\n const input = inputs[0];\n const output = outputs[0];\n\n const minValues = parameters.min;\n const maxValues = parameters.max;\n const currentValues = parameters.current;\n\n if (!input.length || input[0].length === 0) {\n for (const outputChannel of output) {\n const current =\n parameters.current.length > 1\n ? parameters.current[0]\n : parameters.current[0];\n\n outputChannel.fill(current);\n }\n\n return true;\n }\n\n for (let channel = 0; channel < input.length; channel++) {\n const inputChannel = input[channel];\n const outputChannel = output[channel];\n\n for (let i = 0; i < inputChannel.length; i++) {\n const x = inputChannel[i];\n\n const min = minValues.length > 1 ? minValues[i] : minValues[0];\n const max = maxValues.length > 1 ? maxValues[i] : maxValues[0];\n const current =\n currentValues.length > 1\n ? currentValues[i]\n : currentValues[0];\n\n if (x < 0) {\n outputChannel[i] = current * Math.pow(min / current, -x);\n } else {\n outputChannel[i] = current * Math.pow(max / current, x);\n }\n }\n }\n\n return true;\n }\n }\n\n registerProcessor(\"scale-processor\", ScaleProcessor);\n }).toString(),\n \")()\",\n ],\n { type: \"application/javascript\" },\n ),\n);\n","import { Context } from \"@blibliki/utils\";\nimport { IModule, Module, SetterHooks } from \"@/core\";\nimport { ModulePropSchema } from \"@/core/schema\";\nimport { CustomWorklet, newAudioWorklet } from \"@/processors\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IScale = IModule<ModuleType.Scale>;\nexport type IScaleProps = {\n min: number;\n max: number;\n current: number;\n};\n\nexport const scalePropSchema: ModulePropSchema<IScaleProps> = {\n min: {\n kind: \"number\",\n min: -Infinity,\n max: Infinity,\n step: 0.01,\n label: \"Min\",\n },\n max: {\n kind: \"number\",\n min: -Infinity,\n max: Infinity,\n step: 0.01,\n label: \"Max\",\n },\n current: {\n kind: \"number\",\n min: -Infinity,\n max: Infinity,\n step: 0.01,\n label: \"Current\",\n },\n};\n\nconst DEFAULT_PROPS: IScaleProps = { min: 0, max: 1, current: 0.5 };\n\nexport default class Scale\n extends Module<ModuleType.Scale>\n implements\n Pick<\n SetterHooks<IScaleProps>,\n \"onAfterSetMin\" | \"onAfterSetMax\" | \"onAfterSetCurrent\"\n >\n{\n declare audioNode: AudioWorkletNode;\n\n constructor(engineId: string, params: ICreateModule<ModuleType.Scale>) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const audioNodeConstructor = (context: Context) =>\n newAudioWorklet(context, CustomWorklet.ScaleProcessor);\n\n super(engineId, {\n ...params,\n props,\n audioNodeConstructor,\n });\n\n this.registerDefaultIOs();\n }\n\n get current() {\n return this.audioNode.parameters.get(\"current\")!;\n }\n\n get min() {\n return this.audioNode.parameters.get(\"min\")!;\n }\n\n get max() {\n return this.audioNode.parameters.get(\"max\")!;\n }\n\n onAfterSetMin: SetterHooks<IScaleProps>[\"onAfterSetMin\"] = (value) => {\n this.min.value = value;\n };\n\n onAfterSetMax: SetterHooks<IScaleProps>[\"onAfterSetMax\"] = (value) => {\n this.max.value = value;\n };\n\n onAfterSetCurrent: SetterHooks<IScaleProps>[\"onAfterSetCurrent\"] = (\n value,\n ) => {\n this.current.value = value;\n };\n}\n","import { INote, Module, IModule, MidiOutput, ModulePropSchema } from \"@/core\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IStepSequencer = IModule<ModuleType.StepSequencer>;\n\nexport type ISequence = {\n active: boolean;\n // time: BarsBeatsSixteenths;\n duration: string;\n notes: INote[];\n};\n\nexport type IStepSequencerProps = {\n bars: number;\n steps: number;\n sequences: ISequence[][];\n};\n\nexport const stepSequencerPropSchema: ModulePropSchema<\n Omit<IStepSequencerProps, \"sequences\">\n> = {\n steps: {\n kind: \"number\",\n min: 1,\n max: 16,\n step: 1,\n label: \"Steps\",\n },\n bars: {\n kind: \"number\",\n min: 1,\n max: 16,\n step: 1,\n label: \"Steps\",\n },\n};\n\nconst DEFAULT_PROPS: IStepSequencerProps = {\n sequences: [],\n steps: 16,\n bars: 1,\n};\n\n// Not implemented yet, just the data modeling\nexport default class StepSequencer extends Module<ModuleType.StepSequencer> {\n declare audioNode: undefined;\n midiOutput!: MidiOutput;\n\n constructor(\n engineId: string,\n params: ICreateModule<ModuleType.StepSequencer>,\n ) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n\n super(engineId, {\n ...params,\n props,\n });\n }\n}\n","import { Context } from \"@blibliki/utils\";\nimport { IModule, Module, ModulePropSchema } from \"@/core\";\nimport { IModuleConstructor, SetterHooks } from \"@/core/module/Module\";\nimport { IPolyModuleConstructor, PolyModule } from \"@/core/module/PolyModule\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IStereoPanner = IModule<ModuleType.StereoPanner>;\nexport type IStereoPannerProps = {\n pan: number;\n};\n\nexport const stereoPannerPropSchema: ModulePropSchema<IStereoPannerProps> = {\n pan: {\n kind: \"number\",\n min: -1,\n max: 1,\n step: 0.01,\n label: \"Pan\",\n },\n};\n\nconst DEFAULT_PROPS: IStereoPannerProps = {\n pan: 0,\n};\n\nexport class MonoStereoPanner\n extends Module<ModuleType.StereoPanner>\n implements Pick<SetterHooks<IStereoPannerProps>, \"onAfterSetPan\">\n{\n declare audioNode: StereoPannerNode;\n\n constructor(\n engineId: string,\n params: ICreateModule<ModuleType.StereoPanner>,\n ) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const audioNodeConstructor = (context: Context) =>\n new StereoPannerNode(context.audioContext);\n\n super(engineId, {\n ...params,\n audioNodeConstructor,\n props,\n });\n\n this.registerDefaultIOs();\n this.registerAdditionalInputs();\n }\n\n onAfterSetPan: SetterHooks<IStereoPannerProps>[\"onAfterSetPan\"] = (value) => {\n this.audioNode.pan.value = value;\n };\n\n private registerAdditionalInputs() {\n this.registerAudioInput({\n name: \"pan\",\n getAudioNode: () => this.audioNode.pan,\n });\n }\n}\n\nexport default class StereoPanner extends PolyModule<ModuleType.StereoPanner> {\n constructor(\n engineId: string,\n params: IPolyModuleConstructor<ModuleType.StereoPanner>,\n ) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const monoModuleConstructor = (\n engineId: string,\n params: IModuleConstructor<ModuleType.StereoPanner>,\n ) => new MonoStereoPanner(engineId, params);\n\n super(engineId, {\n ...params,\n props,\n monoModuleConstructor,\n });\n\n this.registerAdditionalInputs();\n this.registerDefaultIOs();\n }\n\n private registerAdditionalInputs() {\n this.registerAudioInput({ name: \"pan\" });\n }\n}\n","import { ContextTime } from \"@blibliki/transport\";\nimport { Module, IModule, MidiOutput, Note, ModulePropSchema } from \"@/core\";\nimport MidiEvent from \"@/core/midi/MidiEvent\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IVirtualMidi = IModule<ModuleType.VirtualMidi>;\nexport type IVirtualMidiProps = {\n activeNotes: string[];\n};\n\nexport const virtualMidiPropSchema: ModulePropSchema<IVirtualMidiProps> = {\n activeNotes: {\n kind: \"array\",\n label: \"Active notes\",\n },\n};\n\nconst DEFAULT_PROPS: IVirtualMidiProps = { activeNotes: [] };\n\nexport default class VirtualMidi extends Module<ModuleType.VirtualMidi> {\n declare audioNode: undefined;\n midiOutput!: MidiOutput;\n\n constructor(engineId: string, params: ICreateModule<ModuleType.VirtualMidi>) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n\n super(engineId, {\n ...params,\n props,\n });\n\n this.registerInputs();\n this.registerOutputs();\n }\n\n sendMidi(midiEvent: MidiEvent) {\n this.midiOutput.onMidiEvent(midiEvent);\n }\n\n triggerAttack = (note: Note, triggerAttack: ContextTime) => {\n this.props = { activeNotes: [...this.props.activeNotes, note.fullName] };\n this.triggerPropsUpdate();\n this.sendMidi(MidiEvent.fromNote(note, true, triggerAttack));\n };\n\n triggerRelease = (note: Note, triggerAttack: ContextTime) => {\n this.props = {\n activeNotes: this.props.activeNotes.filter(\n (name) => name !== note.fullName,\n ),\n };\n this.triggerPropsUpdate();\n this.sendMidi(MidiEvent.fromNote(note, false, triggerAttack));\n };\n\n private registerInputs() {\n this.registerMidiInput({\n name: \"midi in\",\n onMidiEvent: this.onMidiEvent,\n });\n }\n\n private registerOutputs() {\n this.midiOutput = this.registerMidiOutput({ name: \"midi out\" });\n }\n}\n"],"mappings":"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","names":["index_exports","__export","Engine","MidiDevice","MidiMappingMode","MidiPortState","ModuleType","Note","OscillatorWave","moduleSchemas","__toCommonJS","import_transport","import_utils","import_utils","import_utils","import_es_toolkit","import_utils","PolyModule","engineId","params","id","name","moduleType","voices","monoModuleConstructor","props","InputCollection","OutputCollection","value","m","time","audioModule","from","to","output","input","callback","midiEvent","voiceNo","moduleByVoice","Engine","import_utils","Base","module","props","io","plugOther","currentIO","callback","connections","otherIO","IO","PolyAudioInput","IO","io","plugOther","PolyAudioOutput","plugOrUnplug","voice","thisIO","otherIO","isPlug","maxVoices","thisMonoIO","otherMonoIO","AudioInput","IO","module","props","AudioOutput","io","plugOther","PolyAudioInput","input","MidiInput","IO","module","props","MidiOutput","event","input","IOCollection","collectionType","module","props","io","PolyModule","AudioInput","AudioOutput","Module","PolyAudioInput","PolyAudioOutput","MidiInput","MidiOutput","callback","id","name","InputCollection","OutputCollection","Message","data","frequencyTable","frequencyTable_default","Notes","MIDI_OCTAVE_SYTSTEM","Note","_Note","frequency","noteName","note","freq","frequencyTable_default","message","name","octave","noteOn","statusByte","string","matches","props","MidiEvent","_MidiEvent","noteName","noteOn","triggeredAt","note","Note","Message","cc","value","message","voiceNo","newEvent","Module","engineId","params","id","name","moduleType","voiceNo","audioNodeConstructor","props","InputCollection","OutputCollection","value","updatedValue","key","propValue","result","hookType","hookName","hook","audioModule","from","to","output","input","callback","_time","note","_triggeredAt","n","_event","midiEvent","triggeredAt","Engine","import_utils","Routes","engine","props","id","route","_","sourceIO","destinationIO","source","destination","import_jzz","MidiPortState","MidiDevice","input","id","name","context","msg","state","callback","c","data","message","Message","timestamp","midiEvent","MidiEvent","MAP_KEYS","Note","computerKeyboardData","ComputerKeyboardInput","context","id","name","state","callback","c","noteOn","event","note","midiEvent","MidiEvent","MidiDeviceManager","context","id","name","d","callback","jzz","JZZ","info","inputInfo","port","device","MidiDevice","err","computerKeyboardDevice","ComputerKeyboardInput","currentInputIds","i","jzzPort","listener","import_utils","voiceSchedulerPropSchema","DEFAULT_PROPS","Voice","Module","engineId","params","props","midiEvent","triggeredAt","note","type","noteName","VoiceScheduler","PolyModule","monoModuleConstructor","voice","v","a","b","constantPropSchema","DEFAULT_PROPS","Constant","Module","engineId","params","props","audioNodeConstructor","context","value","time","note","triggeredAt","import_utils","DEFAULT_PROPS","envelopePropSchema","MonoEnvelope","Module","engineId","params","props","audioNodeConstructor","context","audioNode","note","triggeredAt","attack","decay","sustain","release","currentGainValue","Envelope","PolyModule","monoModuleConstructor","gainPropSchema","DEFAULT_PROPS","MonoGain","Module","engineId","params","props","audioNodeConstructor","context","value","Gain","PolyModule","monoModuleConstructor","MIN_FREQ","MAX_FREQ","DEFAULT_PROPS","filterPropSchema","MonoFilter","Module","engineId","params","props","audioNodeConstructor","context","MonoGain","createModule","value","Filter","PolyModule","monoModuleConstructor","inspectorPropSchema","DEFAULT_PROPS","Inspector","Module","engineId","params","props","audioNodeConstructor","context","value","DEFAULT_PROPS","masterPropSchema","Master","Module","engineId","params","props","audioNodeConstructor","context","MidiMappingMode","midiMapperPropSchema","DEFAULT_PROPS","getMidiFromMappedValue","value","midiValue","propSchema","mapping","min","max","exp","threshold","mode","curvedValue","newMidiValue","MidiMapper","Module","engineId","params","props","event","triggeredAt","activePage","m","_triggeredAt","propName","mappedModule","moduleSchemas","mappedValue","currentValue","normalizedMidi","steps","optionIndex","clampedIndex","hasGlobalAutoAssign","autoAssign","hasPageAutoAssign","updatedGlobalMappings","updatedPageMappings","updatedPages","page","index","midiSelectorPropSchema","DEFAULT_PROPS","MidiSelector","Module","engineId","params","props","midiDevice","value","midiEvent","import_utils","LOW_GAIN","OscillatorWave","oscillatorPropSchema","DEFAULT_PROPS","MonoOscillator","Module","engineId","params","props","audioNodeConstructor","context","value","lowGain","time","note","triggeredAt","lastNote","frequency","coarse","octave","fine","actionAt","Oscillator","PolyModule","monoModuleConstructor","audioModule","import_utils","filterProcessorURL","FilterProcessor","inputs","outputs","parameters","input","output","cutoff","resonance","channelNum","inputChannel","outputChannel","i","s","cutoffHz","clampedHz","normalizedCutoff","c","mrc","scaleProcessorURL","ScaleProcessor","inputs","outputs","parameters","input","output","minValues","maxValues","currentValues","outputChannel","current","channel","inputChannel","i","x","min","max","loadProcessors","context","scaleProcessorURL","filterProcessorURL","newAudioWorklet","worklet","scalePropSchema","DEFAULT_PROPS","Scale","Module","engineId","params","props","audioNodeConstructor","context","newAudioWorklet","value","stepSequencerPropSchema","DEFAULT_PROPS","StepSequencer","Module","engineId","params","props","stereoPannerPropSchema","DEFAULT_PROPS","MonoStereoPanner","Module","engineId","params","props","audioNodeConstructor","context","value","StereoPanner","PolyModule","monoModuleConstructor","virtualMidiPropSchema","DEFAULT_PROPS","VirtualMidi","Module","engineId","params","props","midiEvent","note","triggerAttack","MidiEvent","name","ModuleType","moduleSchemas","oscillatorPropSchema","gainPropSchema","masterPropSchema","midiSelectorPropSchema","envelopePropSchema","filterPropSchema","scalePropSchema","stereoPannerPropSchema","inspectorPropSchema","constantPropSchema","midiMapperPropSchema","virtualMidiPropSchema","stepSequencerPropSchema","voiceSchedulerPropSchema","createModule","engineId","params","Oscillator","Gain","Master","MidiSelector","Envelope","Filter","Scale","StereoPanner","Inspector","Constant","MidiMapper","VirtualMidi","StepSequencer","VoiceScheduler","Engine","_Engine","id","engine","data","bpm","timeSignature","modules","routes","context","m","r","_start","_end","_event","_ticks","_actionAt","Routes","MidiDeviceManager","loadProcessors","params","module","createModule","updates","PolyModule","props","source","destination","output","input","value","moduleId","ioName","type","name","callback","noteName","virtualMidi","MidiEvent","actionAt","import_transport","import_utils"]}