From c5f889a34dae02670edee1d972a178c26ecfe522 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Fri, 7 Oct 2016 15:13:37 -0700 Subject: [PATCH] update for sound --- .../tests/performance/crowd-agent.js | 28 ++++++++++++-- scripts/developer/tests/performance/summon.js | 38 ++++++++++++++++--- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/scripts/developer/tests/performance/crowd-agent.js b/scripts/developer/tests/performance/crowd-agent.js index 5df576cf99..6b73d66c4f 100644 --- a/scripts/developer/tests/performance/crowd-agent.js +++ b/scripts/developer/tests/performance/crowd-agent.js @@ -16,7 +16,7 @@ var MESSAGE_CHANNEL = "io.highfidelity.summon-crowd"; -print('crowd-agent version 1'); +print('crowd-agent version 2'); /* Observations: - File urls for AC scripts silently fail. Use a local server (e.g., python SimpleHTTPServer) for development. @@ -24,9 +24,26 @@ print('crowd-agent version 1'); - JSON.stringify(Avatar) silently fails (even when Agent.isAvatar) */ +function messageSend(message) { + Messages.sendMessage(MESSAGE_CHANNEL, JSON.stringify(message)); +} + +function getSound(data, callback) { // callback(sound) when downloaded (which may be immediate). + var sound = SoundCache.getSound(data.url); + if (sound.downloaded) { + return callback(sound); + } + sound.ready.connect(function () { callback(sound); }); +} +function onFinishedPlaying() { + messageSend({key: 'finishedSound'}); +} + +var MILLISECONDS_IN_SECOND = 1000; function startAgent(parameters) { // Can also be used to update. print('crowd-agent starting params', JSON.stringify(parameters), JSON.stringify(Agent)); Agent.isAvatar = true; + Agent.isListeningToAudioStream = true; // Send silence when not chattering. if (parameters.position) { Avatar.position = parameters.position; } @@ -36,6 +53,12 @@ function startAgent(parameters) { // Can also be used to update. if (parameters.skeletonModelURL) { Avatar.skeletonModelURL = parameters.skeletonModelURL; } + if (parameters.soundData) { + getSound(parameters.soundData, function (sound) { + Script.setTimeout(onFinishedPlaying, sound.duration * MILLISECONDS_IN_SECOND); + Agent.playAvatarSound(sound); + }); + } if (parameters.animationData) { data = parameters.animationData; Avatar.startAnimation(data.url, data.fps || 30, 1.0, (data.loopFlag === undefined) ? true : data.loopFlag, false, data.startFrame || 0, data.endFrame); @@ -47,9 +70,6 @@ function stopAgent(parameters) { print('crowd-agent stopped', JSON.stringify(parameters), JSON.stringify(Agent)); } -function messageSend(message) { - Messages.sendMessage(MESSAGE_CHANNEL, JSON.stringify(message)); -} function messageHandler(channel, messageString, senderID) { if (channel !== MESSAGE_CHANNEL) { return; diff --git a/scripts/developer/tests/performance/summon.js b/scripts/developer/tests/performance/summon.js index 2eb1fbe301..10c3af5ae5 100644 --- a/scripts/developer/tests/performance/summon.js +++ b/scripts/developer/tests/performance/summon.js @@ -18,15 +18,25 @@ var label = "summon"; function debug() { print.apply(null, [].concat.apply([label, version], [].map.call(arguments, JSON.stringify))); } -var MINIMUM_AVATARS = 25; +var MINIMUM_AVATARS = 25; // We will summon agents to produce this many total. (Of course, there might not be enough agents.) var DENSITY = 0.3; // square meters per person. Some say 10 sq ft is arm's length (0.9m^2), 4.5 is crowd (0.4m^2), 2.5 is mosh pit (0.2m^2). +var SOUND_DATA = {url: "http://howard-stearns.github.io/models/sounds/piano1.wav"}; +var AVATARS_CHATTERING_AT_ONCE = 4; // How many of the agents should we request to play SOUND at once. +var NEXT_SOUND_SPREAD = 500; // millisecond range of how long to wait after one sound finishes, before playing the next + var spread = Math.sqrt(MINIMUM_AVATARS * DENSITY); // meters var turnSpread = 90; // How many degrees should turn from front range over. function coord() { return (Math.random() * spread) - (spread / 2); } // randomly distribute a coordinate zero += spread/2. - +function contains(array, item) { return array.indexOf(item) >= 0; } +function without(array, itemsToRemove) { return array.filter(function (item) { return !contains(itemsToRemove, item); }); } +function nextAfter(array, id) { // Wrapping next element in array after id. + var index = array.indexOf(id) + 1; + return array[(index >= array.length) ? 0 : index]; +} var summonedAgents = []; +var chattering = []; var MESSAGE_CHANNEL = "io.highfidelity.summon-crowd"; function messageSend(message) { Messages.sendMessage(MESSAGE_CHANNEL, JSON.stringify(message)); @@ -48,15 +58,20 @@ function messageHandler(channel, messageString, senderID) { switch (message.key) { case "hello": // There can be avatars we've summoned that do not yet appear in the AvatarList. - avatarIdentifiers = AvatarList.getAvatarIdentifiers().filter(function (id) { return summonedAgents.indexOf(id) === -1; }); + avatarIdentifiers = without(AvatarList.getAvatarIdentifiers(), summonedAgents); debug('present', avatarIdentifiers, summonedAgents); if ((summonedAgents.length + avatarIdentifiers.length) < MINIMUM_AVATARS ) { + var chatter = chattering.length < AVATARS_CHATTERING_AT_ONCE; + if (chatter) { + chattering.push(senderID); + } summonedAgents.push(senderID); messageSend({ key: 'SUMMON', rcpt: senderID, position: Vec3.sum(MyAvatar.position, {x: coord(), y: 0, z: coord()}), - orientation: Quat.fromPitchYawRollDegrees(0, Quat.safeEulerAngles(MyAvatar.orientation).y + (turnSpread * (Math.random() - 0.5)), 0)/*, + orientation: Quat.fromPitchYawRollDegrees(0, Quat.safeEulerAngles(MyAvatar.orientation).y + (turnSpread * (Math.random() - 0.5)), 0), + soundData: chatter && SOUND_DATA/* // No need to specify skeletonModelURL //skeletonModelURL: "file:///c:/Program Files/High Fidelity Release/resources/meshes/being_of_light/being_of_light.fbx", //skeletonModelURL: "file:///c:/Program Files/High Fidelity Release/resources/meshes/defaultAvatar_full.fst"/, @@ -71,6 +86,16 @@ function messageHandler(channel, messageString, senderID) { }); } break; + case "finishedSound": // Give someone else a chance. + chattering = without(chattering, [senderID]); + Script.setTimeout(function () { + messageSend({ + key: 'SUMMON', + rcpt: nextAfter(without(summonedAgents, chattering), senderID), + soundData: SOUND_DATA + }); + }, Math.random() * NEXT_SOUND_SPREAD); + break; case "HELO": Window.alert("Someone else is summoning avatars."); break; @@ -93,11 +118,12 @@ Script.scriptEnding.connect(function () { messageSend({key: 'HELO'}); // Ask agents to report in now. Script.setTimeout(function () { + var total = AvatarList.getAvatarIdentifiers().length; if (0 === summonedAgents.length) { Window.alert("No agents reported.\n\Please run " + MINIMUM_AVATARS + " instances of\n\ http://cdn.highfidelity.com/davidkelly/production/scripts/tests/performance/crowd-agent.js\n\ on your domain server."); - } else if (summonedAgents.length < MINIMUM_AVATARS) { - Window.alert("Only " + summonedAgents.length + " of the expected " + MINIMUM_AVATARS + " agents reported in."); + } else if (total < MINIMUM_AVATARS) { + Window.alert("Only " + summonedAgents.length + " of the expected " + (MINIMUM_AVATARS - total) + " agents + reported in."); } }, 5000);