From 70942925bc200da48196b5955d86156f12513d29 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 19 Dec 2016 10:32:17 -0800 Subject: [PATCH] Entity script for ambisonic sound emitter --- .../tutorials/entity_scripts/ambientSound.js | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 scripts/tutorials/entity_scripts/ambientSound.js diff --git a/scripts/tutorials/entity_scripts/ambientSound.js b/scripts/tutorials/entity_scripts/ambientSound.js new file mode 100644 index 0000000000..a387f00c10 --- /dev/null +++ b/scripts/tutorials/entity_scripts/ambientSound.js @@ -0,0 +1,101 @@ +// ambientSound.js +// +// This entity script will allow you to create an ambient sound that loops when a person is within a given +// range of this entity. Great way to add one or more ambisonic soundfields to your environment. +// +// In the userData section for the entity, add two values: +// userData.SoundURL should be a string giving the URL to the sound file. Defaults to 100 meters if not set. +// userData.range should be an integer for the max distance away from the entity where the sound will be audible. +// userData.volume is the max volume at which the clip should play. +// +// Note: When you update the above values, you need to reload the entity script for it to see the changes. Also, +// remember that the entity has to be visible to the user for the sound to play at all, so make sure the entity is +// large enough to be loaded at the range you set, particularly for large ranges. +// +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function(){ + // This sample clip and range will be used if you don't add userData to the entity (see above) + var DEFAULT_RANGE = 100; + var DEFAULT_URL = "http://hifi-content.s3.amazonaws.com/ken/samples/forest_ambiX.wav"; + var DEFAULT_VOLUME = 1.0; + + var soundURL = DEFAULT_URL; + var range = DEFAULT_RANGE; + var maxVolume = DEFAULT_VOLUME; + var UPDATE_INTERVAL_MSECS = 100; + + var entity; + var ambientSound; + var center; + var soundPlaying = false; + var updateTimer = false; + + var WANT_DEBUG = false; + + function debugPrint(string) { + if (WANT_DEBUG) { + print(string); + } + } + + this.preload = function(entityID) { + // Load the sound and range from the entity userData fields, and note the position of the entity. + debugPrint("Ambient sound preload"); + entity = entityID; + var props = Entities.getEntityProperties(entityID, [ "userData" ]); + var data = JSON.parse(props.userData); + if (data.soundURL) { + soundURL = data.soundURL; + debugPrint("Read ambient sound URL: " + soundURL); + } + ambientSound = SoundCache.getSound(soundURL); + if (data.range) { + range = data.range; + debugPrint("Read ambient sound range: " + range); + } + if (data.volume) { + maxVolume = data.volume; + debugPrint("Read ambient sound volume: " + maxVolume); + } + updateTimer = Script.setInterval(this.update, UPDATE_INTERVAL_MSECS); + }; + + this.update = function() { + // Every UPDATE_INTERVAL_MSECS, update the volume of the ambient sound based on distance from my avatar + var HYSTERESIS_FRACTION = 0.1; + var props = Entities.getEntityProperties(entity, [ "position" ]); + center = props.position; + var distance = Vec3.length(Vec3.subtract(MyAvatar.position, center)); + if (distance <= range) { + var volume = (1.0 - distance / range) * maxVolume; + if (!soundPlaying && ambientSound.downloaded) { + soundPlaying = Audio.playSound(ambientSound, { loop: true, volume: volume }); + debugPrint("Starting ambient sound, volume: " + volume); + Entities.editEntity(entity, { color: { red: 255, green: 0, blue: 0 }}); + } else if (soundPlaying && soundPlaying.playing) { + soundPlaying.setOptions( { volume: volume } ); + } + } else if (soundPlaying && soundPlaying.playing && (distance > range * HYSTERESIS_FRACTION)) { + soundPlaying.stop(); + soundPlaying = false; + Entities.editEntity(entity, { color: { red: 128, green: 128, blue: 128 }}); + debugPrint("Out of range, stopping ambient sound"); + } + } + + this.unload = function(entityID) { + debugPrint("Ambient sound unload"); + if (updateTimer) { + Script.clearInterval(updateTimer); + } + if (soundPlaying && soundPlaying.playing) { + soundPlaying.stop(); + } + }; + +})