| … | … | @@ -236,15 +236,64 @@ Audio emitters of type `positional` may be added to nodes using the following sy |
| 236 | 236 | |
| 237 | 237 | Note that multiple global audio emitters are allowed on the scene, but only a single audio emitter may be added to a node. |
| 238 | 238 | |
| 239 | | <!-- include audio formula for rolloff --> |
| 239 | ### Audio Rolloff Formula |
| 240 | The Audio Rolloff range is (0, +∞). The default is 1. |
| 240 | 241 | |
| 241 | | <!-- include audio formula for gain --> |
| 242 | The rolloff formula is dependant on the distance model defined. The available distance models are `linear`, `inverse`, and `exponential`. |
| 242 | 243 | |
| 243 | | <!-- include audio formula for cone --> |
| 244 | - linear formula: `1 - rolloffFactor * (distance - refDistance) / (maxDistance - refDistance)` |
| 245 | - inverse formula: `refDistance / (refDistance + rolloffFactor * (Math.max(distance, refDistance) - refDistance))` |
| 246 | - exponential formula: `pow((Math.max(distance, refDistance) / refDistance, -rolloffFactor)` |
| 244 | 247 | |
| 245 | 248 | ### Audio Gain Units |
| 246 | | |
| 247 | | |
| 249 | The gain unit range is (0,+∞). The default is 1. |
| 250 | - gain formula: `originalVolume * gain` |
| 251 | |
| 252 | ### Audio Cone Vizualized |
| 253 |  |
| 254 | |
| 255 | The cone properties relate to the `PannerNode` interface and determine the amount of volume relative to a listeners position within the defined cone area. |
| 256 | |
| 257 | The gain relative to cone properties is determined as follows: |
| 258 | ```function coneGain() { |
| 259 | const sourceOrientation = |
| 260 | new Vec3(source.orientationX, source.orientationY, source.orientationZ); |
| 261 | if (sourceOrientation.magnitude == 0 || |
| 262 | ((source.coneInnerAngle == 360) && (source.coneOuterAngle == 360))) |
| 263 | return 1; // no cone specified - unity gain |
| 264 | // Normalized source-listener vector |
| 265 | const sourcePosition = new Vec3(panner.positionX.value, panner.positionY.value, |
| 266 | panner.positionZ.value); |
| 267 | const listenerPosition = |
| 268 | new Vec3(listener.positionX.value, listener.positionY.value, |
| 269 | listener.positionZ.value); |
| 270 | const sourceToListener = sourcePosition.diff(listenerPosition).normalize(); |
| 271 | const normalizedSourceOrientation = sourceOrientation.normalize(); |
| 272 | // Angle between the source orientation vector and the source-listener vector |
| 273 | const angle = 180 * |
| 274 | Math.acos(sourceToListener.dot(normalizedSourceOrientation)) / |
| 275 | Math.PI; |
| 276 | const absAngle = Math.abs(angle); |
| 277 | // Divide by 2 here since API is entire angle (not half-angle) |
| 278 | const absInnerAngle = Math.abs(source.coneInnerAngle) / 2; |
| 279 | const absOuterAngle = Math.abs(source.coneOuterAngle) / 2; |
| 280 | let gain = 1; |
| 281 | if (absAngle <= absInnerAngle) { |
| 282 | // No attenuation |
| 283 | gain = 1; |
| 284 | } else if (absAngle >= absOuterAngle) { |
| 285 | // Max attenuation |
| 286 | gain = source.coneOuterGain; |
| 287 | } else { |
| 288 | // Between inner and outer cones |
| 289 | // inner -> outer, x goes from 0 -> 1 |
| 290 | const x = (absAngle - absInnerAngle) / (absOuterAngle - absInnerAngle); |
| 291 | gain = (1 - x) + source.coneOuterGain * x; |
| 292 | } |
| 293 | return gain; |
| 294 | } |
| 295 | ``` |
| 296 | [Cone Gain Algorithm Source](https://webaudio.github.io/web-audio-api/#Spatialization-sound-cones) |
| 248 | 297 | |
| 249 | 298 | ### Units for Rotations |
| 250 | 299 | |