From 9b098a4bf7fd7df095a4913a261e28146be6701e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 8 May 2017 10:51:13 -0700 Subject: [PATCH 1/2] Fix randFloat error in ac audio searcher --- tutorial/ACAudioSearchAndInject_tutorial.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tutorial/ACAudioSearchAndInject_tutorial.js b/tutorial/ACAudioSearchAndInject_tutorial.js index 70e936bb1c..6037c5f723 100644 --- a/tutorial/ACAudioSearchAndInject_tutorial.js +++ b/tutorial/ACAudioSearchAndInject_tutorial.js @@ -1,4 +1,5 @@ "use strict"; + /*jslint nomen: true, plusplus: true, vars: true*/ /*global AvatarList, Entities, EntityViewer, Script, SoundCache, Audio, print, randFloat*/ // @@ -41,7 +42,6 @@ var DEFAULT_SOUND_DATA = { //var isACScript = this.EntityViewer !== undefined; var isACScript = true; -Script.include("http://hifi-content.s3.amazonaws.com/ryan/development/utils_ryan.js"); if (isACScript) { Agent.isAvatar = true; // This puts a robot at 0,0,0, but is currently necessary in order to use AvatarList. Avatar.skeletonModelURL = "http://hifi-content.s3.amazonaws.com/ozan/dev/avatars/invisible_avatar/invisible_avatar.fst"; @@ -51,6 +51,10 @@ function debug() { // Display the arguments not just [Object object]. //print.apply(null, [].map.call(arguments, JSON.stringify)); } +function randFloat(low, high) { + return low + Math.random() * (high - low); +} + if (isACScript) { EntityViewer.setCenterRadius(QUERY_RADIUS); } From c73c59baee08865717b057726ebdd0da6440de00 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 8 May 2017 11:19:05 -0700 Subject: [PATCH 2/2] Move changes in AC audio searcher from tutorial content into git --- tutorial/ACAudioSearchAndInject_tutorial.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tutorial/ACAudioSearchAndInject_tutorial.js b/tutorial/ACAudioSearchAndInject_tutorial.js index 6037c5f723..5e2998ff1e 100644 --- a/tutorial/ACAudioSearchAndInject_tutorial.js +++ b/tutorial/ACAudioSearchAndInject_tutorial.js @@ -39,12 +39,17 @@ var DEFAULT_SOUND_DATA = { playbackGapRange: 0 // in ms }; +//var AGENT_AVATAR_POSITION = { x: -1.5327, y: 0.672515, z: 5.91573 }; +var AGENT_AVATAR_POSITION = { x: -2.83785, y: 1.45243, z: -13.6042 }; + //var isACScript = this.EntityViewer !== undefined; var isACScript = true; if (isACScript) { Agent.isAvatar = true; // This puts a robot at 0,0,0, but is currently necessary in order to use AvatarList. Avatar.skeletonModelURL = "http://hifi-content.s3.amazonaws.com/ozan/dev/avatars/invisible_avatar/invisible_avatar.fst"; + Avatar.position = AGENT_AVATAR_POSITION; + Agent.isListeningToAudioStream = true; } function ignore() {} function debug() { // Display the arguments not just [Object object]. @@ -97,6 +102,7 @@ function EntityDatum(entityIdentifier) { // Just the data of an entity that we n return; } var properties, soundData; // Latest data, pulled from local octree. + // getEntityProperties locks the tree, which competes with the asynchronous processing of queryOctree results. // Most entity updates are fast and only a very few do getEntityProperties. function ensureSoundData() { // We only getEntityProperities when we need to. @@ -119,43 +125,54 @@ function EntityDatum(entityIdentifier) { // Just the data of an entity that we n } } } + // Stumbling on big new pile of entities will do a lot of getEntityProperties. Once. if (that.lastUserDataUpdate < userDataCutoff) { // NO DATA => SOUND DATA ensureSoundData(); } + if (!that.url) { // NO DATA => NO DATA return that.stop(); } + if (!that.sound) { // SOUND DATA => DOWNLOADING that.sound = SoundCache.getSound(soundData.url); // SoundCache can manage duplicates better than we can. } + if (!that.sound.downloaded) { // DOWNLOADING => DOWNLOADING return; } + if (that.playAfter > now) { // DOWNLOADING | WAITING => WAITING return; } + ensureSoundData(); // We'll try to play/setOptions and will need position, so we might as well get soundData, too. if (soundData.url !== that.url) { // WAITING => NO DATA (update next time around) return that.stop(); } + var options = { position: properties.position, loop: soundData.loop || DEFAULT_SOUND_DATA.loop, volume: soundData.volume || DEFAULT_SOUND_DATA.volume }; + function repeat() { return !options.loop && (soundData.playbackGap >= 0); } + function randomizedNextPlay() { // time of next play or recheck, randomized to distribute the work var range = soundData.playbackGapRange || DEFAULT_SOUND_DATA.playbackGapRange, base = repeat() ? ((that.sound.duration * MSEC_PER_SEC) + (soundData.playbackGap || DEFAULT_SOUND_DATA.playbackGap)) : RECHECK_TIME; return now + base + randFloat(-Math.min(base, range), range); } + if (that.injector && soundData.playing === false) { that.injector.stop(); that.injector = null; } + if (!that.injector) { if (soundData.playing === false) { // WAITING => PLAYING | WAITING return; @@ -169,6 +186,7 @@ function EntityDatum(entityIdentifier) { // Just the data of an entity that we n } return; } + that.injector.setOptions(options); // PLAYING => UPDATE POSITION ETC if (!that.injector.playing) { // Subtle: a looping sound will not check playbackGap. if (repeat()) { // WAITING => PLAYING @@ -182,6 +200,7 @@ function EntityDatum(entityIdentifier) { // Just the data of an entity that we n } }; } + function internEntityDatum(entityIdentifier, timestamp, avatarPosition, avatar) { ignore(avatarPosition, avatar); // We could use avatars and/or avatarPositions to prioritize which ones to play. var entitySound = entityCache[entityIdentifier]; @@ -190,7 +209,9 @@ function internEntityDatum(entityIdentifier, timestamp, avatarPosition, avatar) } entitySound.timestamp = timestamp; // Might be updated for multiple avatars. That's fine. } + var nUpdates = UPDATES_PER_STATS_LOG, lastStats = Date.now(); + function updateAllEntityData() { // A fast update of all entities we know about. A few make sounds. var now = Date.now(), expirationCutoff = now - EXPIRATION_TIME,