@blibliki/engine 0.3.10 → 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/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "@blibliki/engine",
3
- "version": "0.3.10",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
- "source": "src/index.ts",
6
- "main": "dist/index.cjs",
7
- "module": "dist/index.js",
8
- "types": "dist/index.d.ts",
5
+ "exports": {
6
+ ".": {
7
+ "types": "./dist/index.d.ts",
8
+ "import": "./dist/index.js"
9
+ },
10
+ "./package.json": "./package.json"
11
+ },
9
12
  "files": [
10
13
  "README.md",
11
14
  "src",
@@ -19,9 +22,8 @@
19
22
  "dependencies": {
20
23
  "@julusian/midi": "^3.6.1",
21
24
  "es-toolkit": "^1.41.0",
22
- "node-web-audio-api": "^1.0.3",
23
- "@blibliki/utils": "^0.3.10",
24
- "@blibliki/transport": "^0.3.10"
25
+ "@blibliki/transport": "^0.4.0",
26
+ "@blibliki/utils": "^0.4.0"
25
27
  },
26
28
  "scripts": {
27
29
  "build": "tsup",
@@ -1,3 +1,4 @@
1
+ import { AudioParam } from "@blibliki/utils/web-audio-api";
1
2
  import { ModuleType } from "@/modules";
2
3
  import { Module } from "../module";
3
4
  import IO, { IOProps, IOType } from "./Base";
@@ -1,5 +1,6 @@
1
1
  import { ContextTime } from "@blibliki/transport";
2
2
  import { Context } from "@blibliki/utils";
3
+ import { ConstantSourceNode } from "@blibliki/utils/web-audio-api";
3
4
  import { IModule, Module, ModulePropSchema, SetterHooks } from "@/core";
4
5
  import Note from "@/core/Note";
5
6
  import { ICreateModule, ModuleType } from ".";
@@ -1,5 +1,6 @@
1
1
  import { ContextTime } from "@blibliki/transport";
2
2
  import { Context, cancelAndHoldAtTime } from "@blibliki/utils";
3
+ import { GainNode } from "@blibliki/utils/web-audio-api";
3
4
  import { Module } from "@/core";
4
5
  import Note from "@/core/Note";
5
6
  import { IModuleConstructor } from "@/core/module/Module";
@@ -1,4 +1,5 @@
1
1
  import { Context } from "@blibliki/utils";
2
+ import { BiquadFilterNode } from "@blibliki/utils/web-audio-api";
2
3
  import { EnumProp, ModulePropSchema } from "@/core";
3
4
  import { IModuleConstructor, Module, SetterHooks } from "@/core/module/Module";
4
5
  import { IPolyModuleConstructor, PolyModule } from "@/core/module/PolyModule";
@@ -1,4 +1,5 @@
1
1
  import { Context } from "@blibliki/utils";
2
+ import { GainNode } from "@blibliki/utils/web-audio-api";
2
3
  import { IModule, Module, ModulePropSchema, SetterHooks } from "@/core";
3
4
  import { IModuleConstructor } from "@/core/module/Module";
4
5
  import { IPolyModuleConstructor, PolyModule } from "@/core/module/PolyModule";
@@ -1,4 +1,5 @@
1
1
  import { Context } from "@blibliki/utils";
2
+ import { AnalyserNode } from "@blibliki/utils/web-audio-api";
2
3
  import { IModule, Module, SetterHooks } from "@/core";
3
4
  import { EnumProp, ModulePropSchema } from "@/core/schema";
4
5
  import { ICreateModule, ModuleType } from ".";
@@ -1,5 +1,6 @@
1
1
  import { ContextTime } from "@blibliki/transport";
2
2
  import { Context, dbToGain } from "@blibliki/utils";
3
+ import { GainNode, OscillatorNode } from "@blibliki/utils/web-audio-api";
3
4
  import { IModule, Module } from "@/core";
4
5
  import Note from "@/core/Note";
5
6
  import { IModuleConstructor, SetterHooks } from "@/core/module/Module";
@@ -1,4 +1,5 @@
1
1
  import { Context } from "@blibliki/utils";
2
+ import { StereoPannerNode } from "@blibliki/utils/web-audio-api";
2
3
  import { IModule, Module, ModulePropSchema } from "@/core";
3
4
  import { IModuleConstructor, SetterHooks } from "@/core/module/Module";
4
5
  import { IPolyModuleConstructor, PolyModule } from "@/core/module/PolyModule";
package/dist/index.cjs DELETED
@@ -1,2 +0,0 @@
1
- "use strict";var ht=Object.create;var re=Object.defineProperty;var ft=Object.getOwnPropertyDescriptor;var yt=Object.getOwnPropertyNames;var gt=Object.getPrototypeOf,It=Object.prototype.hasOwnProperty;var Pt=(r,e)=>{for(var t in e)re(r,t,{get:e[t],enumerable:!0})},ke=(r,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of yt(e))!It.call(r,i)&&i!==t&&re(r,i,{get:()=>e[i],enumerable:!(o=ft(e,i))||o.enumerable});return r};var Tt=(r,e,t)=>(t=r!=null?ht(gt(r)):{},ke(e||!r||!r.__esModule?re(t,"default",{value:r,enumerable:!0}):t,r)),vt=r=>ke(re({},"__esModule",{value:!0}),r);var qt={};Pt(qt,{Context:()=>Mt.Context,Engine:()=>S,MidiDevice:()=>v,MidiMappingMode:()=>ae,MidiPortState:()=>z,ModuleType:()=>j,Note:()=>a,OscillatorWave:()=>Z,TransportState:()=>mt.TransportState,moduleSchemas:()=>le});module.exports=vt(qt);var ct=require("@blibliki/transport"),A=require("@blibliki/utils");var ue=require("@blibliki/utils");var De=require("@blibliki/utils"),Fe=require("es-toolkit");var ne=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,ne.uuidv4)(),this.engineId=e,this.name=i,this.moduleType=n,this._props=u,this.inputs=new O(this),this.outputs=new b(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,ne.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 S.getById(this.engineId)}get context(){return this.engine.context}};var we=require("@blibliki/utils");var Me=class{id;ioType;name;module;connections;constructor(e,t){this.module=e,this.name=t.name,this.ioType=t.ioType,this.id=(0,we.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 Me{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 C)&&se(this,e,!0)}unPlug(e,t=!0){super.unPlug(e,t),!(!t&&e instanceof C)&&se(this,e,!1)}findIOByVoice(e){return this.module.findVoice(e).inputs.findByName(this.name)}},C=class extends g{plug(e,t=!0){super.plug(e,t),!(!t&&e instanceof P)&&se(this,e,!0)}unPlug(e,t=!0){super.unPlug(e,t),!(!t&&e instanceof P)&&se(this,e,!1)}findIOByVoice(e){return this.module.findVoice(e).outputs.findByName(this.name)}};function se(r,e,t){if(e instanceof P||e instanceof C){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}},G=class extends g{onMidiEvent=e=>{this.midiConnections.forEach(t=>{t.onMidiEvent(e)})};get midiConnections(){return this.connections.filter(e=>e instanceof N)}};var q=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 C(this.module,e);break;case"midiInput":t=new N(this.module,e);break;case"midiOutput":t=new G(this.module,e);break;default:(0,De.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,Fe.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 q{constructor(e){super("Input",e)}},b=class extends q{constructor(e){super("Output",e)}};var At=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]]),he=At;var fe=["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"],St=2,a=class r{static _notes;name;octave;velocity=1;duration;static fromFrequency(e){let t;for(let[o,i]of he)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=fe[e.data[1]%12],o=Math.floor(e.data[1]/12)-2;return new r(`${t}${o}`)}static notes(e=3){return fe.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 he.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+St)*12+this.noteIndex}get noteIndex(){return fe.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 x=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 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 x(i.midiData(t)),o)}static fromCC(e,t,o){return new r(new x(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,ue.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 b(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,ue.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 S.getById(this.engineId)}get context(){return this.engine.context}};var Ge=require("@blibliki/utils"),V=class{engine;routes;constructor(e){this.engine=e,this.routes=new Map}addRoute(e){let t=e.id??(0,Ge.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 z=(t=>(t.connected="connected",t.disconnected="disconnected",t))(z||{}),v=class{id;name;eventListerCallbacks=[];context;input;messageHandler=null;constructor(e,t){this.id=e.id,this.name=e.name,this.input=e,this.context=t,this.connect()}get state(){return this.input.state}connect(){this.messageHandler=e=>{this.processEvent(e)},this.input.addEventListener(this.messageHandler)}disconnect(){this.messageHandler&&(this.input.removeEventListener(this.messageHandler),this.messageHandler=null)}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 x(e.data),o=new f(t,this.context.browserToContextTime(e.timeStamp));switch(o.type){case"noteon":case"noteoff":case"controlchange":this.eventListerCallbacks.forEach(i=>{i(o)})}}};var xt={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")},Ot=()=>({id:"computer_keyboard",name:"Computer Keyboard",state:"connected"}),E=class{id;name;state;eventListerCallbacks=[];context;constructor(e){let{id:t,name:o,state:i}=Ot();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 xt[e.key]}};var Ve=require("es-toolkit");var qe=require("es-toolkit"),ge=class{id;name;portIndex;input;callbacks=new Set;handler=null;_state="disconnected";constructor(e,t,o){this.portIndex=e,this.id=`node-midi-${e}`,this.name=t,this.input=o}get state(){return this._state}setState(e){this._state=e}addEventListener(e){if(this.callbacks.size===0){this.handler=(t,o)=>{let i={data:new Uint8Array(o),timeStamp:performance.now()};this.callbacks.forEach(n=>{n(i)})};try{this.input.isPortOpen()||(this.input.openPort(this.portIndex),this._state="connected"),this.input.on("message",this.handler)}catch(t){console.error(`Error opening MIDI port ${this.portIndex}:`,t)}}this.callbacks.add(e)}removeEventListener(e){if(this.callbacks.delete(e),this.callbacks.size===0&&this.handler){try{this.input.off("message",this.handler),this.input.isPortOpen()&&(this.input.closePort(),this._state="disconnected")}catch(t){console.error(`Error closing MIDI port ${this.portIndex}:`,t)}this.handler=null}}},Ie=class{ports=new Map;MidiModule;constructor(e){this.MidiModule=e,this.scanPorts()}scanPorts(){try{let e=new this.MidiModule.Input,t=e.getPortCount();for(let o=0;o<t;o++){let i=e.getPortName(o),n=`node-midi-${o}`;if(!this.ports.has(n)){let s=new this.MidiModule.Input,d=new ge(o,i,s);this.ports.set(n,d)}}e.isPortOpen()&&e.closePort()}catch(e){console.error("Error scanning MIDI ports:",e)}}*inputs(){for(let[,e]of this.ports)yield e}addEventListener(e,t){console.warn("Hot-plug detection not supported with node-midi adapter. Restart required for new devices.")}},R=class{async requestMIDIAccess(){try{let e=await import("@julusian/midi"),t="default"in e?e.default:e;return new Ie(t)}catch(e){return console.error("Error loading node-midi:",e),null}}isSupported(){return(0,qe.isNode)()}};var pe=class{input;callbacks=new Set;handler=null;constructor(e){this.input=e}get id(){return this.input.id}get name(){return this.input.name??`Device ${this.input.id}`}get state(){return this.input.state}addEventListener(e){this.callbacks.size===0&&(this.handler=t=>{if(!t.data)return;let o={data:t.data,timeStamp:t.timeStamp};this.callbacks.forEach(i=>{i(o)})},this.input.addEventListener("midimessage",this.handler)),this.callbacks.add(e)}removeEventListener(e){this.callbacks.delete(e),this.callbacks.size===0&&this.handler&&(this.input.removeEventListener("midimessage",this.handler),this.handler=null)}},Pe=class{midiAccess;portCache=new Map;constructor(e){this.midiAccess=e}*inputs(){for(let[,e]of this.midiAccess.inputs)this.portCache.has(e.id)||this.portCache.set(e.id,new pe(e)),yield this.portCache.get(e.id)}addEventListener(e,t){this.midiAccess.addEventListener(e,o=>{let i=o.port;if(!i||i.type!=="input")return;let n=i;this.portCache.has(n.id)||this.portCache.set(n.id,new pe(n)),t(this.portCache.get(n.id))})}},L=class{async requestMIDIAccess(){try{if(typeof navigator>"u"||typeof navigator.requestMIDIAccess!="function")return null;let e=await navigator.requestMIDIAccess();return new Pe(e)}catch(e){return console.error("Error enabling Web MIDI API:",e),null}}isSupported(){return typeof navigator<"u"&&typeof navigator.requestMIDIAccess=="function"}};function ze(){return(0,Ve.isNode)()?new R:new L}var k=class{devices=new Map;initialized=!1;listeners=[];context;midiAccess=null;adapter=ze();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{if(!this.adapter.isSupported()){console.warn("MIDI is not supported on this platform");return}if(this.midiAccess=await this.adapter.requestMIDIAccess(),!this.midiAccess){console.error("Failed to get MIDI access");return}for(let e of this.midiAccess.inputs())this.devices.has(e.id)||this.devices.set(e.id,new v(e,this.context))}catch(e){console.error("Error enabling MIDI:",e)}}addComputerKeyboard(){if(typeof document>"u")return;let e=new E(this.context);this.devices.set(e.id,e)}listenChanges(){this.midiAccess&&this.midiAccess.addEventListener("statechange",e=>{if(e.state==="connected"){if(this.devices.has(e.id))return;let t=new v(e,this.context);this.devices.set(t.id,t),this.listeners.forEach(o=>{o(t)})}else{let t=this.devices.get(e.id);if(!t||t instanceof E)return;t.disconnect(),this.devices.delete(t.id),this.listeners.forEach(o=>{o(t)})}})}};var lt=require("@blibliki/utils");var Re={},Le={},Te=class extends p{activeNote=null;triggeredAt=0;constructor(e,t){let o={...Le,...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")}}},_=class extends m{midiOutput;constructor(e,t){let o={...Le,...t.props},i=(n,s)=>new Te(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 _e={value:{kind:"number",min:-1/0,max:1/0,step:.01,label:"Value"}},bt={value:1},U=class extends p{isStated=!1;constructor(e,t){let o={...bt,...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 ve=require("@blibliki/utils");var Ue={attack:.01,decay:0,sustain:1,release:0},Be={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"}},Ae=class extends p{constructor(e,t){let o={...Ue,...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,ve.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,ve.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)}},B=class extends m{constructor(e,t){let o={...Ue,...t.props},i=(n,s)=>new Ae(n,s);super(e,{...t,props:o,monoModuleConstructor:i}),this.registerDefaultIOs()}};var He={gain:{kind:"number",min:0,max:1/0,step:.01,label:"Gain"}},Ke={gain:1},H=class extends p{constructor(e,t){let o={...Ke,...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})}},K=class extends m{constructor(e,t){let o={...Ke,...t.props},i=(n,s)=>new H(n,s);super(e,{...t,props:o,monoModuleConstructor:i}),this.registerAdditionalInputs(),this.registerDefaultIOs()}registerAdditionalInputs(){this.registerAudioInput({name:"gain"})}};var $e=20,xe=2e4,je={cutoff:xe,envelopeAmount:0,type:"lowpass",Q:1},We={cutoff:{kind:"number",min:$e,max:xe,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"}},Se=class extends p{scale;amount;constructor(e,t){let o={...je,...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 H(e,{name:"amount",moduleType:"Gain",props:{gain:o.envelopeAmount}}),this.scale=de(e,{name:"scale",moduleType:"Scale",props:{min:$e,max:xe,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})}},$=class extends m{constructor(e,t){let o={...je,...t.props},i=(n,s)=>new Se(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 Qe={fftSize:{kind:"enum",options:[32,64,128,256,512,1024,2048,4096,8192,16384,32768],label:"FFT size"}},Ct={fftSize:512},W=class extends p{_buffer;constructor(e,t){let o={...Ct,...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 Nt={},Ye={},Q=class extends p{constructor(e,t){let o={...Nt,...t.props},i=n=>n.destination;super(e,{...t,audioNodeConstructor:i,props:o}),this.registerDefaultIOs("in")}};var ae=(s=>(s.direct="direct",s.directRev="directRev",s.toggleInc="toggleInc",s.toggleDec="toggleDec",s.incDec="incDec",s.incDecRev="incDecRev",s))(ae||{}),Je={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"}},Et={pages:[{name:"Page 1",mappings:[{}]}],activePage:0,globalMappings:[{}]};function kt({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 Y=class extends p{constructor(e,t){let o={...Et,...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=le[d.moduleType][i],c;switch(u.kind){case"number":{let h=d.props[i];if(s==="incDec"||s==="incDecRev"?n=kt({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 w=Math.round((c-M)/u.step);c=M+w*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 Xe={selectedId:{kind:"string",label:"Midi device ID"},selectedName:{kind:"string",label:"Midi device name"}},wt={selectedId:void 0,selectedName:void 0},J=class extends p{midiOutput;_forwardMidiEvent;constructor(e,t){let o={...wt,...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 Oe=require("@blibliki/utils");var be=-18,Z=(i=>(i.sine="sine",i.triangle="triangle",i.square="square",i.sawtooth="sawtooth",i))(Z||{}),Ze={wave:{kind:"enum",options:Object.values(Z),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 ${be}db Gain`}},et={wave:"sine",frequency:440,fine:0,coarse:0,octave:0,lowGain:!1},Ce=class extends p{isStated=!1;outputGain;detuneGain;constructor(e,t){let o={...et,...t.props},i=n=>new OscillatorNode(n.audioContext);super(e,{...t,props:o,audioNodeConstructor:i}),this.outputGain=new GainNode(this.context.audioContext,{gain:(0,Oe.dbToGain)(be)}),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,Oe.dbToGain)(be):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})}},X=class extends m{constructor(e,t){let o={...et,...t.props},i=(n,s)=>new Ce(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 it=require("@blibliki/utils");var tt=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],w=Math.max(20,Math.min(2e4,l)),ce=Math.log(w/20)/Math.log(2e4/20),T=Math.pow(.5,(1-ce)/.125),Ee=1-Math.pow(.5,((u.length>1?u[I]:u[0])+.125)/.125)*T;this.s0=Ee*this.s0-T*this.s1+T*y,this.s1=Ee*this.s1+T*this.s0,M[I]=this.s1}}return!0}}registerProcessor("filter-processor",r)}).toString(),")()"],{type:"application/javascript"}));var ot=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],w=d.length>1?d[y]:d[0],ce=u.length>1?u[y]:u[0],T=c.length>1?c[y]:c[0];l<0?I[y]=T*Math.pow(w/T,-l):I[y]=T*Math.pow(ce/T,l)}}return!0}}registerProcessor("scale-processor",r)}).toString(),")()"],{type:"application/javascript"}));async function rt(r){await r.addModule(ot),await r.addModule(tt)}function nt(r,e){switch(e){case"ScaleProcessor":return r.newAudioWorklet("scale-processor");case"FilterProcessor":return r.newAudioWorklet("filter-processor");default:(0,it.assertNever)(e)}}var st={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"}},Dt={min:0,max:1,current:.5},ee=class extends p{constructor(e,t){let o={...Dt,...t.props},i=n=>nt(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 ut={steps:{kind:"number",min:1,max:16,step:1,label:"Steps"},bars:{kind:"number",min:1,max:16,step:1,label:"Steps"}},Ft={sequences:[],steps:16,bars:1},te=class extends p{midiOutput;constructor(e,t){let o={...Ft,...t.props};super(e,{...t,props:o})}};var pt={pan:{kind:"number",min:-1,max:1,step:.01,label:"Pan"}},dt={pan:0},Ne=class extends p{constructor(e,t){let o={...dt,...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})}},oe=class extends m{constructor(e,t){let o={...dt,...t.props},i=(n,s)=>new Ne(n,s);super(e,{...t,props:o,monoModuleConstructor:i}),this.registerAdditionalInputs(),this.registerDefaultIOs()}registerAdditionalInputs(){this.registerAudioInput({name:"pan"})}};var at={activeNotes:{kind:"array",label:"Active notes"}},Gt={activeNotes:[]},ie=class extends p{midiOutput;constructor(e,t){let o={...Gt,...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 j=(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))(j||{}),le={Oscillator:Ze,Gain:He,Master:Ye,MidiSelector:Xe,Envelope:Be,Filter:We,Scale:st,StereoPanner:pt,Inspector:Qe,Constant:_e,MidiMapper:Je,VirtualMidi:at,StepSequencer:ut,VoiceScheduler:Re};function de(r,e){switch(e.moduleType){case"Oscillator":return new X(r,e);case"Gain":return new K(r,e);case"Master":return new Q(r,e);case"MidiSelector":return new J(r,e);case"Envelope":return new B(r,e);case"Filter":return new $(r,e);case"Scale":return new ee(r,e);case"StereoPanner":return new oe(r,e);case"Inspector":return new W(r,e);case"Constant":return new U(r,e);case"MidiMapper":return new Y(r,e);case"VirtualMidi":return new ie(r,e);case"StepSequencer":return new te(r,e);case"VoiceScheduler":return new _(r,e);default:(0,lt.assertNever)(e)}}var S=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,A.assertDefined)(t),t}static get current(){return(0,A.assertDefined)(this._currentId),this.getById(this._currentId)}static async load(e){let{bpm:t,timeSignature:o,modules:i,routes:n}=e,s=new A.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,A.uuidv4)(),this.context=e,this.transport=new ct.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 k(this.context),r._engines.set(this.id,this),r._currentId=this.id}get state(){return this.transport.state}async initialize(){this.isInitialized||(await rt(this.context),await this.midiDeviceManager.initialize(),this.isInitialized=!0)}addModule(e){let t=de(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,A.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 mt=require("@blibliki/transport"),Mt=require("@blibliki/utils");
2
- //# sourceMappingURL=index.cjs.map