<!-- NEW1 — TEST 1 · THE LIVING DISTRICT · part 224 -->
property
	 * on the track before creating the interpolant. The settings should contain:
	 * - `inTangents`: Float32Array with [time, value] pairs per keyframe per component
	 * - `outTangents`: Float32Array with [time, value] pairs per keyframe per component
	 *
	 * @static
	 * @param {TypedArray} [result] - The result buffer.
	 * @return {BezierInterpolant} The new interpolant.
	 */
	InterpolantFactoryMethodBezier( result ) {

		const interpolant = new BezierInterpolant( this.times, this.values, this.getValueSize(), result );

		if ( this.settings ) {

			interpolant.inTangents = this.settings.inTangents;
			interpolant.outTangents = this.settings.outTangents;

		}

		return interpolant;

	}

	/**
	 * Defines the interpolation factor method for this keyframe track.
	 *
	 * @param {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth|InterpolateBezier)} interpolation - The interpolation type.
	 * @return {KeyframeTrack} A reference to this keyframe track.
	 */
	setInterpolation( interpolation ) {

		let factoryMethod;

		switch ( interpolation ) {

			case InterpolateDiscrete:

				factoryMethod = this.InterpolantFactoryMethodDiscrete;

				break;

			case InterpolateLinear:

				factoryMethod = this.InterpolantFactoryMethodLinear;

				break;

			case InterpolateSmooth:

				factoryMethod = this.InterpolantFactoryMethodSmooth;

				break;

			case InterpolateBezier:

				factoryMethod = this.InterpolantFactoryMethodBezier;

				break;

		}

		if ( factoryMethod === undefined ) {

			const message = 'unsupported interpolation for ' +
				this.ValueTypeName + ' keyframe track named ' + this.name;

			if ( this.createInterpolant === undefined ) {

				// fall back to default, unless the default itself is messed up
				if ( interpolation !== this.DefaultInterpolation ) {

					this.setInterpolation( this.DefaultInterpolation );

				} else {

					throw new Error( message ); // fatal, in this case

				}

			}

			warn( 'KeyframeTrack:', message );
			return this;

		}

		this.createInterpolant = factoryMethod;

		return this;

	}

	/**
	 * Returns the current interpolation type.
	 *
	 * @return {(InterpolateLinear|InterpolateDiscrete|InterpolateSmooth|InterpolateBezier)} The interpolation type.
	 */
	getInterpolation() {

		switch ( this.createInterpolant ) {

			case this.InterpolantFactoryMethodDiscrete:

				return InterpolateDiscrete;

			case this.InterpolantFactoryMethodLinear:

				return InterpolateLinear;

			case this.InterpolantFactoryMethodSmooth:

				return InterpolateSmooth;

			case this.InterpolantFactoryMethodBezier:

				return InterpolateBezier;

		}

	}

	/**
	 * Returns the value size.
	 *
	 * @return {number} The value size.
	 */
	getValueSize() {

		return this.values.length / this.times.length;

	}

	/**
	 * Moves all keyframes either forward or backward in time.
	 *
	 * @param {number} timeOffset - The offset to move the time values.
	 * @return {KeyframeTrack} A reference to this keyframe track.
	 */
	shift( timeOffset ) {

		if ( timeOffset !== 0.0 ) {

			const times = this.times;

			for ( let i = 0, n = times.length; i !== n; ++ i ) {

				times[ i ] += timeOffset;

			}

		}

		return this;

	}

	/**
	 * Scale all keyframe times by a factor (useful for frame - seconds conversions).
	 *
	 * @param {number} timeScale - The time scale.
	 * @return {KeyframeTrack} A reference to this keyframe track.
	 */
	scale( timeScale ) {

		if ( timeScale !== 1.0 ) {

			const times = this.times;

			for ( let i = 0, n = times.length; i !== n; ++ i ) {

				times[ i ] *= timeScale;

			}

			if ( hasTangents( this.settings ) ) {

				scaleTangentTimes( this.settings.inTangents, timeScale );
				scaleTangentTimes( this.settings.outTangents, timeScale );

			}

		}

		return this;

	}

	/**
	 * Removes keyframes before and after animation without changing any values within the defined time range.
	 *
	 * Note: The method does not shift around keys to the start of the track time, because for interpolated
	 * keys this will change their values
	 *
	 * @param {number} startTime - The start time.
	 * @param {number} endTime - The end time.
	 * @return {KeyframeTrack} A reference to this keyframe track.
	 */
	trim( startTime, endTime ) {

		const times = this.times,
			nKeys = times.length;

		let from = 0,
			to = nKeys - 1;

		while ( from !== nKeys && times[ from ] < startTime ) {

			++ from;

		}

		while ( to !== -1 && times[ to ] > endTime ) {

			-- to;

		}

		++ to; // inclusive -> exclusive bound

		if ( from !== 0 || to !== nKeys ) {

			// empty tracks are forbidden, so keep at least one keyframe
			if ( from >= to ) {

				to = Math.max( to, 1 );
				from = to - 1;

			}

			const stride = this.getValueSize();
			this.times = times.slice( from, to );
			this.values = this.values.slice( from * stride, to * stride );

		}

		return this;

	}

	/**
	 * Performs minimal validation on the keyframe track. Returns `true` if the valu