@polygonjs/polygonjs
Version:
node-based WebGL 3D engine https://polygonjs.com
112 lines (101 loc) • 3.02 kB
text/typescript
/**
* Phaser is a phaser effect. Phasers work by changing the phase
* of different frequency components of an incoming signal. Read more on
* [Wikipedia](https://en.wikipedia.org/wiki/Phaser_(effect)).
* Inspiration for this phaser comes from [Tuna.js](https://github.com/Dinahmoe/tuna/).
*
* See description on [Tone.js](https://tonejs.github.io/)
*/
import {Phaser} from 'tone/build/esm/effect/Phaser';
const DEFAULTS = {
Q: 10,
baseFrequency: 350,
frequency: 0.5,
octaves: 3,
stages: 10,
}; //Phaser.getDefaults();
import {TypedAudioNode} from './_Base';
import {NodeParamsConfig, ParamConfig} from '../utils/params/ParamsConfig';
import {AudioBuilder} from '../../../core/audio/AudioBuilder';
import {BaseNodeType} from '../_Base';
import {effectParamsOptions} from './utils/EffectsController';
const paramCallback = (node: BaseNodeType) => {
PhaserAudioNode.PARAM_CALLBACK_updateEffect(node as PhaserAudioNode);
};
class PhaserAudioParamsConfig extends NodeParamsConfig {
/** @param frequency */
frequency = ParamConfig.FLOAT(DEFAULTS.frequency, {
range: [0, 1000],
rangeLocked: [true, false],
});
/** @param baseFrequency */
baseFrequency = ParamConfig.FLOAT(DEFAULTS.baseFrequency, {
range: [0, 1000],
rangeLocked: [true, false],
...effectParamsOptions(paramCallback),
});
/** @param octaves */
octaves = ParamConfig.FLOAT(DEFAULTS.octaves, {
range: [0, 10],
rangeLocked: [true, false],
...effectParamsOptions(paramCallback),
});
/** @param sensitivity */
stages = ParamConfig.FLOAT(DEFAULTS.stages, {
range: [0, 1],
rangeLocked: [true, false],
});
/** @param Q */
Q = ParamConfig.FLOAT(DEFAULTS.Q, {
range: [0, 1],
rangeLocked: [true, false],
});
}
const ParamsConfig = new PhaserAudioParamsConfig();
export class PhaserAudioNode extends TypedAudioNode<PhaserAudioParamsConfig> {
override paramsConfig = ParamsConfig;
static override type() {
return 'phaser';
}
override initializeNode() {
this.io.inputs.setCount(1);
}
override cook(inputContents: AudioBuilder[]) {
const audioBuilder = inputContents[0];
this._resetEffect();
const effect = this._effect();
const inputNode = audioBuilder.audioNode();
if (inputNode) {
inputNode.connect(effect);
}
audioBuilder.setAudioNode(effect);
this.setAudioBuilder(audioBuilder);
}
private __effect__: Phaser | undefined;
private _effect() {
return (this.__effect__ = this.__effect__ || this._createEffect());
}
private _createEffect() {
return new Phaser({
frequency: this.pv.frequency,
baseFrequency: this.pv.baseFrequency,
octaves: this.pv.octaves,
stages: this.pv.stages,
Q: this.pv.Q,
});
}
private _resetEffect() {
if (this.__effect__) {
this.__effect__.dispose();
this.__effect__ = undefined;
}
}
static PARAM_CALLBACK_updateEffect(node: PhaserAudioNode) {
node._updateEffect();
}
private _updateEffect() {
const effect = this._effect();
effect.baseFrequency = this.pv.baseFrequency;
effect.octaves = this.pv.octaves;
}
}