docs: function Source(scene, options) {
    // Public variables.
    /**
     * Mono (1-channel) input {@link
     * https://developer.mozilla.org/en-US/docs/Web/API/AudioNode AudioNode}.
     * @member {AudioNode} input
     * @memberof Source
     * @instance
     */
    /**
     *
     */
  
    // Use defaults for undefined arguments.
    if (options == undefined) {
      options = {};
    }
    if (options.position == undefined) {
      options.position = Utils.DEFAULT_POSITION.slice();
    }
    if (options.forward == undefined) {
      options.forward = Utils.DEFAULT_FORWARD.slice();
    }
    if (options.up == undefined) {
      options.up = Utils.DEFAULT_UP.slice();
    }
    if (options.minDistance == undefined) {
      options.minDistance = Utils.DEFAULT_MIN_DISTANCE;
    }
    if (options.maxDistance == undefined) {
      options.maxDistance = Utils.DEFAULT_MAX_DISTANCE;
    }
    if (options.rolloff == undefined) {
      options.rolloff = Utils.DEFAULT_ROLLOFF;
    }
    if (options.gain == undefined) {
      options.gain = Utils.DEFAULT_SOURCE_GAIN;
    }
    if (options.alpha == undefined) {
      options.alpha = Utils.DEFAULT_DIRECTIVITY_ALPHA;
    }
    if (options.sharpness == undefined) {
      options.sharpness = Utils.DEFAULT_DIRECTIVITY_SHARPNESS;
    }
    if (options.sourceWidth == undefined) {
      options.sourceWidth = Utils.DEFAULT_SOURCE_WIDTH;
    }
  
    // Member variables.
    this._scene = scene;
    this._position = options.position;
    this._forward = options.forward;
    this._up = options.up;
    this._dx = new Float32Array(3);
    this._right = Utils.crossProduct(this._forward, this._up);
  
    // Create audio nodes.
    let context = scene._context;
    this.input = context.createGain();
    this._directivity = new Directivity(context, {
      alpha: options.alpha,
      sharpness: options.sharpness,
    });
    this._toEarly = context.createGain();
    this._toLate = context.createGain();
    this._attenuation = new Attenuation(context, {
      minDistance: options.minDistance,
      maxDistance: options.maxDistance,
      rolloff: options.rolloff,
    });
    this._encoder = new Encoder(context, {
      ambisonicOrder: scene._ambisonicOrder,
      sourceWidth: options.sourceWidth,
    });
  
    // Connect nodes.
    this.input.connect(this._toLate);
    this._toLate.connect(scene._room.late.input);
  
    this.input.connect(this._attenuation.input);
    this._attenuation.output.connect(this._toEarly);
    this._toEarly.connect(scene._room.early.input);
  
    this._attenuation.output.connect(this._directivity.input);
    this._directivity.output.connect(this._encoder.input);
  
    this._encoder.output.connect(scene._listener.input);
  
    // Assign initial conditions.
    this.setPosition(
      options.position[0], options.position[1], options.position[2]);
    this.input.gain.value = options.gain;
  }