mosfez-synth
Version:
A microtonal-aware synth engine library for web.
1 lines • 23.3 kB
Source Map (JSON)
{"version":3,"file":"poly.mjs","sources":["../src/internal/param-utils.ts","../src/dsp-node.ts","../src/internal/voice-allocator.ts","../src/internal/voice-controller.ts","../src/poly.ts"],"sourcesContent":["import { ParamValueObject } from \"../params\";\nimport { ParamDefinitionObject, ParamDefinition } from \"../dsp-node\";\n\nexport function validateParamDefinition(\n name: string,\n paramDef: ParamDefinition\n): ParamDefinition {\n if (!isConstant(paramDef) && !isVariable(paramDef)) {\n throw new Error(\n `param \"${name}\" must be a constant number or a string referring to a param name, but got ${paramDef}`\n );\n }\n return paramDef;\n}\n\nexport function validateParamDefinitionObject(\n paramDefs: ParamDefinitionObject\n): ParamDefinitionObject {\n for (const name in paramDefs) {\n validateParamDefinition(name, paramDefs[name] as ParamDefinition);\n }\n return paramDefs;\n}\n\nexport function isConstant(paramDef: ParamDefinition): paramDef is number {\n return typeof paramDef === \"number\";\n}\n\nexport function isVariable(paramDef: ParamDefinition): paramDef is string {\n return typeof paramDef === \"string\";\n}\n\nexport function resolveParam(\n params: Partial<ParamValueObject>,\n paramDef: ParamDefinition\n): number | undefined {\n if (isConstant(paramDef)) {\n return paramDef;\n } else if (isVariable(paramDef)) {\n return params[paramDef] as number;\n }\n return undefined;\n}\n","import type { compile } from \"mosfez-faust/faust\";\nimport type { VoiceController } from \"./internal/voice-controller\";\nimport {\n validateParamDefinitionObject,\n validateParamDefinition,\n} from \"./internal/param-utils\";\n\nexport type ParamDefinition = number | string;\n\nexport type ParamDefinitionObject = Record<string, ParamDefinition>;\n\nexport type DspNodeType = \"faust\" | \"poly\";\n\nexport type DspNodeSerialized = DspNodeFaustSerialized | DspNodePolySerialized;\n\nexport type DspNodeConfig = {\n type: DspNodeType;\n};\n\nexport class DspNode {\n type: DspNodeType;\n\n constructor(config: DspNodeConfig) {\n this.type = config.type;\n }\n\n static isFaustDspNode(DspNode: DspNode): DspNode is DspNodeFaust {\n return DspNode.type === \"faust\";\n }\n\n static isPolyDspNode(DspNode: DspNode): DspNode is DspNodePoly {\n return DspNode.type === \"poly\";\n }\n\n static isFaustDspNodeSerialized(\n serialized: DspNodeSerialized\n ): serialized is DspNodeFaustSerialized {\n return serialized.type === \"faust\";\n }\n\n static isPolyDspNodeSerialized(\n serialized: DspNodeSerialized\n ): serialized is DspNodePolySerialized {\n return serialized.type === \"poly\";\n }\n\n serialize(): DspNodeSerialized {\n throw new Error(\".serialize() can only be called on subclasses\");\n }\n}\n\n//\n// faust\n//\n\nexport type DspNodeFaustDependencies = {\n compile: typeof compile;\n};\n\nexport type DspNodeFaustConfig = {\n dsp: string;\n inputs?: DspNode[];\n paramDefs: ParamDefinitionObject;\n dependencies: DspNodeFaustDependencies;\n};\n\nexport type DspNodeFaustSerialized = {\n type: \"faust\";\n dsp: string;\n inputs: DspNodeSerialized[];\n paramDefs: ParamDefinitionObject;\n};\n\nexport class DspNodeFaust extends DspNode {\n dsp: string;\n inputs: DspNode[];\n paramDefs: ParamDefinitionObject;\n dependencies: DspNodeFaustDependencies;\n\n constructor(config: DspNodeFaustConfig) {\n super({\n type: \"faust\",\n });\n\n this.dsp = config.dsp;\n this.inputs = config.inputs ?? [];\n this.paramDefs = validateParamDefinitionObject(config.paramDefs);\n this.dependencies = config.dependencies;\n }\n\n serialize(): DspNodeFaustSerialized {\n const { dsp, paramDefs } = this;\n const inputs = this.inputs.map((input) => input.serialize());\n\n return {\n type: \"faust\",\n dsp,\n inputs,\n paramDefs,\n };\n }\n}\n\n//\n// poly\n//\n\nexport type DspNodePolyDependencies = {\n VoiceController: typeof VoiceController;\n};\n\nexport type DspNodePolyConfig = {\n input: DspNode;\n polyphony: number;\n paramCacheSize?: number;\n release: ParamDefinition;\n gate: ParamDefinition;\n dependencies: DspNodePolyDependencies;\n};\n\nexport type DspNodePolySerialized = {\n type: \"poly\";\n input: DspNodeSerialized;\n polyphony: number;\n paramCacheSize?: number;\n release: ParamDefinition;\n gate: ParamDefinition;\n};\n\nexport class DspNodePoly extends DspNode {\n input: DspNode;\n polyphony: number;\n paramCacheSize?: number;\n release: ParamDefinition;\n gate: ParamDefinition;\n dependencies: DspNodePolyDependencies;\n\n constructor(config: DspNodePolyConfig) {\n super({\n type: \"poly\",\n });\n\n this.input = config.input;\n this.polyphony = config.polyphony;\n this.paramCacheSize = config.paramCacheSize;\n this.release = validateParamDefinition(\"release\", config.release);\n this.gate = validateParamDefinition(\"gate\", config.gate);\n this.dependencies = config.dependencies;\n }\n\n serialize(): DspNodePolySerialized {\n const { polyphony, paramCacheSize, release, gate } = this;\n const input = this.input.serialize();\n\n return {\n type: \"poly\",\n input,\n polyphony,\n paramCacheSize,\n release,\n gate,\n };\n }\n}\n","type VoiceIndex = number;\ntype VoiceIsNew = boolean;\ntype Result = [VoiceIndex, VoiceIsNew];\ntype Voice = {\n id: string;\n voice: number;\n time: number;\n released?: ReturnType<typeof setTimeout>;\n};\n\nfunction findOldestVoiceIndex(voices: (Voice | undefined)[]): number {\n if (voices.length === 0) return -1;\n const oldest = voices.reduce((prev, current) => {\n const usePrev = !current || (prev && prev.time < current.time);\n return usePrev ? prev : current;\n });\n return oldest?.voice ?? -1;\n}\n\nexport class VoiceAllocator {\n private _time = 0;\n private _voices: (Voice | undefined)[] = [];\n\n constructor(total: number) {\n this._voices.length = total;\n }\n\n private _startVoice(voice: number, id: string) {\n const existing = this._voices[voice];\n if (existing?.released !== undefined) {\n clearTimeout(existing.released);\n }\n this._voices[voice] = {\n id,\n voice,\n time: this._time++,\n };\n return voice;\n }\n\n private _stopVoice(voice: number) {\n this._voices[voice] = undefined;\n }\n\n private _findStarted(id: string) {\n return this._voices.findIndex(\n (v) => v && v.id === id && v.released === undefined\n );\n }\n\n private _findReleased(id: string) {\n return this._voices.findIndex(\n (v) => v && v.id === id && v.released !== undefined\n );\n }\n\n get voices(): (undefined | string)[] {\n return this._voices.map((voice) => voice?.id);\n }\n\n get(id: string): number {\n return this._voices.findIndex((v) => v && v.id === id);\n }\n\n start(id: string): Result {\n // if this voice is already started, return it\n const started = this._findStarted(id);\n if (started !== -1) {\n return [started, false];\n }\n\n // else, if this voice is currently released, start it again and return it\n const released = this._findReleased(id);\n if (released !== -1) {\n return [this._startVoice(released, id), false];\n }\n\n // else, if there is a stopped voice voice, start it and return it\n const stopped = this._voices.findIndex((v) => !v);\n if (stopped !== -1) {\n return [this._startVoice(stopped, id), true];\n }\n\n // else, if there are any released notes, find the oldest, start it and return it\n const releasedVoices = this._voices.filter(\n (v) => v?.released !== undefined\n );\n const oldestReleased = findOldestVoiceIndex(releasedVoices);\n if (oldestReleased !== -1) {\n return [this._startVoice(oldestReleased, id), true];\n }\n\n // else, if there are any active notes, find the oldest, start it and return it\n const oldestActive = findOldestVoiceIndex(this._voices);\n if (oldestActive !== -1) {\n return [this._startVoice(oldestActive, id), true];\n }\n\n throw new Error(\"unable to find oldest active voice\");\n }\n\n stop(id: string): Result {\n const started = this._findStarted(id);\n if (started !== -1) {\n this._stopVoice(started);\n }\n return [started, false];\n }\n\n release(id: string, ms: number): Result {\n const started = this._findStarted(id);\n const voiceObject = this._voices[started];\n if (voiceObject) {\n voiceObject.released = setTimeout(() => {\n this._stopVoice(started);\n }, ms);\n }\n return [started, false];\n }\n}\n","import { VoiceAllocator } from \"./voice-allocator\";\nimport type { ParamValueObject, ParamValue } from \"../params\";\n\nexport type ResolveGate<P extends ParamValueObject> = (\n p: Partial<P>\n) => number | undefined;\n\nexport type VoiceControllerConfig<P extends ParamValueObject> = {\n polyphony: number;\n resolveGate: ResolveGate<P>;\n paramCacheSize: number;\n};\n\nexport type VoiceParam<P extends ParamValueObject> = {\n index: number;\n params: Partial<P>;\n};\n\nexport class VoiceController<P extends ParamValueObject> {\n private _polyphony: number;\n private _resolveGate: ResolveGate<P>;\n private _release = 2000;\n private _paramCacheSize: number;\n private _allocator: VoiceAllocator;\n private _allParams: Partial<P> = {};\n private _perVoiceParamsStore = new Map<\n Extract<keyof P, string>,\n Map<string, ParamValue>\n >();\n private _recentlyAccessedIds = new Set<string>();\n\n constructor(config: VoiceControllerConfig<P>) {\n const { polyphony, paramCacheSize, resolveGate } = config;\n this._polyphony = polyphony;\n this._paramCacheSize = paramCacheSize;\n this._resolveGate = resolveGate;\n this._allocator = new VoiceAllocator(polyphony);\n }\n\n private _accessId(id: string) {\n const set = this._recentlyAccessedIds;\n set.delete(id);\n set.add(id);\n\n while (set.size > this._paramCacheSize) {\n const id = set.keys().next().value;\n set.delete(id);\n this._deleteParamsForId(id);\n }\n }\n\n private _getParamsForVoice(id: string): Partial<P> {\n this._accessId(id);\n\n // build up a params object from the nested maps in perVoiceParamsStore\n const out: Partial<P> = {};\n this._perVoiceParamsStore.forEach((subMap, key) => {\n const value = subMap.get(id);\n if (value !== undefined) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n out[key] = value;\n }\n });\n\n return out;\n }\n\n private _addParamForVoice(\n paramKey: Extract<keyof P, string>,\n id: string,\n paramValue: ParamValue\n ) {\n const subMap: Map<string, ParamValue> =\n this._perVoiceParamsStore.get(paramKey) ?? new Map();\n\n subMap.set(id, paramValue);\n this._perVoiceParamsStore.set(paramKey, subMap);\n }\n\n private _addParamsForVoice(id: string, params: Partial<P>) {\n this._accessId(id);\n\n for (const key in params) {\n const value = params[key];\n if (value !== undefined) {\n this._addParamForVoice(key, id, value);\n }\n }\n }\n\n private _deleteParamsForId(id: string) {\n this._perVoiceParamsStore.forEach((subMap) => {\n subMap.delete(id);\n });\n }\n\n setRelease(release: number) {\n this._release = release;\n }\n\n set({ voice, ...params }: Partial<P>): VoiceParam<P>[] {\n if (voice === undefined) {\n return this.setAll(params as Partial<P>);\n }\n return this.setWithId(`${voice}`, params as Partial<P>);\n }\n\n private setWithId(id: string, params: Partial<P>): VoiceParam<P>[] {\n const gate = this._resolveGate(params);\n const { _allocator, _allParams } = this;\n\n // register note event with voice allocator\n // and receive voice index\n let index = -1;\n if (gate !== undefined) {\n [index] =\n gate > 0 ? _allocator.start(id) : _allocator.release(id, this._release);\n } else {\n index = _allocator.get(id);\n }\n if (index === -1) return [];\n\n // merge params\n const perVoiceParams = this._getParamsForVoice(id);\n\n const mergedParams = {\n ..._allParams,\n ...perVoiceParams,\n ...params,\n };\n\n // add them to the per-voice store\n this._addParamsForVoice(id, mergedParams);\n\n // return current state\n return [\n {\n index,\n params: mergedParams,\n },\n ];\n }\n\n private setAll(params: Partial<P>): VoiceParam<P>[] {\n // set all params\n this._allParams = {\n ...this._allParams,\n ...params,\n };\n\n // add / reset any per-voice sub maps\n for (const paramName in params) {\n this._perVoiceParamsStore.set(paramName, new Map());\n }\n\n // return these params for every voice\n const out: VoiceParam<P>[] = [];\n for (let i = 0; i < this._polyphony; i++) {\n out.push({\n index: i,\n params,\n });\n }\n return out;\n }\n}\n","import { DspNodePoly } from \"./dsp-node\";\nimport type { ParamDefinition, DspNode } from \"./dsp-node\";\nimport { VoiceController } from \"./internal/voice-controller\";\n\nexport type PolyParamDefinitionObject = {\n input: DspNode;\n polyphony: number;\n paramCacheSize?: number;\n release: ParamDefinition;\n gate: ParamDefinition;\n};\n\nexport function poly(params: PolyParamDefinitionObject): DspNodePoly {\n const { input, polyphony, paramCacheSize, release, gate } = params;\n return new DspNodePoly({\n input,\n polyphony,\n paramCacheSize,\n release,\n gate,\n dependencies: {\n VoiceController,\n },\n });\n}\n"],"names":[],"mappings":"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"}