assassin-bug/framework/resonator/vendor/resonance-es6/attenuation.js

152 lines
5.5 KiB
JavaScript

/**
* @license
* Copyright 2017 Google Inc. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file Distance-based attenuation filter.
* @author Andrew Allen <bitllama@google.com>
*/
'use strict';
// Internal dependencies.
import Utils from './utils.js';
/**
* @class Attenuation
* @description Distance-based attenuation filter.
* @param {AudioContext} context
* Associated {@link
https://developer.mozilla.org/en-US/docs/Web/API/AudioContext AudioContext}.
* @param {Object} options
* @param {Number} options.minDistance
* Min. distance (in meters). Defaults to
* {@linkcode Utils.DEFAULT_MIN_DISTANCE DEFAULT_MIN_DISTANCE}.
* @param {Number} options.maxDistance
* Max. distance (in meters). Defaults to
* {@linkcode Utils.DEFAULT_MAX_DISTANCE DEFAULT_MAX_DISTANCE}.
* @param {string} options.rolloff
* Rolloff model to use, chosen from options in
* {@linkcode Utils.ATTENUATION_ROLLOFFS ATTENUATION_ROLLOFFS}. Defaults to
* {@linkcode Utils.DEFAULT_ATTENUATION_ROLLOFF DEFAULT_ATTENUATION_ROLLOFF}.
*/
class Attenuation {
constructor(context, options) {
// Public variables.
/**
* Min. distance (in meters).
* @member {Number} minDistance
* @memberof Attenuation
* @instance
*/
/**
* Max. distance (in meters).
* @member {Number} maxDistance
* @memberof Attenuation
* @instance
*/
/**
* Mono (1-channel) input {@link
* https://developer.mozilla.org/en-US/docs/Web/API/AudioNode AudioNode}.
* @member {AudioNode} input
* @memberof Attenuation
* @instance
*/
/**
* Mono (1-channel) output {@link
* https://developer.mozilla.org/en-US/docs/Web/API/AudioNode AudioNode}.
* @member {AudioNode} output
* @memberof Attenuation
* @instance
*/
// Use defaults for undefined arguments.
if (options == undefined) {
options = {};
}
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_ATTENUATION_ROLLOFF;
}
// Assign values.
this.minDistance = options.minDistance;
this.maxDistance = options.maxDistance;
this.setRolloff(options.rolloff);
// Create node.
this._gainNode = context.createGain();
// Initialize distance to max distance.
this.setDistance(options.maxDistance);
// Input/Output proxy.
this.input = this._gainNode;
this.output = this._gainNode;
}
/**
* Set distance from the listener.
* @param {Number} distance Distance (in meters).
*/
setDistance(distance) {
let gain = 1;
if (this._rolloff == 'logarithmic') {
if (distance > this.maxDistance) {
gain = 0;
}
else if (distance > this.minDistance) {
let range = this.maxDistance - this.minDistance;
if (range > Utils.EPSILON_FLOAT) {
// Compute the distance attenuation value by the logarithmic curve
// "1 / (d + 1)" with an offset of |minDistance|.
let relativeDistance = distance - this.minDistance;
let attenuation = 1 / (relativeDistance + 1);
let attenuationMax = 1 / (range + 1);
gain = (attenuation - attenuationMax) / (1 - attenuationMax);
}
}
}
else if (this._rolloff == 'linear') {
if (distance > this.maxDistance) {
gain = 0;
}
else if (distance > this.minDistance) {
let range = this.maxDistance - this.minDistance;
if (range > Utils.EPSILON_FLOAT) {
gain = (this.maxDistance - distance) / range;
}
}
}
this._gainNode.gain.value = gain;
}
/**
* Set rolloff.
* @param {string} rolloff
* Rolloff model to use, chosen from options in
* {@linkcode Utils.ATTENUATION_ROLLOFFS ATTENUATION_ROLLOFFS}.
*/
setRolloff(rolloff) {
let isValidModel = ~Utils.ATTENUATION_ROLLOFFS.indexOf(rolloff);
if (rolloff == undefined || !isValidModel) {
if (!isValidModel) {
Utils.log('Invalid rolloff model (\"' + rolloff +
'\"). Using default: \"' + Utils.DEFAULT_ATTENUATION_ROLLOFF + '\".');
}
rolloff = Utils.DEFAULT_ATTENUATION_ROLLOFF;
}
else {
rolloff = rolloff.toString().toLowerCase();
}
this._rolloff = rolloff;
}
}
export default Attenuation;