<!-- NEW2 — TEST 2 · THE DISTRICT OF 800 · part 267 -->
he array represents the decibel value for a specific frequency.
	 * The frequencies are spread linearly from 0 to 1/2 of the sample rate.
	 * For example, for 48000 sample rate, the last item of the array will represent
	 * the decibel value for 24000 Hz.
	 *
	 * @return {Uint8Array} The frequency data.
	 */
	getFrequencyData() {

		this.analyser.getByteFrequencyData( this.data );

		return this.data;

	}

	/**
	 * Returns the average of the frequencies returned by {@link AudioAnalyser#getFrequencyData}.
	 *
	 * @return {number} The average frequency.
	 */
	getAverageFrequency() {

		let value = 0;
		const data = this.getFrequencyData();

		for ( let i = 0; i < data.length; i ++ ) {

			value += data[ i ];

		}

		return value / data.length;

	}

}

/**
 * Buffered scene graph property that allows weighted accumulation; used internally.
 */
class PropertyMixer {

	/**
	 * Constructs a new property mixer.
	 *
	 * @param {PropertyBinding} binding - The property binding.
	 * @param {string} typeName - The keyframe track type name.
	 * @param {number} valueSize - The keyframe track value size.
	 */
	constructor( binding, typeName, valueSize ) {

		/**
		 * The property binding.
		 *
		 * @type {PropertyBinding}
		 */
		this.binding = binding;

		/**
		 * The keyframe track value size.
		 *
		 * @type {number}
		 */
		this.valueSize = valueSize;

		let mixFunction,
			mixFunctionAdditive,
			setIdentity;

		// buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ]
		//
		// interpolators can use .buffer as their .result
		// the data then goes to 'incoming'
		//
		// 'accu0' and 'accu1' are used frame-interleaved for
		// the cumulative result and are compared to detect
		// changes
		//
		// 'orig' stores the original state of the property
		//
		// 'add' is used for additive cumulative results
		//
		// 'work' is optional and is only present for quaternion types. It is used
		// to store intermediate quaternion multiplication results

		switch ( typeName ) {

			case 'quaternion':
				mixFunction = this._slerp;
				mixFunctionAdditive = this._slerpAdditive;
				setIdentity = this._setAdditiveIdentityQuaternion;

				this.buffer = new Float64Array( valueSize * 6 );
				this._workIndex = 5;
				break;

			case 'string':
			case 'bool':
				mixFunction = this._select;

				// Use the regular mix function and for additive on these types,
				// additive is not relevant for non-numeric types
				mixFunctionAdditive = this._select;

				setIdentity = this._setAdditiveIdentityOther;

				this.buffer = new Array( valueSize * 5 );
				break;

			default:
				mixFunction = this._lerp;
				mixFunctionAdditive = this._lerpAdditive;
				setIdentity = this._setAdditiveIdentityNumeric;

				this.buffer = new Float64Array( valueSize * 5 );

		}

		this._mixBufferRegion = mixFunction;
		this._mixBufferRegionAdditive = mixFunctionAdditive;
		this._setIdentity = setIdentity;
		this._origIndex = 3;
		this._addIndex = 4;

		/**
		 * Accumulated weight of the property binding.
		 *
		 * @type {number}
		 * @default 0
		 */
		this.cumulativeWeight = 0;

		/**
		 * Accumulated additive weight of the property binding.
		 *
		 * @type {number}
		 * @default 0
		 */
		this.cumulativeWeightAdditive = 0;

		/**
		 * Number of active keyframe tracks currently using this property binding.
		 *
		 * @type {number}
		 * @default 0
		 */
		this.useCount = 0;

		/**
		 * Number of keyframe tracks referencing this property binding.
		 *
		 * @type {number}
		 * @default 0
		 */
		this.referenceCount = 0;

	}

	/**
	 * Accumulates data in the `incoming` region into `accu<i>`.
	 *
	 * @param {number} accuIndex - The accumulation index.
	 * @param {number} weight - The weight.
	 */
	accumulate( accuIndex, weight ) {

		// note: happily accumulating nothing when weight = 0, the caller knows
		// the weight and shouldn't have made the call in the first place

		const buffer = this.buffer,
			stride = this.valueSize,
			offset = accuIndex * stride + stride;

		let currentWeight = this.cumulativeWeight;

		if ( currentWeight === 0 ) {

			// accuN := incoming * weight

			for ( let i = 0; i !== stride; ++ i ) {

				buffer[ offset + i ] = buffer[ i ];

			}

			currentWeight = weight;

		} else {

			// accuN := accuN + incoming * weight

			currentWeight += weight;
			const mix = weight / currentWeight;
			this._mixBufferRegion( buffer, offset, 0, mix, stride );

		}

		this.cumulativeWeight = currentWeight;

	}

	/**
	 * Accumulates data in the `incoming` region into `add`.
	 *
	 * @param {number} weight - The weight.
	 */
	accumulateAdditive( weight ) {

		const buffer = this.buffer,
			stride = this.valueSize,
			offset = stride * this._addIndex;

		if ( this.cumulativeWeightAdditive === 0 ) {

			// add = identity

			this._setIdentity();

		}

		// add := add + incoming * weight

		this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride );
		this.cumulative