UNPKG

@polygonjs/polygonjs

Version:

node-based WebGL 3D engine https://polygonjs.com

182 lines (181 loc) 5.29 kB
"use strict"; import { NodeParamsConfig, ParamConfig } from "../utils/params/ParamsConfig"; import { Meter } from "tone/build/esm/component/analysis/Meter"; import { AudioNodeAnalyserType } from "../../poly/NodeContext"; import { isNumber, isBooleanTrue } from "../../../core/Type"; import { effectParamsOptions } from "./utils/EffectsController"; import { BaseAnalyserAudioNode } from "./_BaseAnalyser"; const DEFAULTS = { smoothing: 0.8 }; const paramCallback = (node) => { MeterAudioNode.PARAM_CALLBACK_updateEffect(node); }; const RANGE_DEFAULT = [1e4, -1e4]; class MeterAudioParamsConfig extends NodeParamsConfig { constructor() { super(...arguments); /** @param a value from between 0 and 1 where 0 represents no time averaging with the last analysis frame */ this.smoothing = ParamConfig.FLOAT(DEFAULTS.smoothing, { range: [0, 1], rangeLocked: [true, true], ...effectParamsOptions(paramCallback) }); /** @param normalizes the output between 0 and 1. The value will be in decibel otherwise. */ this.normalRange = ParamConfig.BOOLEAN(1, effectParamsOptions(paramCallback)); /** @param display meter param */ this.updateValueParam = ParamConfig.BOOLEAN(1, { cook: false, callback: (node) => { MeterAudioNode.PARAM_CALLBACK_updateUpdateMeterParam(node); } }); /** @param meter value */ this.value = ParamConfig.FLOAT(0, { visibleIf: { updateValueParam: 1 }, range: [-100, 100], editable: false, cook: false }); /** @param display meter param */ this.updateRangeParam = ParamConfig.BOOLEAN(1, { cook: false, callback: (node) => { MeterAudioNode.PARAM_CALLBACK_updateUpdateMeterParam(node); } }); /** @param accumulated range */ this.maxRange = ParamConfig.VECTOR2([1e4, -1e4], { visibleIf: { updateRangeParam: 1 }, editable: false, cook: false }); /** @param resetMaxRange */ this.resetMaxRange = ParamConfig.BUTTON(null, { visibleIf: { updateRangeParam: 1 }, callback: (node) => { MeterAudioNode.PARAM_CALLBACK_resetMaxRange(node); } }); } } const ParamsConfig = new MeterAudioParamsConfig(); export class MeterAudioNode extends BaseAnalyserAudioNode { constructor() { super(...arguments); this.paramsConfig = ParamsConfig; this._arrayValue = new Float32Array(1); } static type() { return AudioNodeAnalyserType.METER; } initializeNode() { this.io.inputs.setCount(1); } cook(inputContents) { const audioBuilder = inputContents[0]; this._resetEffect(); const meter = this._effect(); this._updateOnTickHook(); const inputNode = audioBuilder.audioNode(); if (inputNode) { inputNode.connect(meter); } audioBuilder.setAudioNode(meter); this.setAudioBuilder(audioBuilder); } getAnalyserValue() { if (this.__effect__) { const value = this.__effect__.getValue(); if (isNumber(value)) { this._arrayValue[0] = value; return this._arrayValue; } else { return value; } } } _effect() { return this.__effect__ = this.__effect__ || this._createEffect(); } _createEffect() { return new Meter({ smoothing: this.pv.smoothing, normalRange: isBooleanTrue(this.pv.normalRange) }); } _resetEffect() { if (this.__effect__) { this.__effect__.dispose(); this.__effect__ = void 0; } } static PARAM_CALLBACK_updateEffect(node) { node._updateEffect(); } _updateEffect() { const effect = this._effect(); effect.normalRange = isBooleanTrue(this.pv.normalRange); effect.smoothing = this.pv.smoothing; } /* * UPDATE METER PARAM */ static PARAM_CALLBACK_updateUpdateMeterParam(node) { node._updateMeterParam(); node._updateOnTickHook(); } static PARAM_CALLBACK_resetMaxRange(node) { node.p.maxRange.set(RANGE_DEFAULT); } _updateMeterParam() { if (!this.__effect__) { return; } const value = this.getAnalyserValue(); if (!value) { return; } const valueN = value[0]; if (!isFinite(valueN)) { return; } if (isBooleanTrue(this.pv.updateValueParam)) { if (isNumber(valueN)) { this.p.value.set(valueN); } } if (isBooleanTrue(this.pv.updateRangeParam)) { const newVal = valueN; if (newVal < this.pv.maxRange.x) { this.p.maxRange.x.set(newVal); } else { if (newVal > this.pv.maxRange.y) { this.p.maxRange.y.set(newVal); } } } } /* * REGISTER TICK CALLBACK */ _updateOnTickHook() { if (isBooleanTrue(this.pv.updateValueParam) || isBooleanTrue(this.pv.updateRangeParam)) { this._registerOnTickHook(); } else { this._unRegisterOnTickHook(); } } async _registerOnTickHook() { if (this.scene().registeredBeforeTickCallbacks().has(this._tickCallbackName())) { return; } this.scene().registerOnBeforeTick(this._tickCallbackName(), this._updateMeterParam.bind(this)); } async _unRegisterOnTickHook() { this.scene().unRegisterOnBeforeTick(this._tickCallbackName()); } _tickCallbackName() { return `audio/Meter-${this.graphNodeId()}`; } }