optimization by moving child objects into constructor

means that in many cases the param won't be assigned twice
This commit is contained in:
Yotam Mann 2019-08-08 14:15:56 -04:00
parent a7d37ce720
commit 38d6f9d242
12 changed files with 167 additions and 121 deletions

View file

@ -1,6 +1,6 @@
import { Gain } from "../../core/context/Gain";
import { Param } from "../../core/context/Param";
import { ToneAudioNode, ToneAudioNodeOptions } from "../../core/context/ToneAudioNode";
import { InputNode, ToneAudioNode, ToneAudioNodeOptions } from "../../core/context/ToneAudioNode";
import { Decibels } from "../../core/type/Units";
import { optionsFromArguments } from "../../core/util/Defaults";
import { readOnly } from "../../core/util/Interface";
@ -27,16 +27,12 @@ export class Volume extends ToneAudioNode<VolumeOptions> {
/**
* the output node
*/
output: Gain<Decibels> = new Gain({
context: this.context,
gain: 0,
units: "decibels",
});
output: Gain<Decibels>;
/**
* Input and output are the same
*/
input = this.output;
input: Gain;
/**
* The unmuted volume
@ -46,7 +42,7 @@ export class Volume extends ToneAudioNode<VolumeOptions> {
/**
* The volume control in decibels.
*/
volume: Param<Decibels> = this.output.gain;
volume: Param<Decibels>;
constructor(options?: Decibels | Partial<VolumeOptions>);
constructor() {
@ -54,7 +50,12 @@ export class Volume extends ToneAudioNode<VolumeOptions> {
super(optionsFromArguments(Volume.getDefaults(), arguments, ["volume"]));
const options = optionsFromArguments(Volume.getDefaults(), arguments, ["volume"]);
this.volume.setValueAtTime(options.volume, 0);
this.input = this.output = new Gain({
context: this.context,
gain: options.volume,
units: "decibels",
});
this.volume = this.output.gain;
readOnly(this, "volume");
this._unmutedVolume = options.volume;

View file

@ -46,7 +46,6 @@ export class Destination extends ToneAudioNode<DestinationOptions> {
connectSeries(this.input, this.output, this.context.rawContext.destination);
this.volume.setValueAtTime(options.volume, 0);
this.mute = options.mute;
}

View file

@ -49,12 +49,11 @@ export abstract class Instrument<Options extends InstrumentOptions> extends Tone
super(optionsFromArguments(Instrument.getDefaults(), arguments));
const options = optionsFromArguments(Instrument.getDefaults(), arguments);
this._volume = new Volume({
this._volume = this.output = new Volume({
context: this.context,
volume: options.volume,
});
this.volume = this._volume.volume;
this.output = this._volume;
readOnly(this, "volume");
}

View file

@ -1,6 +1,7 @@
import { Signal } from "Tone/signal";
import { AmplitudeEnvelope } from "../component/envelope/AmplitudeEnvelope";
import { Envelope, EnvelopeOptions } from "../component/envelope/Envelope";
import { Time } from "../core/type/Units";
import { Cents, Frequency, Time } from "../core/type/Units";
import { omitFromObject, optionsFromArguments } from "../core/util/Defaults";
import { readOnly } from "../core/util/Interface";
import { RecursivePartial } from "../core/util/Interface";
@ -33,31 +34,35 @@ export class Synth extends Monophonic<SynthOptions> {
/**
* The oscillator.
*/
readonly oscillator = new OmniOscillator({ context: this.context });
readonly oscillator: OmniOscillator<any>;
/**
* The frequency signal
*/
readonly frequency = this.oscillator.frequency;
readonly frequency: Signal<Frequency>;
/**
* The detune signal
*/
readonly detune = this.oscillator.detune;
readonly detune: Signal<Cents>;
/**
* The envelope
*/
readonly envelope: AmplitudeEnvelope = new AmplitudeEnvelope({ context: this.context });
protected _internalChannels = [this.oscillator, this.envelope];
constructor(options?: RecursivePartial<SynthOptions>);
constructor() {
super(optionsFromArguments(Synth.getDefaults(), arguments));
const options = optionsFromArguments(Synth.getDefaults(), arguments);
this.oscillator.set(options.oscillator);
this.oscillator = new OmniOscillator(Object.assign({
context: this.context,
}, options.oscillator));
this.frequency = this.oscillator.frequency;
this.detune = this.oscillator.detune;
this.envelope.set(options.envelope);
// connect the oscillators to the output

View file

@ -1,5 +1,6 @@
import { Volume } from "../component/channel/Volume";
import { ToneAudioNode, ToneAudioNodeOptions } from "../core/context/ToneAudioNode";
import { Param } from "../core/context/Param";
import { OutputNode, ToneAudioNode, ToneAudioNodeOptions } from "../core/context/ToneAudioNode";
import { Decibels, Seconds, Time } from "../core/type/Units";
import { defaultArg, optionsFromArguments } from "../core/util/Defaults";
import { noOp, readOnly } from "../core/util/Interface";
@ -38,17 +39,15 @@ export abstract class Source<Options extends SourceOptions> extends ToneAudioNod
/**
* The output volume node
*/
private _volume: Volume = new Volume({
context: this.context,
});
private _volume: Volume;
/**
* The output note
*/
output = this._volume;
output: OutputNode;
/**
* There is no input
* Sources have no inputs
*/
input = undefined;
@ -57,7 +56,7 @@ export abstract class Source<Options extends SourceOptions> extends ToneAudioNod
* @example
* source.volume.value = -6;
*/
volume = this._volume.volume;
volume: Param<Decibels>;
/**
* Keep track of the scheduled state.
@ -92,12 +91,15 @@ export abstract class Source<Options extends SourceOptions> extends ToneAudioNod
constructor(options: SourceOptions) {
super(options);
readOnly(this, "volume");
this._state.memory = 100;
this.volume.setValueAtTime(options.volume, 0);
// set mute initially
this.mute = options.mute;
this._volume = this.output = new Volume({
context: this.context,
mute: options.mute,
volume: options.volume,
});
this.volume = this._volume.volume;
readOnly(this, "volume");
}
static getDefaults(): SourceOptions {

View file

@ -39,22 +39,22 @@ export class AMOscillator extends Source<AMOscillatorOptions> implements ToneOsc
/**
* The carrier oscillator
*/
private _carrier: Oscillator = new Oscillator({context : this.context });
private _carrier: Oscillator;
/**
* The oscillator's frequency
*/
readonly frequency: Signal<Frequency> = this._carrier.frequency;
readonly frequency: Signal<Frequency>;
/**
* The detune control signal.
*/
readonly detune: Signal<Cents> = this._carrier.detune;
readonly detune: Signal<Cents>;
/**
* The modulating oscillator
*/
private _modulator = new Oscillator({ context : this.context });
private _modulator: Oscillator;
/**
* convert the -1,1 output to 0,1
@ -69,10 +69,7 @@ export class AMOscillator extends Source<AMOscillatorOptions> implements ToneOsc
* //pitch the modulator an octave below carrier
* synth.harmonicity.value = 0.5;
*/
readonly harmonicity: Signal<Positive> = new Multiply({
context: this.context,
units: "positive",
});
readonly harmonicity: Signal<Positive>;
/**
* the node where the modulation happens
@ -88,19 +85,33 @@ export class AMOscillator extends Source<AMOscillatorOptions> implements ToneOsc
super(optionsFromArguments(AMOscillator.getDefaults(), arguments, ["frequency", "type", "modulationType"]));
const options = optionsFromArguments(AMOscillator.getDefaults(), arguments, ["frequency", "type", "modulationType"]);
this._carrier.type = options.type;
this._modulator.type = options.modulationType;
this.frequency.setValueAtTime(options.frequency, 0);
this.detune.setValueAtTime(options.detune, 0);
this.harmonicity.setValueAtTime(options.harmonicity, 0);
this._carrier = new Oscillator({
context : this.context,
detune: options.detune,
frequency: options.frequency,
phase: options.phase,
type: options.type,
} as OscillatorOptions);
this.frequency = this._carrier.frequency,
this.detune = this._carrier.detune;
this._modulator = new Oscillator({
context : this.context,
phase: options.phase,
type: options.modulationType,
} as OscillatorOptions);
this.harmonicity = new Multiply({
context: this.context,
units: "positive",
value: options.harmonicity,
});
// connections
this.frequency.chain(this.harmonicity, this._modulator.frequency);
this._modulator.chain(this._modulationScale, this._modulationNode.gain);
this._carrier.chain(this._modulationNode, this.output);
this.phase = options.phase;
readOnly(this, ["frequency", "detune", "harmonicity"]);
}

View file

@ -37,28 +37,22 @@ export class FMOscillator extends Source<FMOscillatorOptions> implements ToneOsc
/**
* The carrier oscillator
*/
private _carrier: Oscillator = new Oscillator({
context : this.context,
frequency: 0,
});
private _carrier: Oscillator;
/**
* The oscillator's frequency
*/
readonly frequency: Signal<Frequency> = new Signal({
context: this.context,
units: "frequency",
});
readonly frequency: Signal<Frequency>;
/**
* The detune control signal.
*/
readonly detune: Signal<Cents> = this._carrier.detune;
readonly detune: Signal<Cents>;
/**
* The modulating oscillator
*/
private _modulator = new Oscillator({ context : this.context });
private _modulator: Oscillator;
/**
* Harmonicity is the frequency ratio between the carrier and the modulator oscillators.
@ -68,25 +62,19 @@ export class FMOscillator extends Source<FMOscillatorOptions> implements ToneOsc
* //pitch the modulator an octave below carrier
* synth.harmonicity.value = 0.5;
*/
readonly harmonicity: Signal<Positive> = new Multiply({
context: this.context,
units: "positive",
});
readonly harmonicity: Signal<Positive>;
/**
* The modulation index which is in essence the depth or amount of the modulation. In other terms it is the
* ratio of the frequency of the modulating signal (mf) to the amplitude of the
* modulating signal (ma) -- as in ma/mf.
*/
readonly modulationIndex: Signal<Positive> = new Multiply({
context: this.context,
units: "positive",
});
readonly modulationIndex: Signal<Positive>;
/**
* the node where the modulation happens
*/
private _modulationNode = new Gain({
private _modulationNode: Gain = new Gain({
context: this.context,
gain: 0,
});
@ -98,12 +86,39 @@ export class FMOscillator extends Source<FMOscillatorOptions> implements ToneOsc
super(optionsFromArguments(FMOscillator.getDefaults(), arguments, ["frequency", "type", "modulationType"]));
const options = optionsFromArguments(FMOscillator.getDefaults(), arguments, ["frequency", "type", "modulationType"]);
this._carrier.type = options.type;
this._modulator.type = options.modulationType;
this.frequency.setValueAtTime(options.frequency, 0);
this.detune.setValueAtTime(options.detune, 0);
this.harmonicity.setValueAtTime(options.harmonicity, 0);
this.modulationIndex.setValueAtTime(options.modulationIndex, 0);
this._carrier = new Oscillator({
context : this.context,
detune: options.detune,
frequency: 0,
phase: options.phase,
type: options.type,
} as OscillatorOptions);
this.detune = this._carrier.detune;
this.frequency = new Signal({
context: this.context,
units: "frequency",
value: options.frequency,
});
this._modulator = new Oscillator({
context : this.context,
phase: options.phase,
type: options.modulationType,
} as OscillatorOptions);
this.harmonicity = new Multiply({
context: this.context,
units: "positive",
value: options.harmonicity,
});
this.modulationIndex = new Multiply({
context: this.context,
units: "positive",
value: options.modulationIndex,
});
// connections
this.frequency.connect(this._carrier.frequency);
@ -114,8 +129,6 @@ export class FMOscillator extends Source<FMOscillatorOptions> implements ToneOsc
this._carrier.connect(this.output);
this.detune.connect(this._modulator.detune);
this.phase = options.phase;
readOnly(this, ["modulationIndex", "frequency", "detune", "harmonicity"]);
}

View file

@ -24,18 +24,12 @@ export class FatOscillator extends Source<FatOscillatorOptions> implements ToneO
/**
* The oscillator's frequency
*/
readonly frequency: Signal<Frequency> = new Signal<Cents>({
context: this.context,
units: "frequency",
});
readonly frequency: Signal<Frequency>;
/**
* The detune control signal.
*/
readonly detune: Signal<Cents> = new Signal<Cents>({
context: this.context,
units: "cents",
});
readonly detune: Signal<Cents>;
/**
* The array of oscillators
@ -74,8 +68,16 @@ export class FatOscillator extends Source<FatOscillatorOptions> implements ToneO
super(optionsFromArguments(FatOscillator.getDefaults(), arguments, ["frequency", "type", "spread"]));
const options = optionsFromArguments(FatOscillator.getDefaults(), arguments, ["frequency", "type", "spread"]);
this.frequency.setValueAtTime(options.frequency, 0);
this.detune.setValueAtTime(options.detune, 0);
this.frequency = new Signal({
context: this.context,
units: "frequency",
value: options.frequency,
});
this.detune = new Signal({
context: this.context,
units: "cents",
value: options.detune,
});
this._spread = options.spread;
this._type = options.type;
@ -168,7 +170,6 @@ export class FatOscillator extends Source<FatOscillatorOptions> implements ToneO
get count(): number {
return this._oscillators.length;
}
set count(count: number) {
count = Math.max(count, 1);
if (this._oscillators.length !== count) {

View file

@ -1,5 +1,5 @@
import { AudioRange, Cents, Degrees, Frequency, Positive, Time } from "../../core/type/Units";
import { optionsFromArguments } from "../../core/util/Defaults";
import { optionsFromArguments } from "../../core/util/Defaults";
import { readOnly } from "../../core/util/Interface";
import { isNumber, isString } from "../../core/util/TypeCheck";
import { Signal } from "../../signal/Signal";
@ -105,18 +105,12 @@ implements Omit<ToneOscillatorInterface, "type"> {
/**
* The frequency control.
*/
readonly frequency: Signal<Frequency> = new Signal({
context: this.context,
units: "frequency",
});
readonly frequency: Signal<Frequency>;
/**
* The detune control.
*/
readonly detune: Signal<Cents> = new Signal<Cents>({
context: this.context,
units: "cents",
});
readonly detune: Signal<Cents>;
/**
* The oscillator that can switch types
@ -135,8 +129,16 @@ implements Omit<ToneOscillatorInterface, "type"> {
super(optionsFromArguments(OmniOscillator.getDefaults(), arguments, ["frequency", "type"]));
const options = optionsFromArguments(OmniOscillator.getDefaults(), arguments, ["frequency", "type"]);
this.frequency.setValueAtTime(options.frequency, 0);
this.detune.setValueAtTime(options.detune, 0);
this.frequency = new Signal({
context: this.context,
value: options.frequency,
units: "frequency",
});
this.detune = new Signal({
context: this.context,
value: options.detune,
units: "cents",
});
readOnly(this, ["frequency", "detune"]);
// set the options
@ -152,7 +154,6 @@ implements Omit<ToneOscillatorInterface, "type"> {
PulseOscillator.getDefaults(),
PWMOscillator.getDefaults(),
);
// return Oscillator.getDefaults() as OmniOscillatorConstructorOptions;
}
/**

View file

@ -57,7 +57,7 @@ export class ToneOscillatorNode extends OneShotSource<ToneOscillatorNodeOptions>
context: this.context,
param : this._oscillator.frequency,
units : "frequency",
value : this.toFrequency(options.frequency),
value : options.frequency,
});
this.detune = new Param({

View file

@ -28,13 +28,11 @@ export class PWMOscillator extends Source<PWMOscillatorOptions> implements ToneO
/**
* the pulse oscillator
*/
private _pulse: PulseOscillator = new PulseOscillator({ context: this.context });
private _pulse: PulseOscillator;
/**
* the modulator
* @type {Tone.Oscillator}
* @private
*/
private _modulator: Oscillator = new Oscillator({ context: this.context });
private _modulator: Oscillator;
/**
* Scale the oscillator so it doesn't go silent
@ -48,17 +46,17 @@ export class PWMOscillator extends Source<PWMOscillatorOptions> implements ToneO
/**
* The frequency control.
*/
readonly frequency: Signal<Frequency> = this._modulator.frequency;
readonly frequency: Signal<Frequency>;
/**
* The detune of the oscillator.
*/
readonly detune: Signal<Cents> = this._modulator.detune;
readonly detune: Signal<Cents>;
/**
* The modulation rate of the oscillator.
*/
readonly modulationFrequency: Signal<Frequency> = this._pulse.frequency;
readonly modulationFrequency: Signal<Frequency>;
constructor(options?: Partial<PWMOscillatorOptions>);
constructor(frequency?: Frequency, modulationFrequency?: Frequency);
@ -66,14 +64,25 @@ export class PWMOscillator extends Source<PWMOscillatorOptions> implements ToneO
super(optionsFromArguments(PWMOscillator.getDefaults(), arguments, ["frequency", "modulationFrequency"]));
const options = optionsFromArguments(PWMOscillator.getDefaults(), arguments, ["frequency", "modulationFrequency"]);
this._pulse = new PulseOscillator({
context: this.context,
frequency: options.modulationFrequency,
});
// change the pulse oscillator type
// @ts-ignore
this._pulse._sawtooth.type = "sine";
this._pulse.frequency.setValueAtTime(options.modulationFrequency, 0);
this._modulator.frequency.setValueAtTime(options.frequency, 0);
this._modulator.detune.setValueAtTime(options.detune, 0);
this._modulator.phase = options.phase;
this.modulationFrequency = this._pulse.frequency;
this._modulator = new Oscillator({
context: this.context,
detune: options.detune,
frequency: options.frequency,
phase: options.phase,
});
this.frequency = this._modulator.frequency;
this.detune = this._modulator.detune;
// connections
this._modulator.chain(this._scale, this._pulse.width);

View file

@ -49,10 +49,7 @@ export class PulseOscillator extends Source<PulseOscillatorOptions> implements T
/**
* The width of the pulse.
*/
width: Signal<AudioRange> = new Signal<AudioRange>({
context: this.context,
units: "audioRange",
});
width: Signal<AudioRange>;
/**
* gate the width amount
@ -65,20 +62,17 @@ export class PulseOscillator extends Source<PulseOscillatorOptions> implements T
/**
* the sawtooth oscillator
*/
private _sawtooth: Oscillator = new Oscillator({
context: this.context,
type : "sawtooth",
});
private _sawtooth: Oscillator;
/**
* The frequency control.
*/
frequency: Signal<Frequency> = this._sawtooth.frequency;
frequency: Signal<Frequency>;
/**
* The detune in cents.
*/
detune: Signal<Cents> = this._sawtooth.detune;
detune: Signal<Cents>;
/**
* Threshold the signal to turn it into a square
@ -95,10 +89,21 @@ export class PulseOscillator extends Source<PulseOscillatorOptions> implements T
super(optionsFromArguments(PulseOscillator.getDefaults(), arguments, ["frequency", "width"]));
const options = optionsFromArguments(PulseOscillator.getDefaults(), arguments, ["frequency", "width"]);
this.width.setValueAtTime(options.width, 0);
this._sawtooth.frequency.setValueAtTime(options.frequency, 0);
this._sawtooth.detune.setValueAtTime(options.detune, 0);
this._sawtooth.phase = options.phase;
this.width = new Signal({
context: this.context,
units: "audioRange",
value: options.width,
});
this._sawtooth = new Oscillator({
context: this.context,
detune: options.detune,
frequency: options.frequency,
phase: options.phase,
type : "sawtooth",
});
this.frequency = this._sawtooth.frequency;
this.detune = this._sawtooth.detune;
// connections
this._sawtooth.chain(this._thresh, this.output);