UNPKG

3.62 kBJavaScriptView Raw
1import { optionsFromArguments } from "../core/util/Defaults.js";
2import { isArray, isFunction } from "../core/util/TypeCheck.js";
3import { assert } from "../core/util/Debug.js";
4import { Signal } from "./Signal.js";
5import { SignalOperator } from "./SignalOperator.js";
6/**
7 * Wraps the native Web Audio API
8 * [WaveShaperNode](http://webaudio.github.io/web-audio-api/#the-waveshapernode-interface).
9 *
10 * @example
11 * const osc = new Tone.Oscillator().toDestination().start();
12 * // multiply the output of the signal by 2 using the waveshaper's function
13 * const timesTwo = new Tone.WaveShaper((val) => val * 2, 2048).connect(osc.frequency);
14 * const signal = new Tone.Signal(440).connect(timesTwo);
15 * @category Signal
16 */
17export class WaveShaper extends SignalOperator {
18 constructor() {
19 const options = optionsFromArguments(WaveShaper.getDefaults(), arguments, ["mapping", "length"]);
20 super(options);
21 this.name = "WaveShaper";
22 /**
23 * the waveshaper node
24 */
25 this._shaper = this.context.createWaveShaper();
26 /**
27 * The input to the waveshaper node.
28 */
29 this.input = this._shaper;
30 /**
31 * The output from the waveshaper node
32 */
33 this.output = this._shaper;
34 if (isArray(options.mapping) ||
35 options.mapping instanceof Float32Array) {
36 this.curve = Float32Array.from(options.mapping);
37 }
38 else if (isFunction(options.mapping)) {
39 this.setMap(options.mapping, options.length);
40 }
41 }
42 static getDefaults() {
43 return Object.assign(Signal.getDefaults(), {
44 length: 1024,
45 });
46 }
47 /**
48 * Uses a mapping function to set the value of the curve.
49 * @param mapping The function used to define the values.
50 * The mapping function take two arguments:
51 * the first is the value at the current position
52 * which goes from -1 to 1 over the number of elements
53 * in the curve array. The second argument is the array position.
54 * @example
55 * const shaper = new Tone.WaveShaper();
56 * // map the input signal from [-1, 1] to [0, 10]
57 * shaper.setMap((val, index) => (val + 1) * 5);
58 */
59 setMap(mapping, length = 1024) {
60 const array = new Float32Array(length);
61 for (let i = 0, len = length; i < len; i++) {
62 const normalized = (i / (len - 1)) * 2 - 1;
63 array[i] = mapping(normalized, i);
64 }
65 this.curve = array;
66 return this;
67 }
68 /**
69 * The array to set as the waveshaper curve. For linear curves
70 * array length does not make much difference, but for complex curves
71 * longer arrays will provide smoother interpolation.
72 */
73 get curve() {
74 return this._shaper.curve;
75 }
76 set curve(mapping) {
77 this._shaper.curve = mapping;
78 }
79 /**
80 * Specifies what type of oversampling (if any) should be used when
81 * applying the shaping curve. Can either be "none", "2x" or "4x".
82 */
83 get oversample() {
84 return this._shaper.oversample;
85 }
86 set oversample(oversampling) {
87 const isOverSampleType = ["none", "2x", "4x"].some((str) => str.includes(oversampling));
88 assert(isOverSampleType, "oversampling must be either 'none', '2x', or '4x'");
89 this._shaper.oversample = oversampling;
90 }
91 /**
92 * Clean up.
93 */
94 dispose() {
95 super.dispose();
96 this._shaper.disconnect();
97 return this;
98 }
99}
100//# sourceMappingURL=WaveShaper.js.map
\No newline at end of file