UNPKG

wam-community

Version:

A collection of prebuilt Web Audio Modules ready for use

127 lines (117 loc) 4.27 kB
/** @typedef {import('@webaudiomodules/api').WamParameterConfiguration} WamParameterConfiguration */ /** @typedef {import('@webaudiomodules/api').WamParameterInfoMap} WamParameterInfoMap */ /** @typedef {import('./types').ParametersMapping} ParametersMapping */ /** @typedef {import('./types').InternalParametersDescriptor} InternalParametersDescriptor */ /** @typedef {import('./types').ParametersMappingConfiguratorOptions} ParametersMappingConfiguratorOptions */ import getWamParameterInfo from './sdk/src/WamParameterInfo.js'; const WamParameterInfo = getWamParameterInfo(); export default class ParamMappingConfigurator { /** * @param {ParametersMappingConfiguratorOptions} [options = {}] */ constructor(options = {}) { const { paramsConfig, paramsMapping, internalParamsConfig } = options; this._paramsConfig = paramsConfig; this._paramsMapping = paramsMapping; this._internalParamsConfig = internalParamsConfig; } /** * @private * @type {Record<string, WamParameterConfiguration>} */ _paramsConfig = undefined; /** * Auto-completed `paramsConfig`: * * if no `paramsConfig` is defined while initializing, this will be be filled from the internalParamsConfig; * * if a parameter is not fully configured, the incompleted properties will have the same value as in the internalParamsConfig. * * @type {WamParameterInfoMap} */ get paramsConfig() { const { internalParamsConfig } = this; return Object.entries(this._paramsConfig || internalParamsConfig) .reduce((configs, [id, config]) => { const internalParam = internalParamsConfig[id]; configs[id] = new WamParameterInfo(id, { ...config, label: config.label ?? id, defaultValue: config.defaultValue ?? internalParam?.defaultValue, minValue: config.minValue ?? internalParam?.minValue, maxValue: config.maxValue ?? internalParam?.maxValue, }); return configs; }, {}); } /** * @private * @type {InternalParametersDescriptor} */ _internalParamsConfig = undefined; /** * Auto-completed configuration of the `internalParamsConfig` * * Internal Parameters Config contains all the automatable parameters' information. * * An automatable parameter could be a `WebAudio` `AudioParam` * or a config with an `onChange` callback that will be called while the value has been changed. * * @type {InternalParametersDescriptor} */ get internalParamsConfig() { return Object.entries(this._internalParamsConfig || {}) .reduce((configs, [name, config]) => { if (config instanceof AudioParam) configs[name] = config; else { const defaultConfig = { minValue: 0, maxValue: 1, defaultValue: 0, automationRate: 30, }; configs[name] = { ...defaultConfig, ...config }; } return configs; }, {}); } /** * @private * @type {ParametersMapping} */ _paramsMapping = {} /** * Auto-completed `paramsMapping`, * the mapping can be omitted while initialized, * but is useful when an exposed param (in the `paramsConfig`) should automate * several internal params (in the `internalParamsConfig`) or has a different range there. * * If a parameter is present in both `paramsConfig` and `internalParamsConfig` (or the `paramsConfig` is not configured), * a map of this parameter will be there automatically, if not declared explicitly. * * @type {ParametersMapping} */ get paramsMapping() { const declared = this._paramsMapping || {}; const externalParams = this.paramsConfig; const internalParams = this.internalParamsConfig; return Object.entries(externalParams) .reduce((mapping, [name, { minValue, maxValue }]) => { const sourceRange = [minValue, maxValue]; const defaultMapping = { sourceRange, targetRange: [...sourceRange] }; if (declared[name]) { const declaredTargets = Object.entries(declared[name]) .reduce((targets, [targetName, targetMapping]) => { if (internalParams[targetName]) { targets[targetName] = { ...defaultMapping, ...targetMapping }; } return targets; }, {}); mapping[name] = declaredTargets; } else if (internalParams[name]) { mapping[name] = { [name]: { ...defaultMapping } }; } return mapping; }, {}); } }