@blibliki/engine 0.3.3 → 0.3.5

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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../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/MidiEvent.ts","../src/core/Note/frequencyTable.ts","../src/core/Note/index.ts","../src/core/Timing/Time.ts","../src/core/Timing/Scheduler.ts","../src/core/Timing/Transport.ts","../src/core/Timing/index.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/Gain.ts","../src/modules/BiquadFilter.ts","../src/modules/Constant.ts","../src/modules/Envelope.ts","../src/processors/index.ts","../src/processors/filter-processor.ts","../src/processors/scale-processor.ts","../src/modules/Filter.ts","../src/modules/Inspector.ts","../src/modules/Master.ts","../src/modules/MidiSelector.ts","../src/modules/Oscillator.ts","../src/modules/Scale.ts","../src/modules/StepSequencer.ts","../src/modules/VirtualMidi.ts"],"sourcesContent":["import { assertDefined, Optional, pick, uuidv4 } from \"@blibliki/utils\";\nimport {\n IAnyAudioContext,\n IRoute,\n Routes,\n MidiDeviceManager,\n IModule,\n TTime,\n Transport,\n MidiEvent,\n} from \"@/core\";\nimport {\n ICreateModule,\n ModuleParams,\n ModuleType,\n ModuleTypeToModuleMapping,\n createModule,\n} from \"@/modules\";\nimport { PolyModule } 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 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>,\n ) => void)[] = [];\n\n readonly id: string;\n context: IAnyAudioContext;\n isInitialized = false;\n routes: Routes;\n transport: Transport;\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 constructor(context: IAnyAudioContext) {\n this.id = uuidv4();\n\n this.context = context;\n this.transport = new Transport({\n onStart: this.onStart,\n onStop: this.onStop,\n });\n this.routes = new Routes(this);\n this.modules = new Map();\n this.midiDeviceManager = new MidiDeviceManager();\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(props: { offset?: TTime; actionAt?: TTime } = {}) {\n await this.resume();\n this.transport.start(props);\n }\n\n stop(props: { actionAt?: TTime } = {}) {\n this.transport.stop(props);\n }\n\n pause(props: { actionAt?: TTime } = {}) {\n this.transport.pause(props);\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: [number, number]) {\n this.transport.timeSignature = value;\n }\n\n get playhead() {\n return this.transport.playhead;\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 Engine._engines.delete(this.id);\n Engine._currentId = Engine._engines.keys().next().value;\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 onPropsUpdate(callback: <T extends ModuleType>(params: IModule<T>) => void) {\n this.propsUpdateCallbacks.push(callback);\n }\n\n _triggerPropsUpdate<T extends ModuleType>(params: IModule<T>) {\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(MidiEvent.fromNote(noteName, type === \"noteOn\"));\n }\n\n private onStart = (actionAt: TTime) => {\n this.modules.forEach((module) => {\n module.start(actionAt);\n });\n };\n\n private onStop = (actionAt: TTime) => {\n this.modules.forEach((module) => {\n module.stop(actionAt);\n });\n };\n}\n","import { Optional, upperFirst, uuidv4 } from \"@blibliki/utils\";\nimport { Engine } from \"@/Engine\";\nimport { AnyModule, ModuleType, ModuleTypeToPropsMapping } from \"@/modules\";\nimport { IAnyAudioContext } from \"../\";\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 { TTime } from \"../Timing/Time\";\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: IAnyAudioContext) => AudioNode;\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 superInitialized = false;\n protected activeNotes: Note[];\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 = {} as ModuleTypeToPropsMapping[T];\n this.props = props;\n\n this.inputs = new InputCollection(this);\n this.outputs = new OutputCollection(this);\n\n this.superInitialized = true;\n }\n\n get props(): ModuleTypeToPropsMapping[T] {\n return this._props;\n }\n\n set props(value: Partial<ModuleTypeToPropsMapping[T]>) {\n Object.keys(value).forEach((key) => {\n const onSetAttr = `onSet${upperFirst(key)}`;\n\n // @ts-expect-error TS7053 ignore this error\n // eslint-disable-next-line\n this[onSetAttr]?.(value[key]);\n });\n\n this._props = { ...this._props, ...value };\n\n Object.keys(value).forEach((key) => {\n const onSetAttr = `onAfterSet${upperFirst(key)}`;\n\n // @ts-expect-error TS7053 ignore this error\n // eslint-disable-next-line\n this[onSetAttr]?.(value[key]);\n });\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: TTime): void {\n // Optional implementation in modules\n }\n\n stop(_time: TTime): void {\n // Optional implementation in modules\n }\n\n triggerAttack(note: Note, _triggeredAt: TTime): 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: TTime): void {\n this.activeNotes = this.activeNotes.filter(\n (n) => n.fullName !== note.fullName,\n );\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 default:\n throw Error(\"This type is not a note\");\n }\n };\n\n protected triggerPropsUpdate() {\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 }\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 { 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 this.collection.map((io) => io.serialize());\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 { 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 { TTime } from \"../Timing\";\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 protected superInitialized = false;\n private _voices!: number;\n private _name!: string;\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.voices = voices || 1;\n this._props = {} as ModuleTypeToPropsMapping[T];\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 this.superInitialized = true;\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: TTime): void {\n this.audioModules.forEach((m) => {\n m.start(time);\n });\n }\n\n stop(time: TTime): 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 if (!this.superInitialized) return;\n\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 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","import { Message } from \"webmidi\";\nimport Note, { INote } from \"../Note\";\nimport { t, TTime } from \"../Timing/Time\";\n\nexport enum MidiEventType {\n noteOn = \"noteon\",\n noteOff = \"noteoff\",\n cc = \"cc\",\n}\n\nexport default class MidiEvent {\n note?: Note;\n voiceNo?: number;\n readonly triggeredAt: TTime;\n private message: Message;\n\n static fromNote(\n noteName: string | Note | Omit<INote, \"frequency\">,\n noteOn = true,\n triggeredAt?: TTime,\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(cc: number, value: number, triggeredAt?: TTime): MidiEvent {\n return new MidiEvent(\n new Message(new Uint8Array([0xb0, cc, value])),\n triggeredAt,\n );\n }\n\n constructor(message: Message, triggeredAt?: TTime) {\n this.message = message;\n this.triggeredAt = triggeredAt ?? t();\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 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","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 { Message } from \"webmidi\";\nimport { TTime } from \"../Timing/Time\";\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?: TTime;\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?: TTime;\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 { isNumber } from \"@blibliki/utils\";\nimport { Engine } from \"@/Engine\";\nimport { now } from \".\";\n\nexport type BarsBeatsSixteenths = `${number}:${number}:${number}`;\nexport type TTime = number | BarsBeatsSixteenths | Time;\n\nexport const t = (value?: TTime): Time => {\n value ??= now();\n\n if (value instanceof Time) return value;\n\n return new Time(value);\n};\n\nexport const nt = (value?: TTime): number => {\n value ??= now();\n\n if (typeof value === \"number\") return value;\n\n return t(value).toNumber();\n};\n\nexport default class Time {\n private value: number | BarsBeatsSixteenths;\n private _notation?: BarsBeatsSixteenths;\n private _number?: number;\n\n constructor(value: TTime) {\n this.value = value instanceof Time ? value.value : value;\n\n if (isNumber(this.value)) {\n this._number = this.value;\n } else {\n this._notation = this.value;\n }\n }\n\n add(value: TTime): Time {\n return t(this.toNumber() + t(value).toNumber());\n }\n\n subtrack(value: TTime): Time {\n return t(this.toNumber() - nt(value));\n }\n\n isBefore(value: TTime): boolean {\n return this.toNumber() < nt(value);\n }\n\n isAfter(value: TTime): boolean {\n return this.toNumber() > nt(value);\n }\n\n isEqual(value: TTime): boolean {\n return this.toNumber() > nt(value);\n }\n\n toNotation(): BarsBeatsSixteenths {\n if (this._notation) return this._notation;\n\n const [count, factor] = this.transport.timeSignature;\n const divisionsPerBeat = 16 / factor;\n const divisionsPerBar = count * divisionsPerBeat;\n const secondsPerBeat = 60 / this.transport.bpm;\n\n const totalDivisions = Math.floor(\n ((this.value as number) / secondsPerBeat) * divisionsPerBeat,\n );\n\n const bars = Math.floor(totalDivisions / divisionsPerBar);\n const beats = Math.floor(\n (totalDivisions % divisionsPerBar) / divisionsPerBeat,\n );\n const divisions = totalDivisions % divisionsPerBeat;\n\n this._notation = `${bars}:${beats}:${divisions}`;\n\n return this._notation;\n }\n\n toNumber(): number {\n if (isNumber(this._number)) return this._number;\n\n const [beatsPerBar, sixteenths] = this.transport.timeSignature;\n const secondsPerBeat = 60 / this.transport.bpm;\n\n const [bars, beats, divisions] = (this.value as BarsBeatsSixteenths)\n .split(\":\")\n .map(Number);\n\n const totalBeats =\n bars * beatsPerBar + beats + divisions / (sixteenths / 4);\n\n this._number = totalBeats * secondsPerBeat;\n\n return this._number;\n }\n\n private get transport() {\n return Engine.current.transport;\n }\n}\n","import { Scheduler as InternalScheduler } from \"@ircam/sc-scheduling\";\nimport { now } from \".\";\nimport { nt, t, TTime } from \"./Time\";\nimport Transport from \"./Transport\";\n\nexport default class Scheduler {\n transport: Transport;\n internalScheduler: InternalScheduler;\n\n constructor(transport: Transport) {\n this.transport = transport;\n this.internalScheduler = new InternalScheduler(now, {\n currentTimeToProcessorTimeFunction: () => this.transport.playhead,\n });\n }\n\n start(actionAt: TTime, callback: () => void) {\n this.internalScheduler.add(this.processor, nt(actionAt));\n this.defer(callback, actionAt);\n }\n\n stop(actionAt: TTime, callback: () => void) {\n this.defer(() => {\n this.internalScheduler.remove(this.processor);\n callback();\n }, actionAt);\n }\n\n defer(callback: () => void, actionAt: TTime) {\n this.internalScheduler.defer(callback, nt(actionAt));\n }\n\n private processor = (currentTime: number, playhead: TTime) => {\n console.log(`playhead: ${t(playhead).toNotation()}`);\n return currentTime + 0.5;\n };\n}\n","import { now } from \".\";\nimport Scheduler from \"./Scheduler\";\nimport Time, { t, TTime } from \"./Time\";\n\nexport enum TransportState {\n playing = \"playing\",\n stopped = \"stopped\",\n paused = \"paused\",\n}\n\nexport type TransportEvents = {\n start: { actionAt: TTime; offset: TTime };\n stop: { actionAt: TTime };\n pause: { actionAt: TTime };\n};\n\ntype TPlaybackCallback = (actionAt: TTime) => void;\n\ntype TransportProps = {\n onStart?: TPlaybackCallback;\n onStop?: TPlaybackCallback;\n};\n\nexport default class Transport {\n bpm = 120;\n timeSignature: [number, number] = [4, 4];\n loopStart: TTime;\n loopEnd?: TTime;\n\n state: TransportState = TransportState.stopped;\n offset: TTime = 0;\n\n private startTime: TTime = 0;\n private onStart: TransportProps[\"onStart\"];\n private onStop: TransportProps[\"onStop\"];\n private scheduler: Scheduler;\n\n constructor(props: TransportProps) {\n this.onStart = props.onStart;\n this.onStop = props.onStop;\n this.loopStart = t(\"0:0:0\");\n this.scheduler = new Scheduler(this);\n }\n\n start({\n offset = this.offset,\n actionAt = now(),\n }: {\n offset?: TTime;\n actionAt?: TTime;\n }) {\n if (this.state === TransportState.playing) return;\n\n this.validateFutureTime(actionAt);\n\n this.scheduler.start(actionAt, () => {\n this.state = TransportState.playing;\n this.offset = offset;\n this.startTime = t(actionAt).subtrack(this.offset);\n });\n this.onStart?.(actionAt);\n\n return actionAt;\n }\n\n stop({ actionAt: actionAt = now() }: { actionAt?: TTime }) {\n if (this.state === TransportState.stopped) return;\n\n this.validateFutureTime(actionAt);\n\n this.scheduler.stop(actionAt, () => {\n this.state = TransportState.stopped;\n this.offset = 0;\n });\n this.onStop?.(actionAt);\n\n return actionAt;\n }\n\n pause({ actionAt: actionAt = now() }: { actionAt?: TTime }) {\n if (this.state === TransportState.paused) return;\n\n this.validateFutureTime(actionAt);\n\n this.scheduler.stop(actionAt, () => {\n this.state = TransportState.paused;\n this.offset = t(actionAt).subtrack(this.startTime);\n });\n this.onStop?.(actionAt);\n\n return actionAt;\n }\n\n get playhead(): Time {\n if (this.state === TransportState.stopped) return t(0);\n if (this.state === TransportState.paused) return t(this.offset);\n\n return t(now()).subtrack(this.startTime);\n }\n\n private validateFutureTime(time: TTime) {\n if (t(time).isBefore(now())) throw Error(\"Past time not allowed\");\n }\n}\n","import { Engine } from \"@/Engine\";\n\nexport { default as Transport, TransportState } from \"./Transport\";\nexport { default as Time, t, nt } from \"./Time\";\n\nexport type { TransportEvents } from \"./Transport\";\nexport type { TTime } from \"./Time\";\n\nexport function now() {\n return Engine.current.context.currentTime;\n}\n\nexport function browserToContextTime(time: number): number {\n const differenceBetweenClocks = performance.now() / 1000 - now();\n return time / 1000 - differenceBetweenClocks;\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 for (const id in this.routes) {\n this.removeRoute(id);\n }\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 { Input, Output, WebMidi } from \"webmidi\";\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\n constructor() {\n const computerKeyboardDevice = new ComputerKeyboardDevice();\n this.devices.set(computerKeyboardDevice.id, computerKeyboardDevice);\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 addListener(callback: ListenerCallback) {\n this.listeners.push(callback);\n }\n\n private async initializeDevices() {\n if (this.initialized) return;\n\n try {\n await WebMidi.enable();\n\n WebMidi.inputs.forEach((input) => {\n if (!this.devices.has(input.id)) {\n this.devices.set(input.id, new MidiDevice(input));\n }\n });\n } catch (err) {\n console.error(\"Error enabling WebMidi:\", err);\n }\n }\n\n private listenChanges() {\n WebMidi.addListener(\"connected\", (event) => {\n const port = event.port as Input | Output;\n if (port instanceof Output) return;\n\n if (this.devices.has(port.id)) return;\n\n const device = new MidiDevice(port);\n this.devices.set(device.id, device);\n\n this.listeners.forEach((listener) => {\n listener(device);\n });\n });\n\n WebMidi.addListener(\"disconnected\", (event) => {\n const port = event.port as Input | Output;\n if (port instanceof Output) return;\n\n const device = this.devices.get(port.id);\n if (!device) return;\n if (device instanceof ComputerKeyboardDevice) return;\n\n device.disconnect();\n this.devices.delete(device.id);\n\n this.listeners.forEach((listener) => {\n listener(device);\n });\n });\n }\n}\n","import { MessageEvent, Input } from \"webmidi\";\nimport { browserToContextTime } from \"../Timing\";\nimport MidiEvent, { MidiEventType } from \"./MidiEvent\";\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 input: Input;\n\n constructor(input: Input) {\n this.id = input.id;\n this.name = input.name || `Device ${input.id}`;\n this.input = input;\n\n this.connect();\n }\n\n get state() {\n return this.input.state as MidiPortState;\n }\n\n connect() {\n this.input.addListener(\"midimessage\", (e: MessageEvent) => {\n this.processEvent(e);\n });\n }\n\n disconnect() {\n this.input.removeListener();\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(event: MessageEvent) {\n const midiEvent = new MidiEvent(\n event.message,\n browserToContextTime(event.timestamp),\n );\n\n switch (midiEvent.type) {\n case MidiEventType.noteOn:\n case MidiEventType.noteOff:\n this.eventListerCallbacks.forEach((callback) => {\n callback(midiEvent);\n });\n }\n }\n}\n","import 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\n constructor() {\n const { id, name, state } = computerKeyboardData();\n this.id = id;\n this.name = name;\n this.state = state;\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(note, noteOn);\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, PropSchema } from \"@/core\";\nimport { IPolyModuleConstructor } from \"@/core/module/PolyModule\";\nimport VoiceScheduler, {\n IVoiceSchedulerProps,\n voiceSchedulerPropSchema,\n} from \"@/core/module/VoiceScheduler\";\nimport BiquadFilter, {\n biquadFilterPropSchema,\n IBiquadFilterProps,\n} from \"./BiquadFilter\";\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 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 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 BiquadFilter = \"BiquadFilter\",\n Scale = \"Scale\",\n Inspector = \"Inspector\",\n Constant = \"Constant\",\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.BiquadFilter]: IBiquadFilterProps;\n [ModuleType.Scale]: IScaleProps;\n [ModuleType.Inspector]: IInspectorProps;\n [ModuleType.Constant]: IConstantProps;\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.BiquadFilter]: BiquadFilter;\n [ModuleType.Scale]: Scale;\n [ModuleType.Inspector]: Inspector;\n [ModuleType.Constant]: Constant;\n [ModuleType.VirtualMidi]: VirtualMidi;\n [ModuleType.StepSequencer]: StepSequencer;\n [ModuleType.VoiceScheduler]: VoiceScheduler;\n};\n\nexport const moduleSchemas: {\n [K in ModuleType]: PropSchema<Partial<ModuleTypeToPropsMapping[K]>>;\n} = {\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.BiquadFilter]: biquadFilterPropSchema,\n [ModuleType.Scale]: scalePropSchema,\n [ModuleType.Inspector]: inspectorPropSchema,\n [ModuleType.Constant]: constantPropSchema,\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 {\n IStepSequencer,\n IStepSequencerProps,\n ISequence,\n} from \"./StepSequencer\";\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.BiquadFilter\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.BiquadFilter:\n return new BiquadFilter(engineId, params);\n case ModuleType.Scale:\n return new Scale(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.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 { EmptyObject } from \"@blibliki/utils\";\nimport { ICreateModule, ModuleType } from \"@/modules\";\nimport { MidiOutput } from \"../IO\";\nimport { nt, t, TTime } from \"../Timing/Time\";\nimport MidiEvent, { MidiEventType } from \"../midi/MidiEvent\";\nimport { PropSchema } from \"../schema\";\nimport { IModuleConstructor, Module } from \"./Module\";\nimport { IPolyModuleConstructor, PolyModule } from \"./PolyModule\";\n\nexport type IVoiceSchedulerProps = EmptyObject;\nexport const voiceSchedulerPropSchema: PropSchema<IVoiceSchedulerProps> = {};\nconst DEFAULT_PROPS = {};\n\nclass Voice extends Module<ModuleType.VoiceScheduler> {\n declare audioNode: undefined;\n activeNote: string | null = null;\n triggeredAt: TTime = t(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 nt(a.triggeredAt) - nt(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 { IAnyAudioContext, IModule, Module } from \"@/core\";\nimport { IModuleConstructor } from \"@/core/module/Module\";\nimport { IPolyModuleConstructor, PolyModule } from \"@/core/module/PolyModule\";\nimport { PropSchema } from \"@/core/schema\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IGain = IModule<ModuleType.Gain>;\nexport type IGainProps = {\n gain: number;\n};\n\nexport const gainPropSchema: PropSchema<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 extends Module<ModuleType.Gain> {\n declare audioNode: GainNode;\n\n constructor(engineId: string, params: ICreateModule<ModuleType.Gain>) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const audioNodeConstructor = (context: IAnyAudioContext) =>\n new GainNode(context);\n\n super(engineId, {\n ...params,\n audioNodeConstructor,\n props,\n });\n\n this.registerDefaultIOs();\n this.registerAdditionalInputs();\n }\n\n protected onSetGain(value: IGainProps[\"gain\"]) {\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 { IAnyAudioContext, Module } from \"@/core\";\nimport { IModuleConstructor } from \"@/core/module/Module\";\nimport { IPolyModuleConstructor, PolyModule } from \"@/core/module/PolyModule\";\nimport { PropSchema } from \"@/core/schema\";\nimport { createModule, ICreateModule, ModuleType } from \".\";\nimport { MonoGain } from \"./Gain\";\nimport Scale from \"./Scale\";\n\nexport type IBiquadFilterProps = {\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: IBiquadFilterProps = {\n cutoff: MAX_FREQ,\n envelopeAmount: 0,\n type: \"lowpass\",\n Q: 1,\n};\n\nexport const biquadFilterPropSchema: PropSchema<IBiquadFilterProps> = {\n cutoff: {\n kind: \"number\",\n min: MIN_FREQ,\n max: MAX_FREQ,\n step: 1,\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: -100,\n max: 100,\n step: 0.1,\n label: \"Q\",\n },\n};\n\nclass MonoBiquadFilter extends Module<ModuleType.BiquadFilter> {\n declare audioNode: BiquadFilterNode;\n private scale: Scale;\n private amount: MonoGain;\n\n constructor(\n engineId: string,\n params: ICreateModule<ModuleType.BiquadFilter>,\n ) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n\n const audioNodeConstructor = (context: IAnyAudioContext) =>\n new BiquadFilterNode(context, {\n type: props.type,\n frequency: props.cutoff,\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 protected onSetType(value: IBiquadFilterProps[\"type\"]) {\n this.audioNode.type = value;\n }\n\n protected onSetCutoff(value: IBiquadFilterProps[\"cutoff\"]) {\n if (!this.superInitialized) return;\n\n this.scale.props = { current: value };\n }\n\n protected onSetQ(value: IBiquadFilterProps[\"Q\"]) {\n this.audioNode.Q.value = value;\n }\n\n protected onSetEnvelopeAmount(value: IBiquadFilterProps[\"envelopeAmount\"]) {\n if (!this.superInitialized) return;\n\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 BiquadFilter extends PolyModule<ModuleType.BiquadFilter> {\n constructor(\n engineId: string,\n params: IPolyModuleConstructor<ModuleType.BiquadFilter>,\n ) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const monoModuleConstructor = (\n engineId: string,\n params: IModuleConstructor<ModuleType.BiquadFilter>,\n ) => new MonoBiquadFilter(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 { IAnyAudioContext, IModule, Module } from \"@/core\";\nimport Note from \"@/core/Note\";\nimport { nt, TTime } from \"@/core/Timing/Time\";\nimport { PropSchema } from \"@/core/schema\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IConstant = IModule<ModuleType.Constant>;\nexport type IConstantProps = {\n value: number;\n};\n\nexport const constantPropSchema: PropSchema<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 extends Module<ModuleType.Constant> {\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: IAnyAudioContext) =>\n new ConstantSourceNode(context);\n\n super(engineId, {\n ...params,\n props,\n audioNodeConstructor,\n });\n\n this.registerDefaultIOs(\"out\");\n }\n\n protected onSetValue(value: IConstantProps[\"value\"]) {\n this.audioNode.offset.value = value;\n }\n\n start(time: TTime) {\n if (this.isStated) return;\n\n this.isStated = true;\n this.audioNode.start(nt(time));\n }\n\n stop(time: TTime) {\n this.audioNode.stop(nt(time));\n this.rePlugAll(() => {\n this.audioNode = new ConstantSourceNode(this.context, {\n offset: this.props.value,\n });\n });\n\n this.isStated = false;\n }\n\n triggerAttack = (note: Note, triggeredAt: TTime) => {\n this.audioNode.offset.setValueAtTime(note.frequency, nt(triggeredAt));\n this.start(triggeredAt);\n };\n\n triggerRelease = () => {\n // Do nothing\n };\n}\n","import { createScaleNormalized } from \"@blibliki/utils\";\nimport { IAnyAudioContext, Module } from \"@/core\";\nimport Note from \"@/core/Note\";\nimport { nt, TTime } from \"@/core/Timing/Time\";\nimport { IModuleConstructor } from \"@/core/module/Module\";\nimport { IPolyModuleConstructor, PolyModule } from \"@/core/module/PolyModule\";\nimport { PropSchema } 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.1,\n decay: 0.2,\n sustain: 0,\n release: 0.3,\n};\n\nexport const envelopePropSchema: PropSchema<IEnvelopeProps> = {\n attack: {\n kind: \"number\",\n min: 0.0001,\n max: 1,\n step: 0.01,\n label: \"Attack\",\n },\n decay: {\n kind: \"number\",\n min: 0,\n max: 1,\n step: 0.01,\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: 1,\n step: 0.01,\n label: \"Release\",\n },\n};\n\nconst scaleToTen = createScaleNormalized({\n min: 0.001,\n max: 10,\n});\n\nconst scaleToFive = createScaleNormalized({\n min: 0.001,\n max: 5,\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: IAnyAudioContext) => {\n const audioNode = new GainNode(context);\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: TTime) {\n super.triggerAttack(note, triggeredAt);\n\n const attack = this.scaledAttack();\n const decay = this.scaledDecay();\n const sustain = this.props.sustain;\n const triggeredAtNum = nt(triggeredAt);\n\n this.audioNode.gain.cancelAndHoldAtTime(triggeredAtNum);\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, triggeredAtNum);\n }\n\n // Attack\n this.audioNode.gain.exponentialRampToValueAtTime(\n 1.0,\n triggeredAtNum + attack,\n );\n\n // Decay\n if (sustain > 0) {\n this.audioNode.gain.exponentialRampToValueAtTime(\n sustain,\n triggeredAtNum + attack + decay,\n );\n // Do not set to zero or anything else!\n } else {\n this.audioNode.gain.exponentialRampToValueAtTime(\n 0.001,\n triggeredAtNum + attack + decay,\n );\n }\n }\n\n triggerRelease(note: Note, triggeredAt: TTime) {\n super.triggerRelease(note, triggeredAt);\n if (this.activeNotes.length > 0) return;\n\n const release = this.scaledRelease();\n const triggeredAtNum = nt(triggeredAt);\n\n // Cancel scheduled automations and set gain to the ACTUAL value at this moment\n this.audioNode.gain.cancelAndHoldAtTime(triggeredAtNum);\n const currentGainValue = this.audioNode.gain.value;\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, triggeredAtNum);\n // Exponential ramp to a tiny value\n this.audioNode.gain.exponentialRampToValueAtTime(\n 0.0001,\n triggeredAtNum + release - 0.0001,\n );\n }\n\n // Set to zero at the very end\n this.audioNode.gain.setValueAtTime(0, triggeredAtNum + release);\n }\n\n private scaledAttack() {\n return scaleToTen(this.props.attack);\n }\n\n private scaledDecay() {\n return scaleToFive(this.props.decay);\n }\n\n private scaledRelease() {\n return scaleToTen(this.props.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 { assertNever } from \"@blibliki/utils\";\nimport { IAnyAudioContext } from \"@/core\";\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: IAnyAudioContext) {\n await context.audioWorklet.addModule(scaleProcessorURL);\n await context.audioWorklet.addModule(filterProcessorURL);\n}\n\nexport function newAudioWorklet(\n context: IAnyAudioContext,\n worklet: CustomWorklet,\n) {\n switch (worklet) {\n case CustomWorklet.ScaleProcessor:\n return new AudioWorkletNode(context, \"scale-processor\");\n case CustomWorklet.FilterProcessor:\n return new AudioWorkletNode(context, \"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 { IAnyAudioContext, Module } from \"@/core\";\nimport { IModuleConstructor } from \"@/core/module/Module\";\nimport { IPolyModuleConstructor, PolyModule } from \"@/core/module/PolyModule\";\nimport { PropSchema } from \"@/core/schema\";\nimport { CustomWorklet, newAudioWorklet } from \"@/processors\";\nimport { createModule, ICreateModule, ModuleType } from \".\";\nimport { MonoGain } from \"./Gain\";\nimport Scale from \"./Scale\";\n\nexport type IFilterProps = {\n cutoff: number;\n envelopeAmount: number;\n resonance: number;\n};\n\nconst MIN_FREQ = 20;\nconst MAX_FREQ = 22050;\n\nconst DEFAULT_PROPS: IFilterProps = {\n cutoff: MAX_FREQ,\n envelopeAmount: 0,\n resonance: 0,\n};\n\nexport const filterPropSchema: PropSchema<IFilterProps> = {\n cutoff: {\n kind: \"number\",\n min: MIN_FREQ,\n max: MAX_FREQ,\n step: 0.0001,\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 resonance: {\n kind: \"number\",\n min: 0,\n max: 4,\n step: 0.01,\n label: \"resonance\",\n },\n};\n\nclass MonoFilter extends Module<ModuleType.Filter> {\n declare audioNode: AudioWorkletNode;\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: IAnyAudioContext) =>\n newAudioWorklet(context, CustomWorklet.FilterProcessor);\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.cutoff);\n\n this.registerDefaultIOs();\n this.registerInputs();\n }\n\n get cutoff() {\n return this.audioNode.parameters.get(\"cutoff\")!;\n }\n\n get resonance() {\n return this.audioNode.parameters.get(\"resonance\")!;\n }\n\n protected onSetCutoff(value: IFilterProps[\"cutoff\"]) {\n if (!this.superInitialized) return;\n\n this.scale.props = { current: value };\n }\n\n protected onSetResonance(value: IFilterProps[\"resonance\"]) {\n this.resonance.value = value;\n }\n\n protected onSetEnvelopeAmount(value: IFilterProps[\"envelopeAmount\"]) {\n if (!this.superInitialized) return;\n\n this.amount.props = { gain: value };\n }\n\n private registerInputs() {\n this.registerAudioInput({\n name: \"cutoff\",\n getAudioNode: () => this.scale.audioNode,\n });\n\n this.registerAudioInput({\n name: \"cutoffMod\",\n getAudioNode: () => this.amount.audioNode,\n });\n\n this.registerAudioInput({\n name: \"Q\",\n getAudioNode: () => this.resonance,\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 { IAnyAudioContext, IModule, Module } from \"@/core\";\nimport { PropSchema } 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: PropSchema<IInspectorProps> = {\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 extends Module<ModuleType.Inspector> {\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: IAnyAudioContext) =>\n new AnalyserNode(context);\n\n super(engineId, {\n ...params,\n props,\n audioNodeConstructor,\n });\n\n this.registerDefaultIOs(\"in\");\n }\n\n protected onSetFftSize(value: number) {\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 { EmptyObject } from \"@blibliki/utils\";\nimport { IAnyAudioContext, IModule, Module } from \"@/core\";\nimport { PropSchema } from \"@/core/schema\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IMaster = IModule<ModuleType.Master>;\nexport type IMasterProps = EmptyObject;\n\nconst DEFAULT_PROPS: IMasterProps = {};\n\nexport const masterPropSchema: PropSchema<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: IAnyAudioContext) =>\n context.destination;\n\n super(engineId, { ...params, audioNodeConstructor, props });\n\n this.registerDefaultIOs(\"in\");\n }\n}\n","import { IModule, Module, MidiOutput } from \"@/core\";\nimport MidiEvent from \"@/core/midi/MidiEvent\";\nimport { PropSchema } from \"@/core/schema\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IMidiSelector = IModule<ModuleType.MidiSelector>;\nexport type IMidiSelectorProps = {\n selectedId: string | undefined | null;\n};\n\nexport const midiSelectorPropSchema: PropSchema<IMidiSelectorProps> = {\n selectedId: {\n kind: \"string\",\n label: \"Midi device ID\",\n },\n};\n\nconst DEFAULT_PROPS: IMidiSelectorProps = { selectedId: undefined };\n\nexport default class MidiSelector extends Module<ModuleType.MidiSelector> {\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 this.addEventListener(this.props.selectedId);\n\n this.registerOutputs();\n }\n\n protected onSetSelectedId(value: string | null) {\n if (!this.superInitialized) return;\n\n this.removeEventListener();\n this.addEventListener(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(midiId: string | undefined | null) {\n if (!midiId) return;\n\n const midiDevice = this.engine.findMidiDevice(midiId);\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 { dbToGain } from \"@blibliki/utils\";\nimport { IAnyAudioContext, IModule, Module } from \"@/core\";\nimport Note from \"@/core/Note\";\nimport { nt, TTime } from \"@/core/Timing/Time\";\nimport { IModuleConstructor } from \"@/core/module/Module\";\nimport { IPolyModuleConstructor, PolyModule } from \"@/core/module/PolyModule\";\nimport { PropSchema } 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: PropSchema<IOscillatorProps> = {\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: -4,\n max: 4,\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\nexport class MonoOscillator extends Module<ModuleType.Oscillator> {\n declare audioNode: OscillatorNode;\n isStated = false;\n lowOutputGain: GainNode;\n detuneGain!: GainNode;\n\n constructor(engineId: string, params: ICreateModule<ModuleType.Oscillator>) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const audioNodeConstructor = (context: IAnyAudioContext) =>\n new OscillatorNode(context);\n\n super(engineId, {\n ...params,\n props,\n audioNodeConstructor,\n });\n\n this.lowOutputGain = new GainNode(this.context, {\n gain: dbToGain(LOW_GAIN),\n });\n\n this.applyOutputGain();\n this.initializeGainDetune();\n this.registerInputs();\n this.registerOutputs();\n }\n\n protected onAfterSetWave(value: OscillatorWave) {\n this.audioNode.type = value;\n }\n\n protected onAfterSetFrequency() {\n this.updateFrequency();\n }\n\n protected onAfterSetFine() {\n this.updateFrequency();\n }\n\n protected onAfterSetCoarse() {\n this.updateFrequency();\n }\n\n protected onAfterSetOctave() {\n this.updateFrequency();\n }\n\n protected onAfterSetLowGain() {\n if (!this.superInitialized) return;\n\n this.rePlugAll();\n }\n\n start(time: TTime) {\n if (this.isStated) return;\n\n this.isStated = true;\n this.audioNode.start(nt(time));\n }\n\n stop(time: TTime) {\n this.audioNode.stop(nt(time));\n this.rePlugAll(() => {\n this.audioNode = new OscillatorNode(this.context, {\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: TTime) => {\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: TTime) {\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 if (!this.superInitialized) return;\n\n const transposed =\n frequency * Math.pow(2, coarse / 12 + octave + fine / 12);\n return transposed;\n }\n\n private updateFrequency(actionAt?: TTime) {\n if (this.finalFrequency === undefined) return;\n\n if (actionAt) {\n this.audioNode.frequency.setValueAtTime(\n this.finalFrequency,\n nt(actionAt),\n );\n } else {\n this.audioNode.frequency.value = this.finalFrequency;\n }\n }\n\n private applyOutputGain() {\n this.audioNode.connect(this.lowOutputGain);\n }\n\n private initializeGainDetune() {\n this.detuneGain = new GainNode(this.context, { 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: () =>\n this.props.lowGain ? this.lowOutputGain : this.audioNode,\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: TTime) {\n this.audioModules.forEach((audioModule) => {\n audioModule.start(time);\n });\n }\n\n stop(time: TTime) {\n this.audioModules.forEach((audioModule) => {\n audioModule.stop(time);\n });\n }\n\n private registerInputs() {\n this.registerAudioInput({ name: \"detune\" });\n }\n}\n","import { IAnyAudioContext, IModule, Module } from \"@/core\";\nimport { PropSchema } 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: PropSchema<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 extends Module<ModuleType.Scale> {\n declare audioNode: AudioWorkletNode;\n\n constructor(engineId: string, params: ICreateModule<ModuleType.Scale>) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const audioNodeConstructor = (context: IAnyAudioContext) =>\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 protected onSetMin(value: number) {\n this.min.value = value;\n }\n\n protected onSetMax(value: number) {\n this.max.value = value;\n }\n\n protected onSetCurrent(value: number) {\n this.current.value = value;\n }\n}\n","import { INote, PropSchema, Module, IModule, MidiOutput } from \"@/core\";\nimport { BarsBeatsSixteenths } from \"@/core/Timing/Time\";\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: PropSchema<\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 { PropSchema, Module, IModule, MidiOutput, Note } from \"@/core\";\nimport { TTime } from \"@/core/Timing/Time\";\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: PropSchema<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: TTime) => {\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: TTime) => {\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":["assertDefined","pick","uuidv4","upperFirst","uuidv4","assertNever","deterministicId","uuidv4","PolyModule","engineId","params","id","name","moduleType","voices","monoModuleConstructor","props","uuidv4","InputCollection","OutputCollection","value","m","time","audioModule","from","to","output","input","callback","midiEvent","voiceNo","moduleByVoice","deterministicId","Engine","deterministicId","Base","module","props","deterministicId","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","assertNever","callback","id","name","InputCollection","OutputCollection","Message","frequencyTable","frequencyTable_default","Notes","MIDI_OCTAVE_SYTSTEM","Note","_Note","frequency","noteName","note","freq","frequencyTable_default","message","name","octave","noteOn","statusByte","string","matches","props","isNumber","InternalScheduler","Scheduler","transport","InternalScheduler","now","actionAt","callback","nt","currentTime","playhead","t","TransportState","Transport","props","t","Scheduler","offset","actionAt","now","time","now","Engine","browserToContextTime","time","differenceBetweenClocks","t","value","now","Time","nt","_Time","isNumber","count","factor","divisionsPerBeat","divisionsPerBar","secondsPerBeat","totalDivisions","bars","beats","divisions","beatsPerBar","sixteenths","totalBeats","Engine","MidiEvent","_MidiEvent","noteName","noteOn","triggeredAt","note","Note","Message","cc","value","message","t","voiceNo","newEvent","Module","engineId","params","id","name","moduleType","voiceNo","audioNodeConstructor","props","uuidv4","InputCollection","OutputCollection","value","key","onSetAttr","upperFirst","audioModule","from","to","output","input","callback","_time","note","_triggeredAt","n","midiEvent","triggeredAt","Engine","uuidv4","Routes","engine","props","id","route","sourceIO","destinationIO","source","destination","Output","WebMidi","MidiPortState","MidiDevice","input","id","name","state","callback","c","event","midiEvent","MidiEvent","browserToContextTime","MAP_KEYS","Note","computerKeyboardData","ComputerKeyboardInput","id","name","state","callback","c","noteOn","event","note","midiEvent","MidiEvent","MidiDeviceManager","computerKeyboardDevice","ComputerKeyboardInput","id","callback","WebMidi","input","MidiDevice","err","event","port","Output","device","listener","assertNever","voiceSchedulerPropSchema","DEFAULT_PROPS","Voice","Module","t","engineId","params","props","midiEvent","triggeredAt","note","type","noteName","VoiceScheduler","PolyModule","monoModuleConstructor","voice","v","a","b","nt","gainPropSchema","DEFAULT_PROPS","MonoGain","Module","engineId","params","props","audioNodeConstructor","context","value","Gain","PolyModule","monoModuleConstructor","MIN_FREQ","MAX_FREQ","DEFAULT_PROPS","biquadFilterPropSchema","MonoBiquadFilter","Module","engineId","params","props","audioNodeConstructor","context","MonoGain","createModule","value","BiquadFilter","PolyModule","monoModuleConstructor","constantPropSchema","DEFAULT_PROPS","Constant","Module","engineId","params","props","audioNodeConstructor","context","value","time","nt","note","triggeredAt","createScaleNormalized","DEFAULT_PROPS","envelopePropSchema","scaleToTen","createScaleNormalized","scaleToFive","MonoEnvelope","Module","engineId","params","props","audioNodeConstructor","context","audioNode","note","triggeredAt","attack","decay","sustain","triggeredAtNum","nt","release","currentGainValue","Envelope","PolyModule","monoModuleConstructor","assertNever","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","assertNever","MIN_FREQ","MAX_FREQ","DEFAULT_PROPS","filterPropSchema","MonoFilter","Module","engineId","params","props","audioNodeConstructor","context","newAudioWorklet","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","midiSelectorPropSchema","DEFAULT_PROPS","MidiSelector","Module","engineId","params","props","value","midiEvent","midiId","dbToGain","LOW_GAIN","OscillatorWave","oscillatorPropSchema","DEFAULT_PROPS","MonoOscillator","Module","engineId","params","props","audioNodeConstructor","context","dbToGain","value","time","nt","note","triggeredAt","lastNote","frequency","coarse","octave","fine","actionAt","Oscillator","PolyModule","monoModuleConstructor","audioModule","scalePropSchema","DEFAULT_PROPS","Scale","Module","engineId","params","props","audioNodeConstructor","context","newAudioWorklet","value","stepSequencerPropSchema","DEFAULT_PROPS","StepSequencer","Module","engineId","params","props","virtualMidiPropSchema","DEFAULT_PROPS","VirtualMidi","Module","engineId","params","props","midiEvent","note","triggerAttack","MidiEvent","name","ModuleType","moduleSchemas","oscillatorPropSchema","gainPropSchema","masterPropSchema","midiSelectorPropSchema","envelopePropSchema","filterPropSchema","biquadFilterPropSchema","scalePropSchema","inspectorPropSchema","constantPropSchema","virtualMidiPropSchema","stepSequencerPropSchema","voiceSchedulerPropSchema","createModule","engineId","params","Oscillator","Gain","Master","MidiSelector","Envelope","Filter","BiquadFilter","Scale","Inspector","Constant","VirtualMidi","StepSequencer","VoiceScheduler","assertNever","Engine","_Engine","id","engine","assertDefined","context","uuidv4","Transport","Routes","MidiDeviceManager","loadProcessors","params","module","createModule","updates","pick","PolyModule","props","source","destination","output","input","value","moduleId","ioName","type","callback","noteName","virtualMidi","MidiEvent","actionAt"]}
1
+ {"version":3,"sources":["../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/MidiEvent.ts","../src/core/Note/frequencyTable.ts","../src/core/Note/index.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/Gain.ts","../src/modules/BiquadFilter.ts","../src/modules/Constant.ts","../src/modules/Envelope.ts","../src/processors/index.ts","../src/processors/filter-processor.ts","../src/processors/scale-processor.ts","../src/modules/Filter.ts","../src/modules/Inspector.ts","../src/modules/Master.ts","../src/modules/MidiSelector.ts","../src/modules/Oscillator.ts","../src/modules/Scale.ts","../src/modules/StepSequencer.ts","../src/modules/VirtualMidi.ts","../src/index.ts"],"sourcesContent":["import {\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 { IRoute, Routes, MidiDeviceManager, IModule, MidiEvent } from \"@/core\";\nimport {\n ICreateModule,\n ModuleParams,\n ModuleType,\n ModuleTypeToModuleMapping,\n createModule,\n} from \"@/modules\";\nimport { PolyModule } 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 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>,\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 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 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 onPropsUpdate(callback: <T extends ModuleType>(params: IModule<T>) => void) {\n this.propsUpdateCallbacks.push(callback);\n }\n\n _triggerPropsUpdate<T extends ModuleType>(params: IModule<T>) {\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 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 superInitialized = false;\n protected activeNotes: Note[];\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 = {} as ModuleTypeToPropsMapping[T];\n this.props = props;\n\n this.inputs = new InputCollection(this);\n this.outputs = new OutputCollection(this);\n\n this.superInitialized = true;\n }\n\n get props(): ModuleTypeToPropsMapping[T] {\n return this._props;\n }\n\n set props(value: Partial<ModuleTypeToPropsMapping[T]>) {\n Object.keys(value).forEach((key) => {\n const onSetAttr = `onSet${upperFirst(key)}`;\n\n // @ts-expect-error TS7053 ignore this error\n // eslint-disable-next-line\n this[onSetAttr]?.(value[key]);\n });\n\n this._props = { ...this._props, ...value };\n\n Object.keys(value).forEach((key) => {\n const onSetAttr = `onAfterSet${upperFirst(key)}`;\n\n // @ts-expect-error TS7053 ignore this error\n // eslint-disable-next-line\n this[onSetAttr]?.(value[key]);\n });\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 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 default:\n throw Error(\"This type is not a note\");\n }\n };\n\n protected triggerPropsUpdate() {\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 }\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 { 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 this.collection.map((io) => io.serialize());\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 protected superInitialized = false;\n private _voices!: number;\n private _name!: string;\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.voices = voices || 1;\n this._props = {} as ModuleTypeToPropsMapping[T];\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 this.superInitialized = true;\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 if (!this.superInitialized) return;\n\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 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","import { ContextTime } from \"@blibliki/transport\";\nimport { Message } from \"webmidi\";\nimport Note, { INote } from \"../Note\";\n\nexport enum MidiEventType {\n noteOn = \"noteon\",\n noteOff = \"noteoff\",\n cc = \"cc\",\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 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","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 \"webmidi\";\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 { 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 for (const id in this.routes) {\n this.removeRoute(id);\n }\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 { Input, Output, WebMidi } from \"webmidi\";\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\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 addListener(callback: ListenerCallback) {\n this.listeners.push(callback);\n }\n\n private async initializeDevices() {\n if (this.initialized) return;\n\n try {\n await WebMidi.enable();\n\n WebMidi.inputs.forEach((input) => {\n if (!this.devices.has(input.id)) {\n this.devices.set(input.id, new MidiDevice(input, this.context));\n }\n });\n } catch (err) {\n console.error(\"Error enabling WebMidi:\", 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 WebMidi.addListener(\"connected\", (event) => {\n const port = event.port as Input | Output;\n if (port instanceof Output) return;\n\n if (this.devices.has(port.id)) return;\n\n const device = new MidiDevice(port, this.context);\n this.devices.set(device.id, device);\n\n this.listeners.forEach((listener) => {\n listener(device);\n });\n });\n\n WebMidi.addListener(\"disconnected\", (event) => {\n const port = event.port as Input | Output;\n if (port instanceof Output) return;\n\n const device = this.devices.get(port.id);\n if (!device) return;\n if (device instanceof ComputerKeyboardDevice) return;\n\n device.disconnect();\n this.devices.delete(device.id);\n\n this.listeners.forEach((listener) => {\n listener(device);\n });\n });\n }\n}\n","import { Context } from \"@blibliki/utils\";\nimport { MessageEvent, Input } from \"webmidi\";\nimport MidiEvent, { MidiEventType } from \"./MidiEvent\";\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: Input;\n\n constructor(input: Input, context: Context) {\n this.id = input.id;\n this.name = input.name || `Device ${input.id}`;\n this.input = input;\n this.context = context;\n\n this.connect();\n }\n\n get state() {\n return this.input.state as MidiPortState;\n }\n\n connect() {\n this.input.addListener(\"midimessage\", (e: MessageEvent) => {\n this.processEvent(e);\n });\n }\n\n disconnect() {\n this.input.removeListener();\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(event: MessageEvent) {\n const midiEvent = new MidiEvent(\n event.message,\n this.context.browserToContextTime(event.timestamp),\n );\n\n switch (midiEvent.type) {\n case MidiEventType.noteOn:\n case MidiEventType.noteOff:\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, PropSchema } from \"@/core\";\nimport { IPolyModuleConstructor } from \"@/core/module/PolyModule\";\nimport VoiceScheduler, {\n IVoiceSchedulerProps,\n voiceSchedulerPropSchema,\n} from \"@/core/module/VoiceScheduler\";\nimport BiquadFilter, {\n biquadFilterPropSchema,\n IBiquadFilterProps,\n} from \"./BiquadFilter\";\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 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 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 BiquadFilter = \"BiquadFilter\",\n Scale = \"Scale\",\n Inspector = \"Inspector\",\n Constant = \"Constant\",\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.BiquadFilter]: IBiquadFilterProps;\n [ModuleType.Scale]: IScaleProps;\n [ModuleType.Inspector]: IInspectorProps;\n [ModuleType.Constant]: IConstantProps;\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.BiquadFilter]: BiquadFilter;\n [ModuleType.Scale]: Scale;\n [ModuleType.Inspector]: Inspector;\n [ModuleType.Constant]: Constant;\n [ModuleType.VirtualMidi]: VirtualMidi;\n [ModuleType.StepSequencer]: StepSequencer;\n [ModuleType.VoiceScheduler]: VoiceScheduler;\n};\n\nexport const moduleSchemas: {\n [K in ModuleType]: PropSchema<Partial<ModuleTypeToPropsMapping[K]>>;\n} = {\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.BiquadFilter]: biquadFilterPropSchema,\n [ModuleType.Scale]: scalePropSchema,\n [ModuleType.Inspector]: inspectorPropSchema,\n [ModuleType.Constant]: constantPropSchema,\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 {\n IStepSequencer,\n IStepSequencerProps,\n ISequence,\n} from \"./StepSequencer\";\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.BiquadFilter\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.BiquadFilter:\n return new BiquadFilter(engineId, params);\n case ModuleType.Scale:\n return new Scale(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.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 { PropSchema } from \"../schema\";\nimport { IModuleConstructor, Module } from \"./Module\";\nimport { IPolyModuleConstructor, PolyModule } from \"./PolyModule\";\n\nexport type IVoiceSchedulerProps = EmptyObject;\nexport const voiceSchedulerPropSchema: PropSchema<IVoiceSchedulerProps> = {};\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 { Context } from \"@blibliki/utils\";\nimport { IModule, Module } from \"@/core\";\nimport { IModuleConstructor } from \"@/core/module/Module\";\nimport { IPolyModuleConstructor, PolyModule } from \"@/core/module/PolyModule\";\nimport { PropSchema } from \"@/core/schema\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IGain = IModule<ModuleType.Gain>;\nexport type IGainProps = {\n gain: number;\n};\n\nexport const gainPropSchema: PropSchema<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 extends Module<ModuleType.Gain> {\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 protected onSetGain(value: IGainProps[\"gain\"]) {\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 { IModuleConstructor, Module } from \"@/core/module/Module\";\nimport { IPolyModuleConstructor, PolyModule } from \"@/core/module/PolyModule\";\nimport { PropSchema } from \"@/core/schema\";\nimport { createModule, ICreateModule, ModuleType } from \".\";\nimport { MonoGain } from \"./Gain\";\nimport Scale from \"./Scale\";\n\nexport type IBiquadFilterProps = {\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: IBiquadFilterProps = {\n cutoff: MAX_FREQ,\n envelopeAmount: 0,\n type: \"lowpass\",\n Q: 1,\n};\n\nexport const biquadFilterPropSchema: PropSchema<IBiquadFilterProps> = {\n cutoff: {\n kind: \"number\",\n min: MIN_FREQ,\n max: MAX_FREQ,\n step: 1,\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: -100,\n max: 100,\n step: 0.1,\n label: \"Q\",\n },\n};\n\nclass MonoBiquadFilter extends Module<ModuleType.BiquadFilter> {\n declare audioNode: BiquadFilterNode;\n private scale: Scale;\n private amount: MonoGain;\n\n constructor(\n engineId: string,\n params: ICreateModule<ModuleType.BiquadFilter>,\n ) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n\n const audioNodeConstructor = (context: Context) =>\n new BiquadFilterNode(context.audioContext, {\n type: props.type,\n frequency: props.cutoff,\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 protected onSetType(value: IBiquadFilterProps[\"type\"]) {\n this.audioNode.type = value;\n }\n\n protected onSetCutoff(value: IBiquadFilterProps[\"cutoff\"]) {\n if (!this.superInitialized) return;\n\n this.scale.props = { current: value };\n }\n\n protected onSetQ(value: IBiquadFilterProps[\"Q\"]) {\n this.audioNode.Q.value = value;\n }\n\n protected onSetEnvelopeAmount(value: IBiquadFilterProps[\"envelopeAmount\"]) {\n if (!this.superInitialized) return;\n\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 BiquadFilter extends PolyModule<ModuleType.BiquadFilter> {\n constructor(\n engineId: string,\n params: IPolyModuleConstructor<ModuleType.BiquadFilter>,\n ) {\n const props = { ...DEFAULT_PROPS, ...params.props };\n const monoModuleConstructor = (\n engineId: string,\n params: IModuleConstructor<ModuleType.BiquadFilter>,\n ) => new MonoBiquadFilter(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 { ContextTime } from \"@blibliki/transport\";\nimport { Context } from \"@blibliki/utils\";\nimport { IModule, Module } from \"@/core\";\nimport Note from \"@/core/Note\";\nimport { PropSchema } from \"@/core/schema\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IConstant = IModule<ModuleType.Constant>;\nexport type IConstantProps = {\n value: number;\n};\n\nexport const constantPropSchema: PropSchema<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 extends Module<ModuleType.Constant> {\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 protected onSetValue(value: IConstantProps[\"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 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, createScaleNormalized } 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 { PropSchema } 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.1,\n decay: 0.2,\n sustain: 0,\n release: 0.3,\n};\n\nexport const envelopePropSchema: PropSchema<IEnvelopeProps> = {\n attack: {\n kind: \"number\",\n min: 0.0001,\n max: 1,\n step: 0.01,\n label: \"Attack\",\n },\n decay: {\n kind: \"number\",\n min: 0,\n max: 1,\n step: 0.01,\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: 1,\n step: 0.01,\n label: \"Release\",\n },\n};\n\nconst scaleToTen = createScaleNormalized({\n min: 0.001,\n max: 10,\n});\n\nconst scaleToFive = createScaleNormalized({\n min: 0.001,\n max: 5,\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.scaledAttack();\n const decay = this.scaledDecay();\n const sustain = this.props.sustain;\n\n this.audioNode.gain.cancelAndHoldAtTime(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.scaledRelease();\n\n // Cancel scheduled automations and set gain to the ACTUAL value at this moment\n this.audioNode.gain.cancelAndHoldAtTime(triggeredAt);\n const currentGainValue = this.audioNode.gain.value;\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 private scaledAttack() {\n return scaleToTen(this.props.attack);\n }\n\n private scaledDecay() {\n return scaleToFive(this.props.decay);\n }\n\n private scaledRelease() {\n return scaleToTen(this.props.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 { 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 { Module } from \"@/core\";\nimport { IModuleConstructor } from \"@/core/module/Module\";\nimport { IPolyModuleConstructor, PolyModule } from \"@/core/module/PolyModule\";\nimport { PropSchema } from \"@/core/schema\";\nimport { CustomWorklet, newAudioWorklet } from \"@/processors\";\nimport { createModule, ICreateModule, ModuleType } from \".\";\nimport { MonoGain } from \"./Gain\";\nimport Scale from \"./Scale\";\n\nexport type IFilterProps = {\n cutoff: number;\n envelopeAmount: number;\n resonance: number;\n};\n\nconst MIN_FREQ = 20;\nconst MAX_FREQ = 22050;\n\nconst DEFAULT_PROPS: IFilterProps = {\n cutoff: MAX_FREQ,\n envelopeAmount: 0,\n resonance: 0,\n};\n\nexport const filterPropSchema: PropSchema<IFilterProps> = {\n cutoff: {\n kind: \"number\",\n min: MIN_FREQ,\n max: MAX_FREQ,\n step: 0.0001,\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 resonance: {\n kind: \"number\",\n min: 0,\n max: 4,\n step: 0.01,\n label: \"resonance\",\n },\n};\n\nclass MonoFilter extends Module<ModuleType.Filter> {\n declare audioNode: AudioWorkletNode;\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 newAudioWorklet(context, CustomWorklet.FilterProcessor);\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.cutoff);\n\n this.registerDefaultIOs();\n this.registerInputs();\n }\n\n get cutoff() {\n return this.audioNode.parameters.get(\"cutoff\")!;\n }\n\n get resonance() {\n return this.audioNode.parameters.get(\"resonance\")!;\n }\n\n protected onSetCutoff(value: IFilterProps[\"cutoff\"]) {\n if (!this.superInitialized) return;\n\n this.scale.props = { current: value };\n }\n\n protected onSetResonance(value: IFilterProps[\"resonance\"]) {\n this.resonance.value = value;\n }\n\n protected onSetEnvelopeAmount(value: IFilterProps[\"envelopeAmount\"]) {\n if (!this.superInitialized) return;\n\n this.amount.props = { gain: value };\n }\n\n private registerInputs() {\n this.registerAudioInput({\n name: \"cutoff\",\n getAudioNode: () => this.scale.audioNode,\n });\n\n this.registerAudioInput({\n name: \"cutoffMod\",\n getAudioNode: () => this.amount.audioNode,\n });\n\n this.registerAudioInput({\n name: \"Q\",\n getAudioNode: () => this.resonance,\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 } from \"@/core\";\nimport { PropSchema } 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: PropSchema<IInspectorProps> = {\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 extends Module<ModuleType.Inspector> {\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 protected onSetFftSize(value: number) {\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 } from \"@/core\";\nimport { PropSchema } from \"@/core/schema\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IMaster = IModule<ModuleType.Master>;\nexport type IMasterProps = EmptyObject;\n\nconst DEFAULT_PROPS: IMasterProps = {};\n\nexport const masterPropSchema: PropSchema<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 { IModule, Module, MidiOutput } from \"@/core\";\nimport MidiEvent from \"@/core/midi/MidiEvent\";\nimport { PropSchema } from \"@/core/schema\";\nimport { ICreateModule, ModuleType } from \".\";\n\nexport type IMidiSelector = IModule<ModuleType.MidiSelector>;\nexport type IMidiSelectorProps = {\n selectedId: string | undefined | null;\n};\n\nexport const midiSelectorPropSchema: PropSchema<IMidiSelectorProps> = {\n selectedId: {\n kind: \"string\",\n label: \"Midi device ID\",\n },\n};\n\nconst DEFAULT_PROPS: IMidiSelectorProps = { selectedId: undefined };\n\nexport default class MidiSelector extends Module<ModuleType.MidiSelector> {\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 this.addEventListener(this.props.selectedId);\n\n this.registerOutputs();\n }\n\n protected onSetSelectedId(value: string | null) {\n if (!this.superInitialized) return;\n\n this.removeEventListener();\n this.addEventListener(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(midiId: string | undefined | null) {\n if (!midiId) return;\n\n const midiDevice = this.engine.findMidiDevice(midiId);\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 } from \"@/core/module/Module\";\nimport { IPolyModuleConstructor, PolyModule } from \"@/core/module/PolyModule\";\nimport { PropSchema } 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: PropSchema<IOscillatorProps> = {\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: -4,\n max: 4,\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\nexport class MonoOscillator extends Module<ModuleType.Oscillator> {\n declare audioNode: OscillatorNode;\n isStated = false;\n lowOutputGain: 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.lowOutputGain = 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 protected onAfterSetWave(value: OscillatorWave) {\n this.audioNode.type = value;\n }\n\n protected onAfterSetFrequency() {\n this.updateFrequency();\n }\n\n protected onAfterSetFine() {\n this.updateFrequency();\n }\n\n protected onAfterSetCoarse() {\n this.updateFrequency();\n }\n\n protected onAfterSetOctave() {\n this.updateFrequency();\n }\n\n protected onAfterSetLowGain() {\n if (!this.superInitialized) return;\n\n this.rePlugAll();\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 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 if (!this.superInitialized) return;\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.lowOutputGain);\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: () =>\n this.props.lowGain ? this.lowOutputGain : this.audioNode,\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 { Context } from \"@blibliki/utils\";\nimport { IModule, Module } from \"@/core\";\nimport { PropSchema } 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: PropSchema<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 extends Module<ModuleType.Scale> {\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 protected onSetMin(value: number) {\n this.min.value = value;\n }\n\n protected onSetMax(value: number) {\n this.max.value = value;\n }\n\n protected onSetCurrent(value: number) {\n this.current.value = value;\n }\n}\n","import { INote, PropSchema, Module, IModule, MidiOutput } 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: PropSchema<\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 { ContextTime } from \"@blibliki/transport\";\nimport { PropSchema, Module, IModule, MidiOutput, Note } 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: PropSchema<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","export { Engine } from \"./Engine\";\nexport type { ICreateRoute, IUpdateModule } from \"./Engine\";\n\nexport type {\n IRoute,\n IIOSerialize,\n IModule,\n IModuleSerialize,\n IPolyModuleSerialize,\n IMidiDevice,\n PropDefinition,\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 { ModuleType, moduleSchemas, OscillatorWave } from \"./modules\";\nexport type {\n IOscillator,\n IGain,\n IMaster,\n ISequence,\n IStepSequencerProps,\n IStepSequencer,\n ModuleTypeToPropsMapping,\n ICreateModule,\n ModuleParams,\n} from \"./modules\";\n"],"mappings":"AAAA,OAIE,aAAAA,OAEK,sBACP,OACE,iBAAAC,GAGA,QAAAC,GACA,UAAAC,OACK,kBCZP,OAA4B,cAAAC,GAAY,UAAAC,OAAc,kBCDtD,OAAS,eAAAC,OAAmB,kBCC5B,OAAS,mBAAAC,GAA2B,UAAAC,OAAc,kBAkC3C,IAAeC,EAAf,KAEP,CACE,GACA,SACA,WACA,aACA,OACA,QACU,sBACA,OACA,iBAAmB,GACrB,QACA,MAER,YAAYC,EAAkBC,EAAmC,CAC/D,GAAM,CAAE,GAAAC,EAAI,KAAAC,EAAM,WAAAC,EAAY,OAAAC,EAAQ,sBAAAC,EAAuB,MAAAC,CAAM,EACjEN,EAEF,KAAK,aAAe,CAAC,EAErB,KAAK,sBAAwBK,EAC7B,KAAK,GAAKJ,GAAMM,GAAO,EACvB,KAAK,SAAWR,EAChB,KAAK,KAAOG,EACZ,KAAK,WAAaC,EAClB,KAAK,OAASC,GAAU,EACxB,KAAK,OAAS,CAAC,EACf,KAAK,MAAQE,EAEb,KAAK,OAAS,IAAIE,EAChB,IACF,EACA,KAAK,QAAU,IAAIC,EACjB,IACF,EAEA,KAAK,iBAAmB,EAC1B,CAEA,IAAI,MAAO,CACT,OAAO,KAAK,KACd,CAEA,IAAI,KAAKC,EAAe,CACtB,KAAK,MAAQA,EACb,KAAK,aAAa,QAASC,GAAOA,EAAE,KAAOD,CAAM,CACnD,CAEA,IAAI,OAAqC,CACvC,OAAO,KAAK,MACd,CAEA,IAAI,MAAMA,EAA6C,CACrD,KAAK,OAAS,CAAE,GAAG,KAAK,OAAQ,GAAGA,CAAM,EACzC,KAAK,aAAa,QAASC,GAAOA,EAAE,MAAQD,CAAM,CACpD,CAEA,IAAI,QAAS,CACX,OAAO,KAAK,OACd,CAEA,IAAI,OAAOA,EAAe,CACxB,KAAK,QAAUA,EACf,KAAK,sBAAsB,EAC3B,KAAK,UAAU,CACjB,CAEA,MAAME,EAAyB,CAC7B,KAAK,aAAa,QAASD,GAAM,CAC/BA,EAAE,MAAMC,CAAI,CACd,CAAC,CACH,CAEA,KAAKA,EAAyB,CAC5B,KAAK,aAAa,QAASD,GAAM,CAC/BA,EAAE,KAAKC,CAAI,CACb,CAAC,CACH,CAEA,WAAqC,CACnC,MAAO,CACL,GAAI,KAAK,GACT,KAAM,KAAK,KACX,WAAY,KAAK,WACjB,OAAQ,KAAK,OACb,MAAO,KAAK,MACZ,OAAQ,KAAK,OAAO,UAAU,EAC9B,QAAS,KAAK,QAAQ,UAAU,CAClC,CACF,CAEA,KAAK,CACH,YAAAC,EACA,KAAAC,EACA,GAAAC,CACF,EAIG,CACD,IAAMC,EAAS,KAAK,QAAQ,WAAWF,CAAI,EACrCG,EAAQJ,EAAY,OAAO,WAAWE,CAAE,EAE9CC,EAAO,KAAKC,CAAK,CACnB,CAEA,UAAUC,EAAuB,CAC1B,KAAK,mBAEV,KAAK,OAAO,UAAUA,CAAQ,EAC9B,KAAK,QAAQ,UAAUA,CAAQ,EACjC,CAEU,WAAY,CACpB,KAAK,OAAO,UAAU,EACtB,KAAK,QAAQ,UAAU,CACzB,CAEA,SAAU,CACR,KAAK,OAAO,UAAU,EACtB,KAAK,QAAQ,UAAU,EACvB,KAAK,aAAa,QAASP,GAAM,CAC/BA,EAAE,QAAQ,CACZ,CAAC,CACH,CAEA,YAAeQ,GAAyB,CACtC,IAAMC,EAAUD,EAAU,SAAW,EACjB,KAAK,UAAUC,CAAO,EAC9B,YAAYD,CAAS,CACnC,EAEA,UAAUC,EAAiB,CACzB,IAAMC,EAAgB,KAAK,aAAa,KAAMV,GAAMA,EAAE,UAAYS,CAAO,EACzE,GAAI,CAACC,EACH,MAAM,MAAM,SAASD,CAAO,cAAc,KAAK,IAAI,YAAY,EAEjE,OAAOC,CACT,CAEU,mBAAmBX,EAA+B,OAAQ,CAClE,KAAK,kBAAkB,CACrB,KAAM,UACN,YAAa,KAAK,WACpB,CAAC,GAEGA,IAAU,MAAQA,IAAU,SAC9B,KAAK,mBAAmB,CACtB,KAAM,IACR,CAAC,GAGCA,IAAU,OAASA,IAAU,SAC/B,KAAK,oBAAoB,CACvB,KAAM,KACR,CAAC,CAEL,CAEU,mBAAmBJ,EAA4C,CACvE,OAAO,KAAK,OAAO,IAAI,CAAE,GAAGA,EAAO,uBAA8B,CAAC,CACpE,CAEU,oBAAoBA,EAA6C,CACzE,OAAO,KAAK,QAAQ,IAAI,CAAE,GAAGA,EAAO,wBAA+B,CAAC,CACtE,CAEU,kBAAkBA,EAAuC,CACjE,OAAO,KAAK,OAAO,IAAI,CAAE,GAAGA,EAAO,kBAAyB,CAAC,CAC/D,CAEU,mBAAmBA,EAAwC,CACnE,OAAO,KAAK,QAAQ,IAAI,CACtB,GAAGA,EACH,mBACF,CAAC,CACH,CAEQ,uBAAwB,CAC9B,GAAI,KAAK,aAAa,SAAW,KAAK,OAEtC,IAAI,KAAK,aAAa,OAAS,KAAK,OACd,KAAK,aAAa,IAAI,GAC7B,QAAQ,MAChB,CACL,IAAMc,EAAU,KAAK,aAAa,OAC5BnB,EAAKqB,GAAgB,KAAK,GAAIF,EAAQ,SAAS,CAAC,EAEhDP,EAAc,KAAK,sBAAsB,KAAK,SAAU,CAC5D,GAAAZ,EACA,KAAM,KAAK,KACX,WAAY,KAAK,WACjB,QAAAmB,EACA,MAAO,CAAE,GAAG,KAAK,KAAM,CACzB,CAAC,EAED,KAAK,aAAa,KAAKP,CAAW,CACpC,CAEA,KAAK,sBAAsB,EAC7B,CAEA,IAAc,QAAS,CACrB,OAAOU,EAAO,QAAQ,KAAK,QAAQ,CACrC,CAEA,IAAc,SAAU,CACtB,OAAO,KAAK,OAAO,OACrB,CACF,ECrPA,OAAS,mBAAAC,OAAuB,kBAgCzB,IAAeC,GAAf,KAAmC,CACxC,GACA,OACA,KACA,OACA,YAEA,YACEC,EACAC,EACA,CACA,KAAK,OAASD,EACd,KAAK,KAAOC,EAAM,KAClB,KAAK,OAASA,EAAM,OACpB,KAAK,GAAKC,GAAgB,KAAK,OAAO,GAAI,KAAK,IAAI,EACnD,KAAK,YAAc,CAAC,CACtB,CAEA,KAAKC,EAAUC,EAAY,GAAM,CAC/B,KAAK,YAAY,KAAKD,CAAE,EACpBC,GAAWD,EAAG,KAAK,KAAM,EAAK,CACpC,CAEA,OAAOA,EAAUC,EAAY,GAAM,CACjC,KAAK,YAAc,KAAK,YAAY,OACjCC,GAAcA,EAAU,KAAOF,EAAG,EACrC,EACIC,GAAWD,EAAG,OAAO,KAAM,EAAK,CACtC,CAEA,UAAUG,EAAuB,CAC/B,IAAMC,EAAc,KAAK,YACzB,KAAK,UAAU,EACXD,GAAUA,EAAS,EAEvBC,EAAY,QAASC,GAAY,CAC/B,KAAK,KAAKA,CAAO,CACnB,CAAC,CACH,CAEA,WAAY,CACV,KAAK,YAAY,QAASA,GAAY,CACpC,KAAK,OAAOA,CAAO,CACrB,CAAC,CACH,CAEA,SAIoB,CAClB,OACE,KAAK,SAAW,cAChB,KAAK,SAAW,eAChB,KAAK,SAAW,kBAChB,KAAK,SAAW,iBAEpB,CAEA,QAAyC,CACvC,OACE,KAAK,SAAW,aAAoB,KAAK,SAAW,YAExD,CAEA,WAA0B,CACxB,MAAO,CACL,GAAI,KAAK,GACT,KAAM,KAAK,KACX,OAAQ,KAAK,OACb,SAAU,KAAK,OAAO,EACxB,CACF,CACF,EAE8BC,EAA9B,cAAkEV,EAAK,CAGrE,KAAKI,EAAgBC,EAA2B,CAC9C,MAAM,KAAKD,EAAIC,CAAS,CAC1B,CAEA,OAAOD,EAAgBC,EAA2B,CAChD,MAAM,OAAOD,EAAIC,CAAS,CAC5B,CACF,ECtGO,IAAMM,EAAN,cACGC,CAEV,CAIE,KAAKC,EAAmCC,EAAY,GAAM,CACxD,MAAM,KAAKD,EAAIC,CAAS,EACpB,GAACA,GAAaD,aAAcE,IAEhCC,EAAa,KAAMH,EAAI,EAAI,CAC7B,CAEA,OAAOA,EAAmCC,EAAY,GAAM,CAC1D,MAAM,OAAOD,EAAIC,CAAS,EACtB,GAACA,GAAaD,aAAcE,IAEhCC,EAAa,KAAMH,EAAI,EAAK,CAC9B,CAEA,cAAcI,EAA2B,CACvC,OAAO,KAAK,OACT,UAAUA,CAAK,EACf,OAAO,WAAW,KAAK,IAAI,CAChC,CACF,EAEaF,EAAN,cACGH,CAEV,CAIE,KAAKC,EAAiCC,EAAY,GAAM,CACtD,MAAM,KAAKD,EAAIC,CAAS,EACpB,GAACA,GAAaD,aAAcF,IAEhCK,EAAa,KAAMH,EAAI,EAAI,CAC7B,CAEA,OAAOA,EAAiCC,EAAY,GAAM,CACxD,MAAM,OAAOD,EAAIC,CAAS,EACtB,GAACA,GAAaD,aAAcF,IAEhCK,EAAa,KAAMH,EAAI,EAAK,CAC9B,CAEA,cAAcI,EAA4B,CACxC,OAAO,KAAK,OACT,UAAUA,CAAK,EACf,QAAQ,WAAW,KAAK,IAAI,CACjC,CACF,EAYA,SAASD,EACPE,EACAC,EACAC,EACA,CACA,GAAID,aAAmBR,GAAkBQ,aAAmBJ,EAAiB,CAC3E,IAAMM,EAAY,KAAK,IAAIH,EAAO,OAAO,OAAQC,EAAQ,OAAO,MAAM,EAEtE,QAASF,EAAQ,EAAGA,EAAQI,EAAWJ,IAAS,CAC9C,IAAMK,EAAaJ,EAAO,cAAcD,EAAQC,EAAO,OAAO,MAAM,EAC9DK,EAAcJ,EAAQ,cAAcF,EAAQE,EAAQ,OAAO,MAAM,EAEnEC,EAEFE,EAAW,KAAKC,CAAW,EAG3BD,EAAW,OAAOC,CAAW,CAEjC,CACF,KACE,SAASN,EAAQ,EAAGA,EAAQC,EAAO,OAAO,OAAQD,IAAS,CACzD,IAAMK,EAAaJ,EAAO,cAAcD,CAAK,EAEzCG,EAEFE,EAAW,KAAKH,CAAO,EAGvBG,EAAW,OAAOH,CAAO,CAE7B,CAEJ,CCjGO,IAAMK,EAAN,cACGC,CAEV,CAEE,aAEA,YAAYC,EAA4BC,EAAwB,CAC9D,MAAMD,EAAQC,CAAK,EACnB,KAAK,aAAeA,EAAM,YAC5B,CACF,EAEaC,EAAN,cACGH,CAEV,CAEE,aAEA,YAAYC,EAA4BC,EAAyB,CAC/D,MAAMD,EAAQC,CAAK,EACnB,KAAK,aAAeA,EAAM,YAC5B,CAEA,KAAKE,EAAiCC,EAAY,GAAM,CAEtD,GADA,MAAM,KAAKD,EAAIC,CAAS,EACpBD,aAAcE,EAAgB,OAElC,IAAMC,EAAQH,EAAG,aAAa,EAE1BG,aAAiB,WACnB,KAAK,aAAa,EAAE,QAAQA,CAAK,EAEjC,KAAK,aAAa,EAAE,QAAQA,CAAK,CAErC,CAEA,OAAOH,EAAiCC,EAAY,GAAM,CAExD,GADA,MAAM,OAAOD,EAAIC,CAAS,EACtBD,aAAcE,EAAgB,OAElC,IAAMC,EAAQH,EAAG,aAAa,EAE9B,GAAI,CACEG,aAAiB,WACnB,KAAK,aAAa,EAAE,WAAWA,CAAK,EAEpC,KAAK,aAAa,EAAE,WAAWA,CAAK,CAExC,MAAQ,CAER,CACF,CACF,ECtDO,IAAMC,EAAN,cAAwBC,CAAyC,CAEtE,YAEA,YACEC,EACAC,EACA,CACA,MAAMD,EAAQC,CAAK,EACnB,KAAK,YAAcA,EAAM,WAC3B,CACF,EAEaC,EAAN,cAAyBH,CAAyC,CAGvE,YAAeI,GAAqB,CAClC,KAAK,gBAAgB,QAASC,GAAU,CACtCA,EAAM,YAAYD,CAAK,CACzB,CAAC,CACH,EAEA,IAAY,iBAAkB,CAC5B,OAAO,KAAK,YAAY,OAAQC,GAAUA,aAAiBN,CAAS,CACtE,CACF,ELOA,IAA8BO,EAA9B,KAAqE,CACnE,OACA,WAAqB,CAAC,EACtB,eAEA,YACEC,EACAC,EACA,CACA,KAAK,eAAiBD,EACtB,KAAK,OAASC,CAChB,CAEA,IAAkCC,EAAyC,CACzE,IAAIC,EASJ,OAFA,KAAK,iBAAiBD,EAAM,IAAI,EAExBA,EAAM,OAAQ,CACpB,iBACE,GAAI,KAAK,kBAAkBE,EAAY,MAAM,MAAM,gBAAgB,EACnED,EAAK,IAAIE,EAAW,KAAK,OAAQH,CAAK,EACtC,MACF,kBACE,GAAI,KAAK,kBAAkBE,EAAY,MAAM,MAAM,gBAAgB,EACnED,EAAK,IAAIG,EAAY,KAAK,OAAQJ,CAAK,EACvC,MACF,qBACE,GAAI,KAAK,kBAAkBK,EAAQ,MAAM,MAAM,gBAAgB,EAC/DJ,EAAK,IAAIK,EAAe,KAAK,OAAQN,CAAK,EAC1C,MACF,sBACE,GAAI,KAAK,kBAAkBK,EAAQ,MAAM,MAAM,gBAAgB,EAC/DJ,EAAK,IAAIM,EAAgB,KAAK,OAAQP,CAAK,EAC3C,MACF,gBACEC,EAAK,IAAIO,EAAU,KAAK,OAAQR,CAAK,EACrC,MACF,iBACEC,EAAK,IAAIQ,EAAW,KAAK,OAAQT,CAAK,EACtC,MACF,QACEU,GAAYV,CAAK,CACrB,CAEA,YAAK,WAAW,KAAKC,CAAE,EAEhBA,CACT,CAEA,WAAY,CACV,KAAK,WAAW,QAASA,GAAO,CAC9BA,EAAG,UAAU,CACf,CAAC,CACH,CAEA,UAAUU,EAAuB,CAC/B,KAAK,WAAW,QAASV,GAAO,CAC9BA,EAAG,UAAUU,CAAQ,CACvB,CAAC,CACH,CAEA,KAAKC,EAAY,CACf,IAAMX,EAAK,KAAK,WAAW,KAAMA,GAAOA,EAAG,KAAOW,CAAE,EACpD,GAAI,CAACX,EAAI,MAAM,MAAM,kBAAkBW,CAAE,gBAAgB,EAEzD,OAAOX,CACT,CAEA,WAAWY,EAAc,CACvB,IAAMZ,EAAK,KAAK,WAAW,KAAMA,GAAOA,EAAG,OAASY,CAAI,EACxD,GAAI,CAACZ,EAAI,MAAM,MAAM,oBAAoBY,CAAI,gBAAgB,EAE7D,OAAOZ,CACT,CAEA,WAAY,CACV,OAAO,KAAK,WAAW,IAAKA,GAAOA,EAAG,UAAU,CAAC,CACnD,CAEQ,iBAAiBY,EAAc,CACrC,GAAI,KAAK,WAAW,KAAMZ,GAAOA,EAAG,OAASY,CAAI,EAC/C,MAAM,MAAM,mBAAmBA,CAAI,oBAAoB,CAE3D,CACF,EAEaC,EAAN,cAA8BjB,CAAmC,CACtE,YAAYE,EAAqD,CAC/D,MAAM,QAAsBA,CAAM,CACpC,CACF,EAEagB,EAAN,cAA+BlB,CAAoC,CACxE,YAAYE,EAAqD,CAC/D,MAAM,SAAuBA,CAAM,CACrC,CACF,EMtJA,OAAS,WAAAiB,OAAe,UCDxB,IAAMC,GAAiB,IAAI,IAAoB,CAC7C,CAAC,KAAM,KAAK,EACZ,CAAC,MAAO,KAAK,EACb,CAAC,MAAO,KAAK,EACb,CAAC,KAAM,KAAK,EACZ,CAAC,MAAO,KAAK,EACb,CAAC,MAAO,KAAK,EACb,CAAC,KAAM,IAAI,EACX,CAAC,KAAM,KAAK,EACZ,CAAC,MAAO,KAAK,EACb,CAAC,MAAO,KAAK,EACb,CAAC,KAAM,IAAI,EACX,CAAC,MAAO,KAAK,EACb,CAAC,MAAO,KAAK,EACb,CAAC,KAAM,IAAI,EACX,CAAC,MAAO,KAAK,EACb,CAAC,MAAO,KAAK,EACb,CAAC,KAAM,KAAK,EACZ,CAAC,KAAM,IAAI,EACX,CAAC,MAAO,KAAK,EACb,CAAC,MAAO,KAAK,EACb,CAAC,KAAM,KAAK,EACZ,CAAC,MAAO,KAAK,EACb,CAAC,MAAO,KAAK,EACb,CAAC,KAAM,IAAI,EACX,CAAC,KAAM,KAAK,EACZ,CAAC,MAAO,KAAK,EACb,CAAC,MAAO,KAAK,EACb,CAAC,KAAM,EAAI,EACX,CAAC,MAAO,KAAK,EACb,CAAC,MAAO,KAAK,EACb,CAAC,KAAM,EAAI,EACX,CAAC,MAAO,KAAK,EACb,CAAC,MAAO,KAAK,EACb,CAAC,KAAM,KAAK,EACZ,CAAC,KAAM,KAAK,EACZ,CAAC,MAAO,IAAI,EACZ,CAAC,MAAO,IAAI,EACZ,CAAC,KAAM,KAAK,EACZ,CAAC,MAAO,KAAK,EACb,CAAC,MAAO,KAAK,EACb,CAAC,KAAM,KAAK,EACZ,CAAC,KAAM,KAAK,EACZ,CAAC,MAAO,IAAI,EACZ,CAAC,MAAO,IAAI,EACZ,CAAC,KAAM,EAAI,EACX,CAAC,MAAO,MAAM,EACd,CAAC,MAAO,MAAM,EACd,CAAC,KAAM,GAAK,EACZ,CAAC,MAAO,MAAM,EACd,CAAC,MAAO,MAAM,EACd,CAAC,KAAM,MAAM,EACb,CAAC,KAAM,MAAM,EACb,CAAC,MAAO,MAAM,EACd,CAAC,MAAO,MAAM,EACd,CAAC,KAAM,MAAM,EACb,CAAC,MAAO,MAAM,EACd,CAAC,MAAO,MAAM,EACd,CAAC,KAAM,MAAM,EACb,CAAC,KAAM,MAAM,EACb,CAAC,MAAO,GAAK,EACb,CAAC,MAAO,GAAK,EACb,CAAC,KAAM,GAAK,EACZ,CAAC,MAAO,MAAM,EACd,CAAC,MAAO,MAAM,EACd,CAAC,KAAM,GAAK,EACZ,CAAC,MAAO,MAAM,EACd,CAAC,MAAO,MAAM,EACd,CAAC,KAAM,MAAM,EACb,CAAC,KAAM,MAAM,EACb,CAAC,MAAO,MAAM,EACd,CAAC,MAAO,MAAM,EACd,CAAC,KAAM,MAAM,EACb,CAAC,MAAO,MAAM,EACd,CAAC,MAAO,MAAM,EACd,CAAC,KAAM,MAAM,EACb,CAAC,KAAM,MAAM,EACb,CAAC,MAAO,MAAM,EACd,CAAC,MAAO,MAAM,EACd,CAAC,KAAM,GAAK,EACZ,CAAC,MAAO,KAAK,EACb,CAAC,MAAO,KAAK,EACb,CAAC,KAAM,GAAK,EACZ,CAAC,MAAO,MAAM,EACd,CAAC,MAAO,MAAM,EACd,CAAC,KAAM,MAAM,EACb,CAAC,KAAM,MAAM,EACb,CAAC,MAAO,MAAM,EACd,CAAC,MAAO,MAAM,EACd,CAAC,KAAM,MAAM,EACb,CAAC,MAAO,MAAM,EACd,CAAC,MAAO,MAAM,EACd,CAAC,KAAM,MAAM,EACb,CAAC,KAAM,MAAM,EACb,CAAC,MAAO,MAAM,EACd,CAAC,MAAO,MAAM,EACd,CAAC,KAAM,MAAM,EACb,CAAC,MAAO,MAAM,EACd,CAAC,MAAO,MAAM,EACd,CAAC,KAAM,GAAK,EACZ,CAAC,MAAO,MAAM,EACd,CAAC,MAAO,MAAM,EACd,CAAC,KAAM,MAAM,EACb,CAAC,KAAM,MAAM,EACb,CAAC,MAAO,OAAO,EACf,CAAC,MAAO,OAAO,EACf,CAAC,KAAM,OAAO,EACd,CAAC,MAAO,OAAO,EACf,CAAC,MAAO,OAAO,EACf,CAAC,KAAM,OAAO,EACd,CAAC,KAAM,OAAO,EACd,CAAC,MAAO,OAAO,EACf,CAAC,MAAO,OAAO,EACf,CAAC,KAAM,OAAO,EACd,CAAC,MAAO,OAAO,EACf,CAAC,MAAO,OAAO,EACf,CAAC,KAAM,IAAM,EACb,CAAC,MAAO,OAAO,EACf,CAAC,MAAO,OAAO,EACf,CAAC,KAAM,OAAO,EACd,CAAC,KAAM,IAAM,EACb,CAAC,MAAO,OAAO,EACf,CAAC,MAAO,OAAO,EACf,CAAC,KAAM,OAAO,EACd,CAAC,MAAO,OAAO,EACf,CAAC,MAAO,OAAO,EACf,CAAC,KAAM,OAAO,EACd,CAAC,KAAM,OAAO,EACd,CAAC,MAAO,OAAO,EACf,CAAC,MAAO,OAAO,EACf,CAAC,KAAM,OAAO,EACd,CAAC,MAAO,OAAO,EACf,CAAC,MAAO,OAAO,EACf,CAAC,KAAM,IAAM,EACb,CAAC,MAAO,OAAO,EACf,CAAC,MAAO,OAAO,EACf,CAAC,KAAM,OAAO,EACd,CAAC,KAAM,OAAO,EACd,CAAC,MAAO,OAAO,EACf,CAAC,MAAO,OAAO,EACf,CAAC,KAAM,OAAO,EACd,CAAC,MAAO,OAAO,EACf,CAAC,MAAO,OAAO,CACjB,CAAC,EAEMC,GAAQD,GC7If,IAAME,GAAQ,CAAC,IAAK,KAAM,IAAK,KAAM,IAAK,IAAK,KAAM,IAAK,KAAM,IAAK,KAAM,GAAG,EAExEC,GAAsB,EAUPC,EAArB,MAAqBC,CAAsB,CACzC,OAAO,OACP,KACA,OACA,SAAW,EACX,SAEA,OAAO,cAAcC,EAAmB,CACtC,IAAIC,EAEJ,OAAW,CAACC,EAAMC,CAAI,IAAKC,GACzB,GAAID,IAASH,EAEb,CAAAC,EAAWC,EACX,MAGF,GAAI,CAACD,EAAU,MAAM,MAAM,oCAAoC,EAE/D,OAAO,IAAIF,EAAKE,CAAQ,CAC1B,CAEA,OAAO,UAAUI,EAAkB,CACjC,IAAMC,EAAOV,GAAMS,EAAQ,KAAK,CAAC,EAAI,EAAE,EACjCE,EAAS,KAAK,MAAMF,EAAQ,KAAK,CAAC,EAAI,EAAE,EAAI,EAElD,OAAO,IAAIN,EAAK,GAAGO,CAAI,GAAGC,CAAM,EAAE,CACpC,CAEA,OAAO,MAAMA,EAAS,EAAG,CACvB,OAAOX,GAAM,IAAKM,GAAiB,IAAIH,EAAK,GAAGG,CAAI,GAAGK,CAAM,EAAE,CAAC,CACjE,CAEA,YAAYL,EAAyC,CAC/C,OAAOA,GAAS,SAClB,KAAK,WAAWA,CAAI,EAEpB,KAAK,UAAUA,CAAI,CAEvB,CAEA,IAAI,QAAS,CACX,OAAO,KAAK,KAAK,SAAS,GAAG,CAC/B,CAEA,IAAI,UAAW,CACb,MAAO,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,EACnC,CAEA,IAAI,WAAoB,CACtB,OAAOE,GAAe,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,CACxD,CAEA,SAASI,EAAS,GAAkB,CAClC,IAAMC,EAAaD,EAAS,IAAO,IACnC,OAAO,IAAI,WAAW,CAACC,EAAY,KAAK,WAAY,KAAK,SAAW,GAAG,CAAC,CAC1E,CAEA,IAAI,YAAqB,CACvB,OAAQ,KAAK,OAASZ,IAAuB,GAAK,KAAK,SACzD,CAEA,IAAI,WAAoB,CACtB,OAAOD,GAAM,QAAQ,KAAK,IAAI,CAChC,CAEA,SAAU,CACR,OAAO,KAAK,QACd,CAEA,WAAmB,CACjB,MAAO,CACL,KAAM,KAAK,KACX,OAAQ,KAAK,OACb,UAAW,KAAK,UAChB,SAAU,KAAK,SACf,SAAU,KAAK,QACjB,CACF,CAEQ,WAAWc,EAAgB,CACjC,IAAMC,EAAU,cAAc,KAAKD,CAAM,GAAK,CAAC,EAE/C,KAAK,KAAOC,EAAQ,CAAC,EACrB,KAAK,OAASA,EAAQ,CAAC,EAAI,SAASA,EAAQ,CAAC,CAAC,EAAI,CACpD,CAEQ,UAAUC,EAAiC,CACjD,OAAO,OAAO,KAAMA,CAAK,CAC3B,CACF,EFhGA,IAAqBC,EAArB,MAAqBC,CAAU,CAC7B,KACA,QACS,YACD,QAER,OAAO,SACLC,EACAC,EAAS,GACTC,EACW,CACX,IAAMC,EAAOH,aAAoBI,EAAOJ,EAAW,IAAII,EAAKJ,CAAQ,EAEpE,OAAO,IAAID,EAAU,IAAIM,GAAQF,EAAK,SAASF,CAAM,CAAC,EAAGC,CAAW,CACtE,CAEA,OAAO,OACLI,EACAC,EACAL,EACW,CACX,OAAO,IAAIH,EACT,IAAIM,GAAQ,IAAI,WAAW,CAAC,IAAMC,EAAIC,CAAK,CAAC,CAAC,EAC7CL,CACF,CACF,CAEA,YAAYM,EAAkBN,EAA0B,CACtD,KAAK,QAAUM,EACf,KAAK,YAAcN,EACnB,KAAK,YAAY,CACnB,CAEA,IAAI,MAAO,CACT,OAAO,KAAK,QAAQ,IACtB,CAEA,IAAI,QAAS,CACX,OACE,KAAK,OAAS,UAAwB,KAAK,OAAS,SAExD,CAEA,aAAc,CACP,KAAK,SACN,KAAK,OAET,KAAK,KAAOE,EAAK,UAAU,KAAK,OAAO,GACzC,CAEA,IAAI,YAAa,CACf,OAAO,KAAK,OACd,CAEA,MAAMK,EAAkB,CACtB,IAAMC,EAAW,IAAIX,EAAU,KAAK,QAAS,KAAK,WAAW,EAC7D,OAAAW,EAAS,QAAUD,EAEZC,CACT,CACF,EPjCO,IAAeC,EAAf,KAAkE,CACvE,GACA,SACA,KACA,WACA,QACA,UACA,OACA,QACU,OACA,iBAAmB,GACnB,YAEV,YAAYC,EAAkBC,EAA+B,CAC3D,GAAM,CAAE,GAAAC,EAAI,KAAAC,EAAM,WAAAC,EAAY,QAAAC,EAAS,qBAAAC,EAAsB,MAAAC,CAAM,EACjEN,EAEF,KAAK,GAAKC,GAAMM,GAAO,EACvB,KAAK,SAAWR,EAChB,KAAK,KAAOG,EACZ,KAAK,WAAaC,EAClB,KAAK,QAAUC,GAAW,EAC1B,KAAK,YAAc,CAAC,EACpB,KAAK,UAAYC,IAAuB,KAAK,OAAO,EACpD,KAAK,OAAS,CAAC,EACf,KAAK,MAAQC,EAEb,KAAK,OAAS,IAAIE,EAAgB,IAAI,EACtC,KAAK,QAAU,IAAIC,EAAiB,IAAI,EAExC,KAAK,iBAAmB,EAC1B,CAEA,IAAI,OAAqC,CACvC,OAAO,KAAK,MACd,CAEA,IAAI,MAAMC,EAA6C,CACrD,OAAO,KAAKA,CAAK,EAAE,QAASC,GAAQ,CAClC,IAAMC,EAAY,QAAQC,GAAWF,CAAG,CAAC,GAIzC,KAAKC,CAAS,IAAIF,EAAMC,CAAG,CAAC,CAC9B,CAAC,EAED,KAAK,OAAS,CAAE,GAAG,KAAK,OAAQ,GAAGD,CAAM,EAEzC,OAAO,KAAKA,CAAK,EAAE,QAASC,GAAQ,CAClC,IAAMC,EAAY,aAAaC,GAAWF,CAAG,CAAC,GAI9C,KAAKC,CAAS,IAAIF,EAAMC,CAAG,CAAC,CAC9B,CAAC,CACH,CAEA,WAAiC,CAC/B,MAAO,CACL,GAAI,KAAK,GACT,KAAM,KAAK,KACX,WAAY,KAAK,WACjB,QAAS,KAAK,QACd,MAAO,KAAK,MACZ,OAAQ,KAAK,OAAO,UAAU,EAC9B,QAAS,KAAK,QAAQ,UAAU,CAClC,CACF,CAEA,KAAK,CACH,YAAAG,EACA,KAAAC,EACA,GAAAC,CACF,EAIG,CACD,IAAMC,EAAS,KAAK,QAAQ,WAAWF,CAAI,EACrCG,EAAQJ,EAAY,OAAO,WAAWE,CAAE,EAE9CC,EAAO,KAAKC,CAAK,CACnB,CAEU,UAAUC,EAAuB,CACzC,KAAK,OAAO,UAAUA,CAAQ,EAC9B,KAAK,QAAQ,UAAUA,CAAQ,CACjC,CAEU,WAAY,CACpB,KAAK,OAAO,UAAU,EACtB,KAAK,QAAQ,UAAU,CACzB,CAEA,MAAMC,EAA0B,CAEhC,CAEA,KAAKA,EAA0B,CAE/B,CAEA,cAAcC,EAAYC,EAAiC,CACrD,KAAK,YAAY,KAAMC,GAAMA,EAAE,WAAaF,EAAK,QAAQ,GAE7D,KAAK,YAAY,KAAKA,CAAI,CAC5B,CAEA,eAAeA,EAAYC,EAAiC,CAC1D,KAAK,YAAc,KAAK,YAAY,OACjCC,GAAMA,EAAE,WAAaF,EAAK,QAC7B,CACF,CAEA,YAAeG,GAAyB,CACtC,GAAM,CAAE,KAAAH,EAAM,YAAAI,CAAY,EAAID,EAE9B,OAAQA,EAAU,KAAM,CACtB,aAA2B,CACzB,KAAK,cAAcH,EAAOI,CAAW,EACrC,KACF,CACA,cACE,KAAK,eAAeJ,EAAOI,CAAW,EACtC,MACF,QACE,MAAM,MAAM,yBAAyB,CACzC,CACF,EAEU,oBAAqB,CAC7B,KAAK,OAAO,oBAAoB,CAC9B,GAAI,KAAK,GACT,WAAY,KAAK,WACjB,QAAS,KAAK,QACd,KAAM,KAAK,KACX,MAAO,KAAK,KACd,CAAC,CACH,CAEA,SAAU,CACR,KAAK,OAAO,UAAU,EACtB,KAAK,QAAQ,UAAU,CACzB,CAEU,mBAAmBf,EAA+B,OAAQ,CAClE,KAAK,kBAAkB,CACrB,KAAM,UACN,YAAa,KAAK,WACpB,CAAC,EAEI,KAAK,aAENA,IAAU,MAAQA,IAAU,SAC9B,KAAK,mBAAmB,CACtB,KAAM,KACN,aAAc,IAAM,KAAK,SAC3B,CAAC,GAGCA,IAAU,OAASA,IAAU,SAC/B,KAAK,oBAAoB,CACvB,KAAM,MACN,aAAc,IAAM,KAAK,SAC3B,CAAC,EAEL,CAEU,mBAAmBJ,EAAwC,CACnE,OAAO,KAAK,OAAO,IAAI,CAAE,GAAGA,EAAO,mBAA0B,CAAC,CAChE,CAEU,oBAAoBA,EAAyC,CACrE,OAAO,KAAK,QAAQ,IAAI,CAAE,GAAGA,EAAO,oBAA2B,CAAC,CAClE,CAEU,kBAAkBA,EAAuC,CACjE,OAAO,KAAK,OAAO,IAAI,CAAE,GAAGA,EAAO,kBAAyB,CAAC,CAC/D,CAEU,mBAAmBA,EAAwC,CACnE,OAAO,KAAK,QAAQ,IAAI,CACtB,GAAGA,EACH,mBACF,CAAC,CACH,CAEA,IAAc,QAAS,CACrB,OAAOoB,EAAO,QAAQ,KAAK,QAAQ,CACrC,CAEA,IAAc,SAAU,CACtB,OAAO,KAAK,OAAO,OACrB,CACF,EUvOA,OAAmB,UAAAC,OAAc,kBAc1B,IAAMC,EAAN,KAAa,CAClB,OACA,OAEA,YAAYC,EAAgB,CAC1B,KAAK,OAASA,EACd,KAAK,OAAS,IAAI,GACpB,CAEA,SAASC,EAAuC,CAC9C,IAAMC,EAAKD,EAAM,IAAMH,GAAO,EACxBK,EAAQ,CAAE,GAAGF,EAAO,GAAAC,CAAG,EAC7B,YAAK,OAAO,IAAIA,EAAIC,CAAK,EAEzB,KAAK,KAAKD,CAAE,EAELC,CACT,CAEA,YAAYD,EAAY,CACtB,KAAK,OAAOA,CAAE,EACd,KAAK,OAAO,OAAOA,CAAE,CACvB,CAEA,OAAQ,CACN,QAAWA,KAAM,KAAK,OACpB,KAAK,YAAYA,CAAE,CAEvB,CAEQ,KAAKA,EAAY,CACvB,GAAM,CAAE,SAAAE,EAAU,cAAAC,CAAc,EAAI,KAAK,OAAOH,CAAE,EAClDE,EAAS,KAAKC,CAAa,CAC7B,CAEQ,OAAOH,EAAY,CACzB,GAAM,CAAE,SAAAE,EAAU,cAAAC,CAAc,EAAI,KAAK,OAAOH,CAAE,EAClDE,EAAS,OAAOC,CAAa,CAC/B,CAEQ,KAAKH,EAAoB,CAC/B,IAAMC,EAAQ,KAAK,OAAO,IAAID,CAAE,EAChC,GAAI,CAACC,EAAO,MAAM,MAAM,iBAAiBD,CAAE,YAAY,EAEvD,OAAOC,CACT,CAEQ,OAAOD,EAAY,CACzB,IAAMC,EAAQ,KAAK,KAAKD,CAAE,EACpB,CAAE,OAAAI,EAAQ,YAAAC,CAAY,EAAIJ,EAE1BC,EAAW,KAAK,OAAO,OAC3BE,EAAO,SACPA,EAAO,OACP,QACF,EACMD,EAAgB,KAAK,OAAO,OAChCE,EAAY,SACZA,EAAY,OACZ,OACF,EAEA,MAAO,CAAE,SAAAH,EAAU,cAAAC,CAAc,CACnC,CACF,EC7EA,OAAgB,UAAAG,GAAQ,WAAAC,MAAe,UCGhC,IAAKC,OACVA,EAAA,UAAY,YACZA,EAAA,aAAe,eAFLA,OAAA,IAiBSC,EAArB,KAAuD,CACrD,GACA,KACA,qBAA8C,CAAC,EAEvC,QACA,MAER,YAAYC,EAAcC,EAAkB,CAC1C,KAAK,GAAKD,EAAM,GAChB,KAAK,KAAOA,EAAM,MAAQ,UAAUA,EAAM,EAAE,GAC5C,KAAK,MAAQA,EACb,KAAK,QAAUC,EAEf,KAAK,QAAQ,CACf,CAEA,IAAI,OAAQ,CACV,OAAO,KAAK,MAAM,KACpB,CAEA,SAAU,CACR,KAAK,MAAM,YAAY,cAAgB,GAAoB,CACzD,KAAK,aAAa,CAAC,CACrB,CAAC,CACH,CAEA,YAAa,CACX,KAAK,MAAM,eAAe,CAC5B,CAEA,WAAY,CACV,GAAM,CAAE,GAAAC,EAAI,KAAAC,EAAM,MAAAC,CAAM,EAAI,KAE5B,MAAO,CAAE,GAAAF,EAAI,KAAAC,EAAM,MAAAC,CAAM,CAC3B,CAEA,iBAAiBC,EAA+B,CAC9C,KAAK,qBAAqB,KAAKA,CAAQ,CACzC,CAEA,oBAAoBA,EAA+B,CACjD,KAAK,qBAAuB,KAAK,qBAAqB,OACnDC,GAAMA,IAAMD,CACf,CACF,CAEQ,aAAaE,EAAqB,CACxC,IAAMC,EAAY,IAAIC,EACpBF,EAAM,QACN,KAAK,QAAQ,qBAAqBA,EAAM,SAAS,CACnD,EAEA,OAAQC,EAAU,KAAM,CACtB,aACA,cACE,KAAK,qBAAqB,QAASH,GAAa,CAC9CA,EAASG,CAAS,CACpB,CAAC,CACL,CACF,CACF,EC7EA,IAAME,GAAiC,CACrC,EAAG,IAAIC,EAAK,IAAI,EAChB,EAAG,IAAIA,EAAK,IAAI,EAChB,EAAG,IAAIA,EAAK,IAAI,EAChB,EAAG,IAAIA,EAAK,IAAI,EAChB,EAAG,IAAIA,EAAK,IAAI,EAChB,EAAG,IAAIA,EAAK,IAAI,EAChB,EAAG,IAAIA,EAAK,IAAI,EAChB,EAAG,IAAIA,EAAK,IAAI,EAChB,EAAG,IAAIA,EAAK,IAAI,EAChB,EAAG,IAAIA,EAAK,KAAK,EACjB,EAAG,IAAIA,EAAK,KAAK,EACjB,EAAG,IAAIA,EAAK,KAAK,EACjB,EAAG,IAAIA,EAAK,KAAK,EACjB,EAAG,IAAIA,EAAK,KAAK,EACjB,EAAG,IAAIA,EAAK,KAAK,EACjB,EAAG,IAAIA,EAAK,KAAK,CACnB,EAEMC,GAAuB,KAAO,CAClC,GAAI,oBACJ,KAAM,oBACN,iBACF,GAEqBC,EAArB,KAAiE,CAC/D,GACA,KACA,MACA,qBAA8C,CAAC,EACvC,QAER,YAAYC,EAAkB,CAC5B,GAAM,CAAE,GAAAC,EAAI,KAAAC,EAAM,MAAAC,CAAM,EAAIL,GAAqB,EACjD,KAAK,GAAKG,EACV,KAAK,KAAOC,EACZ,KAAK,MAAQC,EACb,KAAK,QAAUH,EAEf,SAAS,iBAAiB,UAAW,KAAK,aAAa,EAAI,CAAC,EAC5D,SAAS,iBAAiB,QAAS,KAAK,aAAa,EAAK,CAAC,CAC7D,CAEA,iBAAiBI,EAA+B,CAC9C,KAAK,qBAAqB,KAAKA,CAAQ,CACzC,CAEA,oBAAoBA,EAA+B,CACjD,KAAK,qBAAuB,KAAK,qBAAqB,OACnDC,GAAMA,IAAMD,CACf,CACF,CAEA,WAAY,CACV,GAAM,CAAE,GAAAH,EAAI,KAAAC,EAAM,MAAAC,CAAM,EAAI,KAE5B,MAAO,CAAE,GAAAF,EAAI,KAAAC,EAAM,MAAAC,CAAM,CAC3B,CAEA,aAAgBG,GAAqBC,GAAyB,CAC5D,IAAMC,EAAO,KAAK,YAAYD,CAAK,EACnC,GAAI,CAACC,EAAM,OAEX,IAAMC,EAAYC,EAAU,SAC1BF,EACAF,EACA,KAAK,QAAQ,qBAAqBC,EAAM,SAAS,CACnD,EACA,KAAK,qBAAqB,QAASH,GAAa,CAC9CA,EAASK,CAAS,CACpB,CAAC,CACH,EAEQ,YAAYF,EAAwC,CAC1D,GAAI,CAAAA,EAAM,OAEV,OAAOX,GAASW,EAAM,GAAG,CAC3B,CACF,EF5EA,IAAqBI,EAArB,KAAuC,CACrC,QAAU,IAAI,IACN,YAAc,GACd,UAAgC,CAAC,EACjC,QAER,YAAYC,EAAkB,CAC5B,KAAK,QAAUA,EACf,KAAK,oBAAoB,CAC3B,CAEA,MAAM,YAAa,CACjB,MAAM,KAAK,kBAAkB,EAE7B,KAAK,cAAc,EACnB,KAAK,YAAc,EACrB,CAEA,KAAKC,EAA6D,CAChE,OAAO,KAAK,QAAQ,IAAIA,CAAE,CAC5B,CAEA,YAAYC,EAA4B,CACtC,KAAK,UAAU,KAAKA,CAAQ,CAC9B,CAEA,MAAc,mBAAoB,CAChC,GAAI,MAAK,YAET,GAAI,CACF,MAAMC,EAAQ,OAAO,EAErBA,EAAQ,OAAO,QAASC,GAAU,CAC3B,KAAK,QAAQ,IAAIA,EAAM,EAAE,GAC5B,KAAK,QAAQ,IAAIA,EAAM,GAAI,IAAIC,EAAWD,EAAO,KAAK,OAAO,CAAC,CAElE,CAAC,CACH,OAASE,EAAK,CACZ,QAAQ,MAAM,0BAA2BA,CAAG,CAC9C,CACF,CAEQ,qBAAsB,CAC5B,GAAI,OAAO,SAAa,IAAa,OAErC,IAAMC,EAAyB,IAAIC,EAAuB,KAAK,OAAO,EACtE,KAAK,QAAQ,IAAID,EAAuB,GAAIA,CAAsB,CACpE,CAEQ,eAAgB,CACtBJ,EAAQ,YAAY,YAAcM,GAAU,CAC1C,IAAMC,EAAOD,EAAM,KAGnB,GAFIC,aAAgBC,IAEhB,KAAK,QAAQ,IAAID,EAAK,EAAE,EAAG,OAE/B,IAAME,EAAS,IAAIP,EAAWK,EAAM,KAAK,OAAO,EAChD,KAAK,QAAQ,IAAIE,EAAO,GAAIA,CAAM,EAElC,KAAK,UAAU,QAASC,GAAa,CACnCA,EAASD,CAAM,CACjB,CAAC,CACH,CAAC,EAEDT,EAAQ,YAAY,eAAiBM,GAAU,CAC7C,IAAMC,EAAOD,EAAM,KACnB,GAAIC,aAAgBC,GAAQ,OAE5B,IAAMC,EAAS,KAAK,QAAQ,IAAIF,EAAK,EAAE,EAClCE,IACDA,aAAkBJ,IAEtBI,EAAO,WAAW,EAClB,KAAK,QAAQ,OAAOA,EAAO,EAAE,EAE7B,KAAK,UAAU,QAASC,GAAa,CACnCA,EAASD,CAAM,CACjB,CAAC,GACH,CAAC,CACH,CACF,EGvFA,OAAS,eAAAE,OAAmB,kBCUrB,IAAMC,GAA6D,CAAC,EACrEC,GAAgB,CAAC,EAEjBC,GAAN,cAAoBC,CAAkC,CAEpD,WAA4B,KAC5B,YAA2B,EAE3B,YACEC,EACAC,EACA,CACA,IAAMC,EAAQ,CAAE,GAAGL,GAAe,GAAGI,EAAO,KAAM,EAElD,MAAMD,EAAU,CACd,GAAGC,EACH,MAAAC,CACF,CAAC,CACH,CAEA,cAAiBC,GAAyB,CACxC,GAAM,CAAE,YAAAC,EAAa,KAAAC,EAAM,KAAAC,CAAK,EAAIH,EAEpC,GAAI,CAACE,EAAM,OACX,IAAME,EAAWF,EAAK,SAEtB,OAAQC,EAAM,CACZ,aACE,KAAK,WAAaC,EAClB,KAAK,YAAcH,EAEnB,MACF,cACE,KAAK,WAAa,KAClB,MACF,QACE,MAAM,MAAM,yBAAyB,CACzC,CACF,CACF,EAEqBI,EAArB,cAA4CC,CAAsC,CAEhF,WAEA,YACET,EACAC,EACA,CACA,IAAMC,EAAQ,CAAE,GAAGL,GAAe,GAAGI,EAAO,KAAM,EAC5CS,EAAwB,CAC5BV,EACAC,IACG,IAAIH,GAAME,EAAUC,CAAM,EAE/B,MAAMD,EAAU,CACd,GAAGC,EACH,MAAAC,EACA,sBAAAQ,CACF,CAAC,EAED,KAAK,eAAe,EACpB,KAAK,gBAAgB,CACvB,CAEA,YAAeP,GAAyB,CACtC,IAAIQ,EAEJ,OAAQR,EAAU,KAAM,CACtB,aACEQ,EAAQ,KAAK,cAAc,EAE3B,MACF,cACEA,EAAQ,KAAK,aAAa,KACvBC,GAAMA,EAAE,aAAeT,EAAU,KAAM,QAC1C,EACA,MACF,QACE,MAAM,MAAM,yBAAyB,CACzC,CAEKQ,IAELA,EAAM,cAAcR,CAAS,EAC7BA,EAAU,QAAUQ,EAAM,QAC1B,KAAK,WAAW,YAAYR,CAAS,EACvC,EAEQ,eAAuB,CAC7B,IAAIQ,EAAQ,KAAK,aAAa,KAAMC,GAAM,CAACA,EAAE,UAAU,EAGvD,OAAAD,IAAU,KAAK,aAAa,KAAK,CAACE,EAAGC,IAC5BD,EAAE,YAAcC,EAAE,WAC1B,EAAE,CAAC,EAEGH,CACT,CAEQ,gBAAiB,CACvB,KAAK,kBAAkB,CACrB,KAAM,UACN,YAAa,KAAK,WACpB,CAAC,CACH,CAEQ,iBAAkB,CACxB,KAAK,WAAa,KAAK,mBAAmB,CAAE,KAAM,UAAW,CAAC,CAChE,CACF,EC5GO,IAAMI,GAAyC,CACpD,KAAM,CACJ,KAAM,SACN,IAAK,EACL,IAAK,IACL,KAAM,IACN,MAAO,MACT,CACF,EAEMC,GAA4B,CAAE,KAAM,CAAE,EAE/BC,EAAN,cAAuBC,CAAwB,CAGpD,YAAYC,EAAkBC,EAAwC,CACpE,IAAMC,EAAQ,CAAE,GAAGL,GAAe,GAAGI,EAAO,KAAM,EAC5CE,EAAwBC,GAC5B,IAAI,SAASA,EAAQ,YAAY,EAEnC,MAAMJ,EAAU,CACd,GAAGC,EACH,qBAAAE,EACA,MAAAD,CACF,CAAC,EAED,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,CAChC,CAEU,UAAUG,EAA2B,CAC7C,KAAK,UAAU,KAAK,MAAQA,CAC9B,CAEQ,0BAA2B,CACjC,KAAK,mBAAmB,CACtB,KAAM,OACN,aAAc,IAAM,KAAK,UAAU,IACrC,CAAC,CACH,CACF,EAEqBC,EAArB,cAAkCC,CAA4B,CAC5D,YACEP,EACAC,EACA,CACA,IAAMC,EAAQ,CAAE,GAAGL,GAAe,GAAGI,EAAO,KAAM,EAC5CO,EAAwB,CAC5BR,EACAC,IACG,IAAIH,EAASE,EAAUC,CAAM,EAElC,MAAMD,EAAU,CACd,GAAGC,EACH,MAAAC,EACA,sBAAAM,CACF,CAAC,EAED,KAAK,yBAAyB,EAC9B,KAAK,mBAAmB,CAC1B,CAEQ,0BAA2B,CACjC,KAAK,mBAAmB,CAAE,KAAM,MAAO,CAAC,CAC1C,CACF,EC/DA,IAAMC,GAAW,GACXC,GAAW,IAEXC,GAAoC,CACxC,OAAQD,GACR,eAAgB,EAChB,KAAM,UACN,EAAG,CACL,EAEaE,GAAyD,CACpE,OAAQ,CACN,KAAM,SACN,IAAKH,GACL,IAAKC,GACL,KAAM,EACN,MAAO,QACT,EACA,eAAgB,CACd,KAAM,SACN,IAAK,GACL,IAAK,EACL,KAAM,IACN,MAAO,iBACT,EACA,KAAM,CACJ,KAAM,OACN,QAAS,CAAC,UAAW,WAAY,UAAU,EAC3C,MAAO,MACT,EACA,EAAG,CACD,KAAM,SACN,IAAK,KACL,IAAK,IACL,KAAM,GACN,MAAO,GACT,CACF,EAEMG,GAAN,cAA+BC,CAAgC,CAErD,MACA,OAER,YACEC,EACAC,EACA,CACA,IAAMC,EAAQ,CAAE,GAAGN,GAAe,GAAGK,EAAO,KAAM,EAE5CE,EAAwBC,GAC5B,IAAI,iBAAiBA,EAAQ,aAAc,CACzC,KAAMF,EAAM,KACZ,UAAWA,EAAM,OACjB,EAAGA,EAAM,CACX,CAAC,EAEH,MAAMF,EAAU,CACd,GAAGC,EACH,MAAAC,EACA,qBAAAC,CACF,CAAC,EAED,KAAK,OAAS,IAAIE,EAASL,EAAU,CACnC,KAAM,SACN,kBACA,MAAO,CAAE,KAAME,EAAM,cAAe,CACtC,CAAC,EAED,KAAK,MAAQI,EAAaN,EAAU,CAClC,KAAM,QACN,mBACA,MAAO,CAAE,IAAKN,GAAU,IAAKC,GAAU,QAAS,KAAK,MAAM,MAAO,CACpE,CAAC,EAED,KAAK,OAAO,KAAK,CAAE,YAAa,KAAK,MAAO,KAAM,MAAO,GAAI,IAAK,CAAC,EACnE,KAAK,MAAM,UAAU,QAAQ,KAAK,UAAU,SAAS,EAErD,KAAK,mBAAmB,EACxB,KAAK,eAAe,CACtB,CAEU,UAAUY,EAAmC,CACrD,KAAK,UAAU,KAAOA,CACxB,CAEU,YAAYA,EAAqC,CACpD,KAAK,mBAEV,KAAK,MAAM,MAAQ,CAAE,QAASA,CAAM,EACtC,CAEU,OAAOA,EAAgC,CAC/C,KAAK,UAAU,EAAE,MAAQA,CAC3B,CAEU,oBAAoBA,EAA6C,CACpE,KAAK,mBAEV,KAAK,OAAO,MAAQ,CAAE,KAAMA,CAAM,EACpC,CAEQ,gBAAiB,CACvB,KAAK,mBAAmB,CACtB,KAAM,SACN,aAAc,IAAM,KAAK,UAAU,SACrC,CAAC,EAED,KAAK,mBAAmB,CACtB,KAAM,YACN,aAAc,IAAM,KAAK,OAAO,SAClC,CAAC,EAED,KAAK,mBAAmB,CACtB,KAAM,IACN,aAAc,IAAM,KAAK,UAAU,CACrC,CAAC,CACH,CACF,EAEqBC,EAArB,cAA0CC,CAAoC,CAC5E,YACET,EACAC,EACA,CACA,IAAMC,EAAQ,CAAE,GAAGN,GAAe,GAAGK,EAAO,KAAM,EAC5CS,EAAwB,CAC5BV,EACAC,IACG,IAAIH,GAAiBE,EAAUC,CAAM,EAE1C,MAAMD,EAAU,CACd,GAAGC,EACH,MAAAC,EACA,sBAAAQ,CACF,CAAC,EAED,KAAK,eAAe,EACpB,KAAK,mBAAmB,CAC1B,CAEQ,gBAAiB,CACvB,KAAK,mBAAmB,CAAE,KAAM,QAAS,CAAC,EAC1C,KAAK,mBAAmB,CAAE,KAAM,WAAY,CAAC,EAC7C,KAAK,mBAAmB,CAAE,KAAM,GAAI,CAAC,CACvC,CACF,ECrJO,IAAMC,GAAiD,CAC5D,MAAO,CACL,KAAM,SACN,IAAK,KACL,IAAK,IACL,KAAM,IACN,MAAO,OACT,CACF,EAEMC,GAAgC,CAAE,MAAO,CAAE,EAE5BC,EAArB,cAAsCC,CAA4B,CAEhE,SAAW,GAEX,YAAYC,EAAkBC,EAA4C,CACxE,IAAMC,EAAQ,CAAE,GAAGL,GAAe,GAAGI,EAAO,KAAM,EAC5CE,EAAwBC,GAC5B,IAAI,mBAAmBA,EAAQ,YAAY,EAE7C,MAAMJ,EAAU,CACd,GAAGC,EACH,MAAAC,EACA,qBAAAC,CACF,CAAC,EAED,KAAK,mBAAmB,KAAK,CAC/B,CAEU,WAAWE,EAAgC,CACnD,KAAK,UAAU,OAAO,MAAQA,CAChC,CAEA,MAAMC,EAAmB,CACnB,KAAK,WAET,KAAK,SAAW,GAChB,KAAK,UAAU,MAAMA,CAAI,EAC3B,CAEA,KAAKA,EAAmB,CACtB,KAAK,UAAU,KAAKA,CAAI,EACxB,KAAK,UAAU,IAAM,CACnB,KAAK,UAAY,IAAI,mBAAmB,KAAK,QAAQ,aAAc,CACjE,OAAQ,KAAK,MAAM,KACrB,CAAC,CACH,CAAC,EAED,KAAK,SAAW,EAClB,CAEA,cAAgB,CAACC,EAAYC,IAA6B,CACxD,KAAK,UAAU,OAAO,eAAeD,EAAK,UAAWC,CAAW,EAChE,KAAK,MAAMA,CAAW,CACxB,EAEA,eAAiB,IAAM,CAEvB,CACF,ECvEA,OAAkB,yBAAAC,OAA6B,kBAe/C,IAAMC,GAAgC,CACpC,OAAQ,GACR,MAAO,GACP,QAAS,EACT,QAAS,EACX,EAEaC,GAAiD,CAC5D,OAAQ,CACN,KAAM,SACN,IAAK,KACL,IAAK,EACL,KAAM,IACN,MAAO,QACT,EACA,MAAO,CACL,KAAM,SACN,IAAK,EACL,IAAK,EACL,KAAM,IACN,MAAO,OACT,EACA,QAAS,CACP,KAAM,SACN,IAAK,EACL,IAAK,EACL,KAAM,IACN,MAAO,SACT,EACA,QAAS,CACP,KAAM,SACN,IAAK,EACL,IAAK,EACL,KAAM,IACN,MAAO,SACT,CACF,EAEMC,GAAaC,GAAsB,CACvC,IAAK,KACL,IAAK,EACP,CAAC,EAEKC,GAAcD,GAAsB,CACxC,IAAK,KACL,IAAK,CACP,CAAC,EAEKE,GAAN,cAA2BC,CAA4B,CAGrD,YAAYC,EAAkBC,EAA4C,CACxE,IAAMC,EAAQ,CAAE,GAAGT,GAAe,GAAGQ,EAAO,KAAM,EAC5CE,EAAwBC,GAAqB,CACjD,IAAMC,EAAY,IAAI,SAASD,EAAQ,YAAY,EACnD,OAAAC,EAAU,KAAK,MAAQ,EAChBA,CACT,EAEA,MAAML,EAAU,CACd,GAAGC,EACH,MAAAC,EACA,qBAAAC,CACF,CAAC,EAED,KAAK,mBAAmB,CAC1B,CAEA,cAAcG,EAAYC,EAA0B,CAClD,MAAM,cAAcD,EAAMC,CAAW,EAErC,IAAMC,EAAS,KAAK,aAAa,EAC3BC,EAAQ,KAAK,YAAY,EACzBC,EAAU,KAAK,MAAM,QAE3B,KAAK,UAAU,KAAK,oBAAoBH,CAAW,EAG/C,KAAK,UAAU,KAAK,QAAU,GAChC,KAAK,UAAU,KAAK,eAAe,KAAOA,CAAW,EAIvD,KAAK,UAAU,KAAK,6BAA6B,EAAKA,EAAcC,CAAM,EAGtEE,EAAU,EACZ,KAAK,UAAU,KAAK,6BAClBA,EACAH,EAAcC,EAASC,CACzB,EAGA,KAAK,UAAU,KAAK,6BAClB,KACAF,EAAcC,EAASC,CACzB,CAEJ,CAEA,eAAeH,EAAYC,EAA0B,CAEnD,GADA,MAAM,eAAeD,EAAMC,CAAW,EAClC,KAAK,YAAY,OAAS,EAAG,OAEjC,IAAMI,EAAU,KAAK,cAAc,EAGnC,KAAK,UAAU,KAAK,oBAAoBJ,CAAW,EACnD,IAAMK,EAAmB,KAAK,UAAU,KAAK,MAEzCA,GAAoB,OAEtB,KAAK,UAAU,KAAK,eAAeA,EAAkBL,CAAW,EAEhE,KAAK,UAAU,KAAK,6BAClB,KACAA,EAAcI,EAAU,IAC1B,GAIF,KAAK,UAAU,KAAK,eAAe,EAAGJ,EAAcI,CAAO,CAC7D,CAEQ,cAAe,CACrB,OAAOhB,GAAW,KAAK,MAAM,MAAM,CACrC,CAEQ,aAAc,CACpB,OAAOE,GAAY,KAAK,MAAM,KAAK,CACrC,CAEQ,eAAgB,CACtB,OAAOF,GAAW,KAAK,MAAM,OAAO,CACtC,CACF,EAEqBkB,EAArB,cAAsCC,CAAgC,CACpE,YACEd,EACAC,EACA,CACA,IAAMC,EAAQ,CAAE,GAAGT,GAAe,GAAGQ,EAAO,KAAM,EAC5Cc,EAAwB,CAC5Bf,EACAC,IACG,IAAIH,GAAaE,EAAUC,CAAM,EAEtC,MAAMD,EAAU,CACd,GAAGC,EACH,MAAAC,EACA,sBAAAa,CACF,CAAC,EAED,KAAK,mBAAmB,CAC1B,CACF,EC5KA,OAAS,eAAAC,OAA4B,kBCA9B,IAAMC,GAAqB,IAAI,gBACpC,IAAI,KACF,CACE,KACC,IAAM,CACL,MAAMC,UAAwB,qBAAsB,CAClD,GACA,GAEA,aAAc,CACZ,MAAM,EACN,KAAK,GAAK,EACV,KAAK,GAAK,CACZ,CAEA,WAAW,sBAAuB,CAChC,MAAO,CACL,CACE,KAAM,SACN,aAAc,IACd,SAAU,GACV,SAAU,GACZ,EACA,CACE,KAAM,YACN,aAAc,EACd,SAAU,EACV,SAAU,CACZ,CACF,CACF,CAEA,QACEC,EACAC,EACAC,EACS,CACT,IAAMC,EAAQH,EAAO,CAAC,EAChBI,EAASH,EAAQ,CAAC,EAElBI,EAASH,EAAW,OACpBI,EAAYJ,EAAW,UAE7B,QAASK,EAAa,EAAGA,EAAaJ,EAAM,OAAQI,IAAc,CAChE,IAAMC,EAAeL,EAAMI,CAAU,EAC/BE,EAAgBL,EAAOG,CAAU,EAEvC,QAASG,EAAI,EAAGA,EAAIF,EAAa,OAAQE,IAAK,CAC5C,IAAMC,EAAIH,EAAaE,CAAC,EAGlBE,EAAWP,EAAO,OAAS,EAAIA,EAAOK,CAAC,EAAIL,EAAO,CAAC,EACnDQ,GAAY,KAAK,IAAI,GAAI,KAAK,IAAI,IAAOD,CAAQ,CAAC,EAClDE,GACJ,KAAK,IAAID,GAAY,EAAE,EAAI,KAAK,IAAI,IAAQ,EAAE,EAC1CE,EAAI,KAAK,IAAI,IAAM,EAAID,IAAoB,IAAK,EAOhDE,GAAM,EANF,KAAK,IACb,KACEV,EAAU,OAAS,EAAIA,EAAUI,CAAC,EAAIJ,EAAU,CAAC,GACjD,MACA,IACJ,EACoBS,EAEpB,KAAK,GAAKC,GAAM,KAAK,GAAKD,EAAI,KAAK,GAAKA,EAAIJ,EAC5C,KAAK,GAAKK,GAAM,KAAK,GAAKD,EAAI,KAAK,GAEnCN,EAAcC,CAAC,EAAI,KAAK,EAC1B,CACF,CAEA,MAAO,EACT,CACF,CAEA,kBAAkB,mBAAoBX,CAAe,CACvD,GAAG,SAAS,EACZ,KACF,EACA,CAAE,KAAM,wBAAyB,CACnC,CACF,ECjFO,IAAMkB,GAAoB,IAAI,gBACnC,IAAI,KACF,CACE,KACC,IAAM,CACL,MAAMC,UAAuB,qBAAsB,CACjD,WAAW,sBAAuB,CAChC,MAAO,CACL,CACE,KAAM,MACN,aAAc,KAChB,EACA,CACE,KAAM,MACN,aAAc,CAChB,EACA,CACE,KAAM,UACN,aAAc,EAChB,CACF,CACF,CAEA,QACEC,EACAC,EACAC,EACA,CACA,IAAMC,EAAQH,EAAO,CAAC,EAChBI,EAASH,EAAQ,CAAC,EAElBI,EAAYH,EAAW,IACvBI,EAAYJ,EAAW,IACvBK,EAAgBL,EAAW,QAEjC,GAAI,CAACC,EAAM,QAAUA,EAAM,CAAC,EAAE,SAAW,EAAG,CAC1C,QAAWK,KAAiBJ,EAAQ,CAClC,IAAMK,GACJP,EAAW,QAAQ,OAAS,EACxBA,EAAW,QAAQ,CAAC,GAG1BM,EAAc,KAAKC,CAAO,CAC5B,CAEA,MAAO,EACT,CAEA,QAASC,EAAU,EAAGA,EAAUP,EAAM,OAAQO,IAAW,CACvD,IAAMC,EAAeR,EAAMO,CAAO,EAC5BF,EAAgBJ,EAAOM,CAAO,EAEpC,QAASE,EAAI,EAAGA,EAAID,EAAa,OAAQC,IAAK,CAC5C,IAAMC,EAAIF,EAAaC,CAAC,EAElBE,GAAMT,EAAU,OAAS,EAAIA,EAAUO,CAAC,EAAIP,EAAU,CAAC,EACvDU,GAAMT,EAAU,OAAS,EAAIA,EAAUM,CAAC,EAAIN,EAAU,CAAC,EACvDG,EACJF,EAAc,OAAS,EACnBA,EAAcK,CAAC,EACfL,EAAc,CAAC,EAEjBM,EAAI,EACNL,EAAcI,CAAC,EAAIH,EAAU,KAAK,IAAIK,GAAML,EAAS,CAACI,CAAC,EAEvDL,EAAcI,CAAC,EAAIH,EAAU,KAAK,IAAIM,GAAMN,EAASI,CAAC,CAE1D,CACF,CAEA,MAAO,EACT,CACF,CAEA,kBAAkB,kBAAmBd,CAAc,CACrD,GAAG,SAAS,EACZ,KACF,EACA,CAAE,KAAM,wBAAyB,CACnC,CACF,EFvEA,eAAsBiB,GAAeC,EAAkB,CACrD,MAAMA,EAAQ,UAAUC,EAAiB,EACzC,MAAMD,EAAQ,UAAUE,EAAkB,CAC5C,CAEO,SAASC,GAAgBH,EAAkBI,EAAwB,CACxE,OAAQA,EAAS,CACf,IAAK,iBACH,OAAOJ,EAAQ,gBAAgB,iBAAiB,EAClD,IAAK,kBACH,OAAOA,EAAQ,gBAAgB,kBAAkB,EACnD,QACEK,GAAYD,CAAO,CACvB,CACF,CGPA,IAAME,GAAW,GACXC,GAAW,MAEXC,GAA8B,CAClC,OAAQD,GACR,eAAgB,EAChB,UAAW,CACb,EAEaE,GAA6C,CACxD,OAAQ,CACN,KAAM,SACN,IAAKH,GACL,IAAKC,GACL,KAAM,KACN,MAAO,QACT,EACA,eAAgB,CACd,KAAM,SACN,IAAK,GACL,IAAK,EACL,KAAM,IACN,MAAO,iBACT,EACA,UAAW,CACT,KAAM,SACN,IAAK,EACL,IAAK,EACL,KAAM,IACN,MAAO,WACT,CACF,EAEMG,GAAN,cAAyBC,CAA0B,CAEzC,MACA,OAER,YAAYC,EAAkBC,EAA0C,CACtE,IAAMC,EAAQ,CAAE,GAAGN,GAAe,GAAGK,EAAO,KAAM,EAE5CE,EAAwBC,GAC5BC,GAAgBD,mBAAsC,EAExD,MAAMJ,EAAU,CACd,GAAGC,EACH,MAAAC,EACA,qBAAAC,CACF,CAAC,EAED,KAAK,OAAS,IAAIG,EAASN,EAAU,CACnC,KAAM,SACN,kBACA,MAAO,CAAE,KAAME,EAAM,cAAe,CACtC,CAAC,EAED,KAAK,MAAQK,EAAaP,EAAU,CAClC,KAAM,QACN,mBACA,MAAO,CAAE,IAAKN,GAAU,IAAKC,GAAU,QAAS,KAAK,MAAM,MAAO,CACpE,CAAC,EAED,KAAK,OAAO,KAAK,CAAE,YAAa,KAAK,MAAO,KAAM,MAAO,GAAI,IAAK,CAAC,EACnE,KAAK,MAAM,UAAU,QAAQ,KAAK,MAAM,EAExC,KAAK,mBAAmB,EACxB,KAAK,eAAe,CACtB,CAEA,IAAI,QAAS,CACX,OAAO,KAAK,UAAU,WAAW,IAAI,QAAQ,CAC/C,CAEA,IAAI,WAAY,CACd,OAAO,KAAK,UAAU,WAAW,IAAI,WAAW,CAClD,CAEU,YAAYa,EAA+B,CAC9C,KAAK,mBAEV,KAAK,MAAM,MAAQ,CAAE,QAASA,CAAM,EACtC,CAEU,eAAeA,EAAkC,CACzD,KAAK,UAAU,MAAQA,CACzB,CAEU,oBAAoBA,EAAuC,CAC9D,KAAK,mBAEV,KAAK,OAAO,MAAQ,CAAE,KAAMA,CAAM,EACpC,CAEQ,gBAAiB,CACvB,KAAK,mBAAmB,CACtB,KAAM,SACN,aAAc,IAAM,KAAK,MAAM,SACjC,CAAC,EAED,KAAK,mBAAmB,CACtB,KAAM,YACN,aAAc,IAAM,KAAK,OAAO,SAClC,CAAC,EAED,KAAK,mBAAmB,CACtB,KAAM,IACN,aAAc,IAAM,KAAK,SAC3B,CAAC,CACH,CACF,EAEqBC,EAArB,cAAoCC,CAA8B,CAChE,YACEV,EACAC,EACA,CACA,IAAMC,EAAQ,CAAE,GAAGN,GAAe,GAAGK,EAAO,KAAM,EAC5CU,EAAwB,CAC5BX,EACAC,IACG,IAAIH,GAAWE,EAAUC,CAAM,EAEpC,MAAMD,EAAU,CACd,GAAGC,EACH,MAAAC,EACA,sBAAAS,CACF,CAAC,EAED,KAAK,eAAe,EACpB,KAAK,mBAAmB,CAC1B,CAEQ,gBAAiB,CACvB,KAAK,mBAAmB,CAAE,KAAM,QAAS,CAAC,EAC1C,KAAK,mBAAmB,CAAE,KAAM,WAAY,CAAC,EAC7C,KAAK,mBAAmB,CAAE,KAAM,GAAI,CAAC,CACvC,CACF,EC/IO,IAAMC,GAAmD,CAC9D,QAAS,CACP,KAAM,OACN,QAAS,CAAC,GAAI,GAAI,IAAK,IAAK,IAAK,KAAM,KAAM,KAAM,KAAM,MAAO,KAAK,EACrE,MAAO,UACT,CACF,EAEMC,GAAiC,CAAE,QAAS,GAAI,EAEjCC,EAArB,cAAuCC,CAA6B,CAE1D,QAER,YAAYC,EAAkBC,EAA6C,CACzE,IAAMC,EAAQ,CAAE,GAAGL,GAAe,GAAGI,EAAO,KAAM,EAC5CE,EAAwBC,GAC5B,IAAI,aAAaA,EAAQ,YAAY,EAEvC,MAAMJ,EAAU,CACd,GAAGC,EACH,MAAAC,EACA,qBAAAC,CACF,CAAC,EAED,KAAK,mBAAmB,IAAI,CAC9B,CAEU,aAAaE,EAAe,CACpC,KAAK,QAAU,IAAI,aAAaA,CAAK,CACvC,CAEA,IAAI,QAAS,CACX,OAAI,KAAK,QAAgB,KAAK,SAE9B,KAAK,QAAU,IAAI,aAAa,KAAK,MAAM,OAAO,EAE3C,KAAK,QACd,CAEA,UAAmB,CACjB,OAAO,KAAK,UAAU,EAAE,CAAC,CAC3B,CAEA,WAA0B,CACxB,YAAK,UAAU,uBAAuB,KAAK,MAAM,EAE1C,KAAK,MACd,CACF,ECnDA,IAAMC,GAA8B,CAAC,EAExBC,GAA6C,CAAC,EAEtCC,EAArB,cAAoCC,CAA0B,CAG5D,YAAYC,EAAkBC,EAA0C,CACtE,IAAMC,EAAQ,CAAE,GAAGN,GAAe,GAAGK,EAAO,KAAM,EAC5CE,EAAwBC,GAAqBA,EAAQ,YAE3D,MAAMJ,EAAU,CAAE,GAAGC,EAAQ,qBAAAE,EAAsB,MAAAD,CAAM,CAAC,EAE1D,KAAK,mBAAmB,IAAI,CAC9B,CACF,ECbO,IAAMG,GAAyD,CACpE,WAAY,CACV,KAAM,SACN,MAAO,gBACT,CACF,EAEMC,GAAoC,CAAE,WAAY,MAAU,EAE7CC,EAArB,cAA0CC,CAAgC,CAExE,WACA,kBAEA,YACEC,EACAC,EACA,CACA,IAAMC,EAAQ,CAAE,GAAGL,GAAe,GAAGI,EAAO,KAAM,EAElD,MAAMD,EAAU,CACd,GAAGC,EACH,MAAAC,CACF,CAAC,EAED,KAAK,iBAAiB,KAAK,MAAM,UAAU,EAE3C,KAAK,gBAAgB,CACvB,CAEU,gBAAgBC,EAAsB,CACzC,KAAK,mBAEV,KAAK,oBAAoB,EACzB,KAAK,iBAAiBA,CAAK,EAC7B,CAEA,IAAY,kBAAmB,CAC7B,OAAI,KAAK,kBAA0B,KAAK,mBAExC,KAAK,kBAAqBC,GAAyB,CACjD,KAAK,WAAW,YAAYA,CAAS,CACvC,EAEO,KAAK,kBACd,CAEQ,iBAAiBC,EAAmC,CAC1D,GAAI,CAACA,EAAQ,OAEM,KAAK,OAAO,eAAeA,CAAM,GACxC,iBAAiB,KAAK,gBAAgB,CACpD,CAEQ,qBAAsB,CAC5B,GAAI,CAAC,KAAK,MAAM,WAAY,OAET,KAAK,OAAO,eAAe,KAAK,MAAM,UAAU,GACvD,oBAAoB,KAAK,gBAAgB,CACvD,CAEQ,iBAAkB,CACxB,KAAK,WAAa,KAAK,mBAAmB,CAAE,KAAM,UAAW,CAAC,CAChE,CACF,ECzEA,OAAkB,YAAAC,OAAgB,kBAQlC,IAAMC,GAAW,IAILC,QACVA,EAAA,KAAO,OACPA,EAAA,SAAW,WACXA,EAAA,OAAS,SACTA,EAAA,SAAW,WAJDA,QAAA,IA2BCC,GAAqD,CAChE,KAAM,CACJ,KAAM,OACN,QAAS,OAAO,OAAOD,EAAc,EACrC,MAAO,UACT,EACA,UAAW,CACT,KAAM,SACN,IAAK,EACL,IAAK,KACL,KAAM,EACN,MAAO,WACT,EACA,KAAM,CACJ,KAAM,SACN,IAAK,GACL,IAAK,EACL,KAAM,IACN,MAAO,MACT,EACA,OAAQ,CACN,KAAM,SACN,IAAK,IACL,IAAK,GACL,KAAM,EACN,MAAO,QACT,EACA,OAAQ,CACN,KAAM,SACN,IAAK,GACL,IAAK,EACL,KAAM,EACN,MAAO,QACT,EACA,QAAS,CACP,KAAM,UACN,MAAO,OAAOD,EAAQ,SACxB,CACF,EAEMG,GAAkC,CACtC,KAAM,OACN,UAAW,IACX,KAAM,EACN,OAAQ,EACR,OAAQ,EACR,QAAS,EACX,EAEaC,GAAN,cAA6BC,CAA8B,CAEhE,SAAW,GACX,cACA,WAEA,YAAYC,EAAkBC,EAA8C,CAC1E,IAAMC,EAAQ,CAAE,GAAGL,GAAe,GAAGI,EAAO,KAAM,EAC5CE,EAAwBC,GAC5B,IAAI,eAAeA,EAAQ,YAAY,EAEzC,MAAMJ,EAAU,CACd,GAAGC,EACH,MAAAC,EACA,qBAAAC,CACF,CAAC,EAED,KAAK,cAAgB,IAAI,SAAS,KAAK,QAAQ,aAAc,CAC3D,KAAME,GAASX,EAAQ,CACzB,CAAC,EAED,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACpB,KAAK,gBAAgB,CACvB,CAEU,eAAeY,EAAuB,CAC9C,KAAK,UAAU,KAAOA,CACxB,CAEU,qBAAsB,CAC9B,KAAK,gBAAgB,CACvB,CAEU,gBAAiB,CACzB,KAAK,gBAAgB,CACvB,CAEU,kBAAmB,CAC3B,KAAK,gBAAgB,CACvB,CAEU,kBAAmB,CAC3B,KAAK,gBAAgB,CACvB,CAEU,mBAAoB,CACvB,KAAK,kBAEV,KAAK,UAAU,CACjB,CAEA,MAAMC,EAAmB,CACnB,KAAK,WAET,KAAK,SAAW,GAChB,KAAK,UAAU,MAAMA,CAAI,EAC3B,CAEA,KAAKA,EAAmB,CACtB,KAAK,UAAU,KAAKA,CAAI,EACxB,KAAK,UAAU,IAAM,CACnB,KAAK,UAAY,IAAI,eAAe,KAAK,QAAQ,aAAc,CAC7D,KAAM,KAAK,MAAM,KACjB,UAAW,KAAK,cAClB,CAAC,EACD,KAAK,gBAAgB,EACrB,KAAK,WAAW,QAAQ,KAAK,UAAU,MAAM,CAC/C,CAAC,EAED,KAAK,SAAW,EAClB,CAEA,cAAgB,CAACC,EAAYC,IAA6B,CACxD,MAAM,cAAcD,EAAMC,CAAW,EAErC,KAAK,MAAQ,CAAE,UAAWD,EAAK,SAAU,EACzC,KAAK,gBAAgBC,CAAW,EAChC,KAAK,MAAMA,CAAW,CACxB,EAEA,eAAeD,EAAYC,EAA0B,CACnD,MAAM,eAAeD,EAAMC,CAAW,EAEtC,IAAMC,EAAW,KAAK,YAAY,OAC9B,KAAK,YAAY,KAAK,YAAY,OAAS,CAAC,EAC5C,KACCA,IAEL,KAAK,MAAQ,CAAE,UAAWA,EAAS,SAAU,EAC7C,KAAK,gBAAgBD,CAAW,EAClC,CAEA,IAAY,gBAAqC,CAC/C,GAAM,CAAE,UAAAE,EAAW,OAAAC,EAAQ,OAAAC,EAAQ,KAAAC,CAAK,EAAI,KAAK,MACjD,OAAK,KAAK,iBAGRH,EAAY,KAAK,IAAI,EAAGC,EAAS,GAAKC,EAASC,EAAO,EAAE,EAH9B,MAK9B,CAEQ,gBAAgBC,EAAwB,CAC1C,KAAK,iBAAmB,SAExBA,EACF,KAAK,UAAU,UAAU,eAAe,KAAK,eAAgBA,CAAQ,EAErE,KAAK,UAAU,UAAU,MAAQ,KAAK,eAE1C,CAEQ,iBAAkB,CACxB,KAAK,UAAU,QAAQ,KAAK,aAAa,CAC3C,CAEQ,sBAAuB,CAC7B,KAAK,WAAa,IAAI,SAAS,KAAK,QAAQ,aAAc,CAAE,KAAM,GAAI,CAAC,EACvE,KAAK,WAAW,QAAQ,KAAK,UAAU,MAAM,CAC/C,CAEQ,gBAAiB,CACvB,KAAK,mBAAmB,CACtB,KAAM,SACN,aAAc,IAAM,KAAK,UAC3B,CAAC,CACH,CAEQ,iBAAkB,CACxB,KAAK,oBAAoB,CACvB,KAAM,MACN,aAAc,IACZ,KAAK,MAAM,QAAU,KAAK,cAAgB,KAAK,SACnD,CAAC,CACH,CACF,EAEqBC,EAArB,cAAwCC,CAAkC,CACxE,YACEjB,EACAC,EACA,CACA,IAAMC,EAAQ,CAAE,GAAGL,GAAe,GAAGI,EAAO,KAAM,EAC5CiB,EAAwB,CAC5BlB,EACAC,IACG,IAAIH,GAAeE,EAAUC,CAAM,EAExC,MAAMD,EAAU,CACd,GAAGC,EACH,MAAAC,EACA,sBAAAgB,CACF,CAAC,EAED,KAAK,eAAe,EACpB,KAAK,mBAAmB,KAAK,CAC/B,CAEA,MAAMX,EAAmB,CACvB,KAAK,aAAa,QAASY,GAAgB,CACzCA,EAAY,MAAMZ,CAAI,CACxB,CAAC,CACH,CAEA,KAAKA,EAAmB,CACtB,KAAK,aAAa,QAASY,GAAgB,CACzCA,EAAY,KAAKZ,CAAI,CACvB,CAAC,CACH,CAEQ,gBAAiB,CACvB,KAAK,mBAAmB,CAAE,KAAM,QAAS,CAAC,CAC5C,CACF,EC1PO,IAAMa,GAA2C,CACtD,IAAK,CACH,KAAM,SACN,IAAK,KACL,IAAK,IACL,KAAM,IACN,MAAO,KACT,EACA,IAAK,CACH,KAAM,SACN,IAAK,KACL,IAAK,IACL,KAAM,IACN,MAAO,KACT,EACA,QAAS,CACP,KAAM,SACN,IAAK,KACL,IAAK,IACL,KAAM,IACN,MAAO,SACT,CACF,EAEMC,GAA6B,CAAE,IAAK,EAAG,IAAK,EAAG,QAAS,EAAI,EAE7CC,EAArB,cAAmCC,CAAyB,CAG1D,YAAYC,EAAkBC,EAAyC,CACrE,IAAMC,EAAQ,CAAE,GAAGL,GAAe,GAAGI,EAAO,KAAM,EAC5CE,EAAwBC,GAC5BC,GAAgBD,kBAAqC,EAEvD,MAAMJ,EAAU,CACd,GAAGC,EACH,MAAAC,EACA,qBAAAC,CACF,CAAC,EAED,KAAK,mBAAmB,CAC1B,CAEA,IAAI,SAAU,CACZ,OAAO,KAAK,UAAU,WAAW,IAAI,SAAS,CAChD,CAEA,IAAI,KAAM,CACR,OAAO,KAAK,UAAU,WAAW,IAAI,KAAK,CAC5C,CAEA,IAAI,KAAM,CACR,OAAO,KAAK,UAAU,WAAW,IAAI,KAAK,CAC5C,CAEU,SAASG,EAAe,CAChC,KAAK,IAAI,MAAQA,CACnB,CAEU,SAASA,EAAe,CAChC,KAAK,IAAI,MAAQA,CACnB,CAEU,aAAaA,EAAe,CACpC,KAAK,QAAQ,MAAQA,CACvB,CACF,EC7DO,IAAMC,GAET,CACF,MAAO,CACL,KAAM,SACN,IAAK,EACL,IAAK,GACL,KAAM,EACN,MAAO,OACT,EACA,KAAM,CACJ,KAAM,SACN,IAAK,EACL,IAAK,GACL,KAAM,EACN,MAAO,OACT,CACF,EAEMC,GAAqC,CACzC,UAAW,CAAC,EACZ,MAAO,GACP,KAAM,CACR,EAGqBC,EAArB,cAA2CC,CAAiC,CAE1E,WAEA,YACEC,EACAC,EACA,CACA,IAAMC,EAAQ,CAAE,GAAGL,GAAe,GAAGI,EAAO,KAAM,EAElD,MAAMD,EAAU,CACd,GAAGC,EACH,MAAAC,CACF,CAAC,CACH,CACF,ECjDO,IAAMC,GAAuD,CAClE,YAAa,CACX,KAAM,QACN,MAAO,cACT,CACF,EAEMC,GAAmC,CAAE,YAAa,CAAC,CAAE,EAEtCC,EAArB,cAAyCC,CAA+B,CAEtE,WAEA,YAAYC,EAAkBC,EAA+C,CAC3E,IAAMC,EAAQ,CAAE,GAAGL,GAAe,GAAGI,EAAO,KAAM,EAElD,MAAMD,EAAU,CACd,GAAGC,EACH,MAAAC,CACF,CAAC,EAED,KAAK,eAAe,EACpB,KAAK,gBAAgB,CACvB,CAEA,SAASC,EAAsB,CAC7B,KAAK,WAAW,YAAYA,CAAS,CACvC,CAEA,cAAgB,CAACC,EAAYC,IAA+B,CAC1D,KAAK,MAAQ,CAAE,YAAa,CAAC,GAAG,KAAK,MAAM,YAAaD,EAAK,QAAQ,CAAE,EACvE,KAAK,mBAAmB,EACxB,KAAK,SAASE,EAAU,SAASF,EAAM,GAAMC,CAAa,CAAC,CAC7D,EAEA,eAAiB,CAACD,EAAYC,IAA+B,CAC3D,KAAK,MAAQ,CACX,YAAa,KAAK,MAAM,YAAY,OACjCE,GAASA,IAASH,EAAK,QAC1B,CACF,EACA,KAAK,mBAAmB,EACxB,KAAK,SAASE,EAAU,SAASF,EAAM,GAAOC,CAAa,CAAC,CAC9D,EAEQ,gBAAiB,CACvB,KAAK,kBAAkB,CACrB,KAAM,UACN,YAAa,KAAK,WACpB,CAAC,CACH,CAEQ,iBAAkB,CACxB,KAAK,WAAa,KAAK,mBAAmB,CAAE,KAAM,UAAW,CAAC,CAChE,CACF,EhB9BO,IAAKG,OACVA,EAAA,OAAS,SACTA,EAAA,WAAa,aACbA,EAAA,KAAO,OACPA,EAAA,aAAe,eACfA,EAAA,SAAW,WACXA,EAAA,OAAS,SACTA,EAAA,aAAe,eACfA,EAAA,MAAQ,QACRA,EAAA,UAAY,YACZA,EAAA,SAAW,WACXA,EAAA,YAAc,cACdA,EAAA,cAAgB,gBAChBA,EAAA,eAAiB,iBAbPA,OAAA,IAgDCC,GAET,CACD,WAAwBC,GACxB,KAAkBC,GAClB,OAAoBC,GACpB,aAA0BC,GAC1B,SAAsBC,GACtB,OAAoBC,GACpB,aAA0BC,GAC1B,MAAmBC,GACnB,UAAuBC,GACvB,SAAsBC,GACtB,YAAyBC,GACzB,cAA2BC,GAC3B,eAA4BC,EAC/B,EAmCO,SAASC,EACdC,EACAC,EAC4D,CAC5D,OAAQA,EAAO,WAAY,CACzB,IAAK,aACH,OAAO,IAAIC,EAAWF,EAAUC,CAAM,EACxC,IAAK,OACH,OAAO,IAAIE,EAAKH,EAAUC,CAAM,EAClC,IAAK,SACH,OAAO,IAAIG,EAAOJ,EAAUC,CAAM,EACpC,IAAK,eACH,OAAO,IAAII,EAAaL,EAAUC,CAAM,EAC1C,IAAK,WACH,OAAO,IAAIK,EAASN,EAAUC,CAAM,EACtC,IAAK,SACH,OAAO,IAAIM,EAAOP,EAAUC,CAAM,EACpC,IAAK,eACH,OAAO,IAAIO,EAAaR,EAAUC,CAAM,EAC1C,IAAK,QACH,OAAO,IAAIQ,EAAMT,EAAUC,CAAM,EACnC,IAAK,YACH,OAAO,IAAIS,EAAUV,EAAUC,CAAM,EACvC,IAAK,WACH,OAAO,IAAIU,EAASX,EAAUC,CAAM,EACtC,IAAK,cACH,OAAO,IAAIW,EAAYZ,EAAUC,CAAM,EACzC,IAAK,gBACH,OAAO,IAAIY,EAAcb,EAAUC,CAAM,EAC3C,IAAK,iBACH,OAAO,IAAIa,EAAed,EAAUC,CAAM,EAC5C,QACEc,GAAYd,CAAM,CACtB,CACF,CfrIO,IAAMe,EAAN,MAAMC,CAAO,CAClB,OAAe,SAAW,IAAI,IAC9B,OAAe,WACP,qBAEO,CAAC,EAEP,GACT,QACA,cAAgB,GAChB,OACA,UACA,QAKA,kBAEA,OAAO,QAAQC,EAAoB,CACjC,IAAMC,EAASF,EAAO,SAAS,IAAIC,CAAE,EACrC,OAAAE,GAAcD,CAAM,EAEbA,CACT,CAEA,WAAW,SAAkB,CAC3B,OAAAC,GAAc,KAAK,UAAU,EAEtB,KAAK,QAAQ,KAAK,UAAU,CACrC,CAEA,YAAYC,EAAkB,CAC5B,KAAK,GAAKC,GAAO,EAEjB,KAAK,QAAUD,EACf,KAAK,UAAY,IAAIE,GAAU,KAAK,QAAS,CAC3C,UAAW,CAACC,EAAeC,IAClB,CAAC,EAEV,SAAWC,GAA2B,CAEtC,EACA,OAASC,GAAkB,CAE3B,EACA,QAAS,KAAK,QACd,OAAQ,KAAK,OACb,QAAUC,GAA2B,CAErC,CACF,CAAC,EACD,KAAK,OAAS,IAAIC,EAAO,IAAI,EAC7B,KAAK,QAAU,IAAI,IACnB,KAAK,kBAAoB,IAAIC,EAAkB,KAAK,OAAO,EAE3Db,EAAO,SAAS,IAAI,KAAK,GAAI,IAAI,EACjCA,EAAO,WAAa,KAAK,EAC3B,CAEA,IAAI,OAAQ,CACV,OAAO,KAAK,UAAU,KACxB,CAEA,MAAM,YAAa,CACb,KAAK,gBAET,MAAMc,GAAe,KAAK,OAAO,EACjC,MAAM,KAAK,kBAAkB,WAAW,EACxC,KAAK,cAAgB,GACvB,CAEA,UAAgCC,EAA0B,CACxD,IAAMC,EAASC,EAAa,KAAK,GAAIF,CAAsB,EAC3D,YAAK,QAAQ,IAAIC,EAAO,GAAIA,CAAM,EAE3BA,EAAO,UAAU,CAC1B,CAEA,aAAmCD,EAA0B,CAC3D,IAAMC,EAAS,KAAK,WAAWD,EAAO,EAAE,EACxC,GAAIC,EAAO,aAAeD,EAAO,WAC/B,MAAM,MACJ,iBAAiBA,EAAO,EAAE,qBAAqBA,EAAO,UAAU,EAClE,EAGF,IAAMG,EAAUC,GAAKJ,EAAO,QAAS,CAAC,OAAQ,OAAO,CAAC,EACtD,cAAO,OAAOC,EAAQE,CAAO,EAEzBF,aAAkBI,GAAcL,EAAO,QAAQ,SAAW,SAC5DC,EAAO,OAASD,EAAO,QAAQ,QAG1BC,EAAO,UAAU,CAC1B,CAEA,aAAaf,EAAY,CACvB,KAAK,QAAQ,OAAOA,CAAE,CACxB,CAEA,SAASoB,EAA6B,CACpC,OAAO,KAAK,OAAO,SAASA,CAAK,CACnC,CAEA,YAAYpB,EAAY,CACtB,KAAK,OAAO,YAAYA,CAAE,CAC5B,CAEA,WAAWoB,EAAwC,CACjD,GAAM,CAAE,OAAAC,EAAQ,YAAAC,CAAY,EAAIF,EAE1BG,EAAS,KAAK,OAAOF,EAAO,SAAUA,EAAO,OAAQ,QAAQ,EAC7DG,EAAQ,KAAK,OACjBF,EAAY,SACZA,EAAY,OACZ,OACF,EAEA,OACGC,EAAO,OAAO,GAAKC,EAAM,OAAO,GAChCD,EAAO,QAAQ,GAAKC,EAAM,QAAQ,CAEvC,CAEA,MAAM,OAAQ,CACZ,MAAM,KAAK,OAAO,EAClB,KAAK,UAAU,MAAM,CACvB,CAEA,MAAO,CACL,KAAK,UAAU,KAAK,EACpB,KAAK,UAAU,MAAM,CACvB,CAEA,OAAQ,CACN,KAAK,UAAU,KAAK,CACtB,CAEA,IAAI,KAAM,CACR,OAAO,KAAK,UAAU,GACxB,CAEA,IAAI,IAAIC,EAAe,CACrB,KAAK,UAAU,IAAMA,CACvB,CAEA,IAAI,eAAgB,CAClB,OAAO,KAAK,UAAU,aACxB,CAEA,IAAI,cAAcA,EAAsB,CACtC,KAAK,UAAU,cAAgBA,CACjC,CAEA,MAAM,QAAS,CACb,MAAM,KAAK,QAAQ,OAAO,CAC5B,CAEA,SAAU,CACR,KAAK,KAAK,EACV,KAAK,OAAO,MAAM,EAClB,KAAK,QAAQ,QAASV,GAAW,CAC/BA,EAAO,QAAQ,CACjB,CAAC,EACD,KAAK,QAAQ,MAAM,CACrB,CAEA,WACEf,EAC4D,CAC5D,IAAMe,EAAS,KAAK,QAAQ,IAAIf,CAAE,EAClC,GAAI,CAACe,EAAQ,MAAM,MAAM,sBAAsBf,CAAE,gBAAgB,EAEjE,OAAOe,CACT,CAEA,OAAOW,EAAkBC,EAAgBC,EAA0B,CAEjE,OADe,KAAK,WAAWF,CAAQ,EACzB,GAAGE,CAAI,GAAG,EAAE,WAAWD,CAAM,CAC7C,CAEA,eAAe3B,EAAY,CACzB,OAAO,KAAK,kBAAkB,KAAKA,CAAE,CACvC,CAEA,cAAc6B,EAA8D,CAC1E,KAAK,qBAAqB,KAAKA,CAAQ,CACzC,CAEA,oBAA0Cf,EAAoB,CAC5D,KAAK,qBAAqB,QAASe,GAAa,CAC9CA,EAASf,CAAM,CACjB,CAAC,CACH,CAGA,mBAAmBd,EAAY8B,EAAkBF,EAA4B,CAC3E,IAAMG,EAAc,KAAK,WAAW/B,CAAE,EACtC,GAAI+B,EAAY,aAAe,cAC7B,MAAM,MAAM,2BAA2B,EAEzCA,EAAY,SACVC,EAAU,SAASF,EAAUF,IAAS,SAAU,KAAK,QAAQ,WAAW,CAC1E,CACF,CAGQ,QAAWK,GAA0B,CAC3C,KAAK,QAAQ,QAASlB,GAAW,CAC/BA,EAAO,MAAMkB,CAAQ,CACvB,CAAC,CACH,EAGQ,OAAUA,GAA0B,CAC1C,KAAK,QAAQ,QAASlB,GAAW,CAC/BA,EAAO,KAAKkB,CAAQ,CACtB,CAAC,CACH,CACF,EgC1OA,OAAS,kBAAAC,OAAsB,sBAG/B,OAAS,WAAAC,OAAe","names":["Transport","assertDefined","pick","uuidv4","upperFirst","uuidv4","assertNever","deterministicId","uuidv4","PolyModule","engineId","params","id","name","moduleType","voices","monoModuleConstructor","props","uuidv4","InputCollection","OutputCollection","value","m","time","audioModule","from","to","output","input","callback","midiEvent","voiceNo","moduleByVoice","deterministicId","Engine","deterministicId","Base","module","props","deterministicId","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","assertNever","callback","id","name","InputCollection","OutputCollection","Message","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","uuidv4","InputCollection","OutputCollection","value","key","onSetAttr","upperFirst","audioModule","from","to","output","input","callback","_time","note","_triggeredAt","n","midiEvent","triggeredAt","Engine","uuidv4","Routes","engine","props","id","route","sourceIO","destinationIO","source","destination","Output","WebMidi","MidiPortState","MidiDevice","input","context","id","name","state","callback","c","event","midiEvent","MidiEvent","MAP_KEYS","Note","computerKeyboardData","ComputerKeyboardInput","context","id","name","state","callback","c","noteOn","event","note","midiEvent","MidiEvent","MidiDeviceManager","context","id","callback","WebMidi","input","MidiDevice","err","computerKeyboardDevice","ComputerKeyboardInput","event","port","Output","device","listener","assertNever","voiceSchedulerPropSchema","DEFAULT_PROPS","Voice","Module","engineId","params","props","midiEvent","triggeredAt","note","type","noteName","VoiceScheduler","PolyModule","monoModuleConstructor","voice","v","a","b","gainPropSchema","DEFAULT_PROPS","MonoGain","Module","engineId","params","props","audioNodeConstructor","context","value","Gain","PolyModule","monoModuleConstructor","MIN_FREQ","MAX_FREQ","DEFAULT_PROPS","biquadFilterPropSchema","MonoBiquadFilter","Module","engineId","params","props","audioNodeConstructor","context","MonoGain","createModule","value","BiquadFilter","PolyModule","monoModuleConstructor","constantPropSchema","DEFAULT_PROPS","Constant","Module","engineId","params","props","audioNodeConstructor","context","value","time","note","triggeredAt","createScaleNormalized","DEFAULT_PROPS","envelopePropSchema","scaleToTen","createScaleNormalized","scaleToFive","MonoEnvelope","Module","engineId","params","props","audioNodeConstructor","context","audioNode","note","triggeredAt","attack","decay","sustain","release","currentGainValue","Envelope","PolyModule","monoModuleConstructor","assertNever","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","assertNever","MIN_FREQ","MAX_FREQ","DEFAULT_PROPS","filterPropSchema","MonoFilter","Module","engineId","params","props","audioNodeConstructor","context","newAudioWorklet","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","midiSelectorPropSchema","DEFAULT_PROPS","MidiSelector","Module","engineId","params","props","value","midiEvent","midiId","dbToGain","LOW_GAIN","OscillatorWave","oscillatorPropSchema","DEFAULT_PROPS","MonoOscillator","Module","engineId","params","props","audioNodeConstructor","context","dbToGain","value","time","note","triggeredAt","lastNote","frequency","coarse","octave","fine","actionAt","Oscillator","PolyModule","monoModuleConstructor","audioModule","scalePropSchema","DEFAULT_PROPS","Scale","Module","engineId","params","props","audioNodeConstructor","context","newAudioWorklet","value","stepSequencerPropSchema","DEFAULT_PROPS","StepSequencer","Module","engineId","params","props","virtualMidiPropSchema","DEFAULT_PROPS","VirtualMidi","Module","engineId","params","props","midiEvent","note","triggerAttack","MidiEvent","name","ModuleType","moduleSchemas","oscillatorPropSchema","gainPropSchema","masterPropSchema","midiSelectorPropSchema","envelopePropSchema","filterPropSchema","biquadFilterPropSchema","scalePropSchema","inspectorPropSchema","constantPropSchema","virtualMidiPropSchema","stepSequencerPropSchema","voiceSchedulerPropSchema","createModule","engineId","params","Oscillator","Gain","Master","MidiSelector","Envelope","Filter","BiquadFilter","Scale","Inspector","Constant","VirtualMidi","StepSequencer","VoiceScheduler","assertNever","Engine","_Engine","id","engine","assertDefined","context","uuidv4","Transport","_start","_end","_event","_ticks","_actionAt","Routes","MidiDeviceManager","loadProcessors","params","module","createModule","updates","pick","PolyModule","props","source","destination","output","input","value","moduleId","ioName","type","callback","noteName","virtualMidi","MidiEvent","actionAt","TransportState","Context"]}