@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
182 lines (181 loc) • 5.29 kB
JavaScript
"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()}`;
}
}