public void StartRecordingAvatars(Dictionary <RefID, Slot> avatar_roots, string override_filename = null) { foreach (var item in avatar_roots) { RefID user_id = item.Key; Slot rootSlot = item.Value; VRIK comp = rootSlot.GetComponentInChildren <VRIK>(); if (comp != null) { IKSolverVR solver = (IKSolverVR)comp.Solver; boness[user_id] = solver.BoneReferences; string filename = ""; if (override_filename != null) { filename = saving_folder + "/" + override_filename + "_mocap.bvh"; } else { filename = saving_folder + "/" + user_id.ToString() + "_mocap.bvh"; } fileWriters[user_id] = new System.IO.StreamWriter(filename); filenames[user_id] = filename; BvhHeaderWrite(fileWriters[user_id], boness[user_id]); } } isRecording = true; }
public void StartRecording() { current_users_ids = new List <string>(); saving_folder = metagen_comp.dataManager.saving_folder; foreach (var item in metagen_comp.userMetaData) { User user = item.Key; UserMetadata metadata = item.Value; if (!metadata.isRecording || (metagen_comp.LocalUser == user && !metagen_comp.record_local_user)) { continue; } RefID user_id = user.ReferenceID; current_users_ids.Add(user_id.ToString()); AvatarAudioOutputManager comp = user.Root.Slot.GetComponentInChildren <AvatarAudioOutputManager>(); AudioOutput audio_output = comp.AudioOutput.Target; audio_outputs[user_id] = audio_output; if (audio_outputs[user_id] == null) { UniLog.Log("OwO: Audio output for user " + user_id.ToString() + " is null!"); } else { UniLog.Log("Sample rate"); UniLog.Log(metagen_comp.Engine.AudioSystem.Connector.SampleRate.ToString()); audio_recorders[user_id] = new AudioRecorder(saving_folder + "/" + user_id.ToString() + "_voice_tmp", metagen_comp.Engine.AudioSystem.BufferSize, 1, metagen_comp.Engine.AudioSystem.SampleRate, 1); audio_recorders[user_id].StartWriting(); } } isRecording = true; }
public void StartInteracting() { foreach (var item in metagen_comp.userMetaData) { User user = item.Key; UserMetadata metadata = item.Value; if (!(metadata.isRecording || metagen_comp.record_everyone)) { continue; } UniLog.Log("Starting voice interaction for user " + user.UserName); RefID user_id = user.ReferenceID; current_users_ids.Add(user_id.ToString()); AvatarAudioOutputManager comp = user.Root.Slot.GetComponentInChildren <AvatarAudioOutputManager>(); AudioOutput audio_output = comp.AudioOutput.Target; audio_outputs[user_id] = audio_output; isRecording[user_id] = false; if (audio_outputs[user_id] == null) { UniLog.Log("OwO: Audio output for user " + user_id.ToString() + " is null!"); } else { UniLog.Log("Sample rate"); UniLog.Log(metagen_comp.Engine.AudioSystem.Connector.SampleRate.ToString()); } } isInteracting = true; }
public void StartRecording() { World currentWorld = metagen_comp.World; current_users_ids = new List <string>(); currentWorld.RunSynchronously(() => { foreach (var item in metagen_comp.userMetaData) { User user = item.Key; UserMetadata metadata = item.Value; if (!metadata.isRecording || (metagen_comp.LocalUser == user && !metagen_comp.record_local_user)) { continue; } RefID user_id = user.ReferenceID; current_users_ids.Add(user_id.ToString()); Slot localSlot = user.Root.HeadSlot.AddLocalSlot("vision recorder camera"); FrooxEngine.Camera camera = localSlot.AttachComponent <FrooxEngine.Camera>(); camera.GetRenderSettings(camera_resolution); camera.NearClipping.Value = 0.15f; cameras[user_id] = camera; int fps = 30; visual_recorders[user_id] = new VideoRecorder(Path.Combine(saving_folder, user_id.ToString() + "_vision_tmp.avi"), camera_resolution.x, camera_resolution.y, fps, metagen_comp); } UniLog.Log("Made visual recorder"); isRecording = true; }); }
void StartWritingFile(RefID user_id) { Guid g = Guid.NewGuid(); audio_recorders[user_id] = new AudioRecorder(saving_folder + "/" + user_id.ToString() + "_voice_tmp_" + g.ToString(), metagen_comp.Engine.AudioSystem.BufferSize, 1, metagen_comp.Engine.AudioSystem.SampleRate, 1); audio_recorders[user_id].StartWriting(); isRecording[user_id] = true; }
void StopWritingFile(RefID user_id) { isRecording[user_id] = false; audio_recorders[user_id].WriteHeader(); string fileName = audio_recorders[user_id].fileName + ".wav"; File.Move(fileName, fileName.Replace("voice_tmp", "voice_ready")); }
public void RegisterUserStreams(string name) { foreach (var userItem in metagen_comp.userMetaData) { User user = userItem.Key; UserMetadata metadata = userItem.Value; if (!metadata.isRecording || (metagen_comp.LocalUser == user && !metagen_comp.record_local_user)) { continue; } RefID user_id = user.ReferenceID; RegisterUserStream(user_id, name); } }
private void ReadHeadings() { foreach (var item in pose_readers) { RefID refID = item.Key; BinaryReaderX reader = item.Value; //send heading bytes to GRPC byte[] byteArray = reader.ReadBytes((int)reader.BaseStream.Length); Google.Protobuf.ByteString byteString = Google.Protobuf.ByteString.CopyFrom(byteArray, 0, byteArray.Length); client.SendHeadingBytes(new Heading { RefId = refID.ToString(), Data = byteString }); } }
public void RegisterUserStream(RefID user_id, string name) { Tuple <BitBinaryWriterX, BitBinaryReaderX> streams = RegisterStream(user_id.ToString() + "_" + name); BitBinaryWriterX bitBinaryWriter = streams.Item1; BitBinaryReaderX bitBinaryReader = streams.Item2; if (bitBinaryWriter != null) { output_writers[user_id] = bitBinaryWriter; } if (bitBinaryReader != null) { output_readers[user_id] = bitBinaryReader; } }
public void InteractPoseStreams(float deltaT) { if (channel.State != ChannelState.Ready) { return; } try { //UniLog.Log("InteractPoseStreams"); foreach (var item in pose_writers) { RefID refID = item.Key; BinaryWriter writer = item.Value; //read heading bytes from GRPC //byte[] bs = null; ByteString bs1 = client.GetFrameBytes(new RefIDMessage { RefId = refID.ToString() }).Data; //writer.Write(bs1.ToByteArray()); //writer.BaseStream.Write(bs1.ToByteArray(),(int) writer.BaseStream.Position, bs1.Length); UniLog.Log(writer.BaseStream.Position); writer.Write(bs1.ToByteArray()); UniLog.Log(writer.BaseStream.Position); UniLog.Log(bs1.Length); writer.BaseStream.Position -= bs1.Length; //writer.Write(frame_bs); } metagen_comp.streamPlayer.PlayStreams(); metagen_comp.metaRecorder.streamRecorder.RecordStreams(deltaT); foreach (var item in pose_readers) { RefID refID = item.Key; BinaryReaderX reader = item.Value; //send heading bytes to GRPC byte[] byteArray = reader.ReadBytes((int)reader.BaseStream.Length); Google.Protobuf.ByteString byteString = Google.Protobuf.ByteString.CopyFrom(byteArray, 0, byteArray.Length); client.SendFrameBytes(new Frame { RefId = refID.ToString(), Data = byteString }); } } catch (Exception e) { UniLog.Log("OwO: " + e.Message); } }
//Record one chunk from the voice audio of each user public void RecordAudio() { //Debug.Log("Recording audio"); foreach (var item in audio_outputs) { AudioOutput audio_output = item.Value; RefID user_id = item.Key; if (audio_output != null) { buffer.EnsureSize <float>(metagen_comp.Engine.AudioSystem.BufferSize, false); if (audio_output.Source.Target != null) { //AudioSystemConnector.InformOfDSPTime(AudioSettings.dspTime); FrooxEngine.Engine.Current.AudioRead(); audio_sources_ready = true; AudioStream <MonoSample> stream = (AudioStream <MonoSample>)audio_output.Source.Target; stream.Read <MonoSample>(buffer.AsMonoBuffer()); //if (buffer.Length > stream.MissedSamples) //{ // buffer = buffer.Take(buffer.Length - stream.MissedSamples).ToArray(); //buffer[0] = 0f; //buffer[1] = 0f; //buffer[2] = 0f; //buffer[3] = 0f; //Console.WriteLine("[{0}]", string.Join(", ", buffer)); for (int i = 0; i < buffer.Length; i++) { buffer[i] = MathX.Clamp(buffer[i], -1, 1); } //UniLog.Log(buffer.Length); audio_recorders[user_id].ConvertAndWrite(buffer); //Task.Run(() => { audio_recorders[user_id].ConvertAndWrite(buffer); }); //metagen_comp.StartTask(async () => { audio_recorders[user_id].ConvertAndWrite(buffer); }); //} } else { UniLog.Log("Audio Output Source target was null! (hmm should we restart it?). Did it happen coz a user left (in which case we shouldn't restart it), or something else?"); //UniLog.Log("Restarting audio recording coz audio output source target was null!"); //StopRecording(); //StartRecording(); } } } }
private void WriteHeadings() { foreach (var item in pose_writers) { RefID refID = item.Key; BinaryWriter writer = item.Value; //read heading bytes from GRPC ByteString bs1 = client.GetHeadingBytes(new RefIDMessage { RefId = refID.ToString() }).Data; UniLog.Log(bs1.Length); //byte[] bs = new byte[bs1.Length]; //bs1.CopyTo(bs, 0); //writer.BaseStream.Write(bs1.ToByteArray(),(int) writer.BaseStream.Position, bs1.Length); writer.Write(bs1.ToByteArray()); writer.BaseStream.Position -= bs1.Length; } }
private void StartInteractingInternal() { try { UniLog.Log("Start pose stream interaction"); channel = new Channel("127.0.0.1:" + (40052).ToString(), ChannelCredentials.Insecure); UniLog.Log("Started grpc channel"); client = new PoseInteraction.PoseInteractionClient(channel); //wsclient = metagen_comp.Slot.AttachComponent<WebsocketClient>(); //wsclient.URL.Value = new Uri("http://127.0.0.1:" + (40052).ToString()); //Acting metagen_comp.streamPlayer.PrepareStreamsExternal(); //RefID user_id = RefID.Parse("IDC00"); foreach (var item in metagen_comp.streamPlayer.output_writers) { RefID refID = item.Key; pose_writers[refID] = item.Value; } WriteHeadings(); metagen_comp.streamPlayer.play_hearing = false; metagen_comp.streamPlayer.play_voice = false; UniLog.Log("metagen_comp.botComponent"); UniLog.Log(metagen_comp.botComponent); UniLog.Log("metagen_comp.botComponent.panelUI"); UniLog.Log(metagen_comp.botComponent.panelUI); Slot avatar = metagen_comp.botComponent.panelUI._avatarRefField.Target.Reference.Target; metagen_comp.streamPlayer.StartPlayingExternal(1, avatar); metagen_comp.metaRecorder.streamRecorder.StartRecordingExternal(); foreach (var item in metagen_comp.metaRecorder.streamRecorder.output_readers) { RefID refID = item.Key; //BinaryWriterX writer = item.Value; //BitReaderStream binaryReader = new BitReaderStream(writer.BaseStream); pose_readers[refID] = item.Value; } ReadHeadings(); UniLog.Log("Finished starting PoseStreamInteraction"); isInteracting = true; } catch (Exception e) { UniLog.Log("TwT: " + e); } }
public void StartRecording() { Dictionary <RefID, Slot> avatar_roots = new Dictionary <RefID, Slot>(); foreach (var item in metagen_comp.userMetaData) { User user = item.Key; UserMetadata metadata = item.Value; UniLog.Log("user " + user.UserName); if (!metadata.isRecording || (metagen_comp.LocalUser == user && !metagen_comp.record_local_user)) { continue; } RefID user_id = user.ReferenceID; Slot rootSlot = user.Root?.Slot; avatar_roots[user_id] = rootSlot; } StartRecordingAvatars(avatar_roots); }
public void StopRecording() { isRecording = false; boness = new Dictionary <RefID, IKSolverVR.References>(); foreach (var item in fileWriters) { RefID user_id = item.Key; StreamWriter writer = item.Value; writer.Close(); metagen_comp.RunSynchronously(() => { string filename = filenames[user_id]; UniLog.Log("Import bvh file"); Slot s = metagen_comp.LocalUserSpace.AddSlot(Path.GetFileName(filename), true); metagen_comp.StartGlobalTask((Func <Task>)(async() => await UniversalImporter.ImportRawFile(s, filename))); }); } fileWriters = new Dictionary <RefID, StreamWriter>(); tracking_rotations = new Dictionary <BodyNode, bool>(); boness = new Dictionary <RefID, IKSolverVR.References>(); filenames = new Dictionary <RefID, string>(); }
//Record one frame of the head camera for each user public void RecordVision() { foreach (var item in visual_recorders) { RefID user_id = item.Key; VideoRecorder videoRecorder = item.Value; if (videoRecorder != null && cameras[user_id] != null) { Task task = metagen_comp.StartTask((Func <Task>)(async() => { Bitmap2D bmp = await cameras[user_id].RenderToBitmap(camera_resolution); visual_recorders[user_id].WriteFrame(bmp.ConvertTo(CodeX.TextureFormat.BGRA32).RawData); //UniLog.Log(DateTime.UtcNow.ToMillisecondTimeString()); })); //TODO: sync video //task.Wait(); //World currentWorld = metagen_comp.World; //FrooxEngine.RenderSettings renderSettings = cameras[user_id].GetRenderSettings(camera_resolution); //byte[] data = currentWorld.Render.Connector.Render(renderSettings).Result; //Bitmap2D bmp = new Bitmap2D(data, renderSettings.size.x, renderSettings.size.y, renderSettings.textureFormat, false, true, (string)null); //visual_recorders[user_id].WriteFrame(bmp.ConvertTo(CodeX.TextureFormat.BGRA32).RawData); } else { //something was null:P bool vis_rec_null = false; bool camera_null = false; if (visual_recorders[user_id] == null) { vis_rec_null = true; } if (cameras[user_id] == null) { camera_null = true; } UniLog.Log("OwO. These things were null: " + (camera_null ? "Camera" : "") + (vis_rec_null ? "Visual recorder" : "")); } } }
public void StartRecording() { source_type = Source.FILE; foreach (var userItem in metagen_comp.userMetaData) { User user = userItem.Key; UserMetadata metadata = userItem.Value; if (!metadata.isRecording || (metagen_comp.LocalUser == user && !metagen_comp.record_local_user)) { continue; } RefID user_id = user.ReferenceID; bool has_eye_tracking = user.Devices.Where <SyncVar>((Func <SyncVar, bool>)(i => i.IsDictionary)).Any <SyncVar>((Func <SyncVar, bool>)(i => i["Type"].GetValue <string>(true) == "Eye Tracking")); if (has_eye_tracking) { RegisterUserStream(user_id, "eye_streams"); eye_streams[user_id] = user.Root.Slot.GetComponent <EyeTrackingStreamManager>(); current_eye_tracking_users.Add(user_id); } } isRecording = true; }
public void RecordFrame() { foreach (User user in metagen_comp.World.AllUsers) { RefID user_id = user.ReferenceID; if (boness.ContainsKey(user_id)) { IKSolverVR.References bones = boness[user_id]; BodyNode node = bonesList[0]; if (bones[node] != null) { Slot bone = bones[node]; float3 pos = bone.GlobalPosition; float3 rot = bone.GlobalRotation.EulerAngles; fileWriters[user_id].Write(string.Format("{0:0.000000}\t{1:0.000000}\t{2:0.000000}", pos.X, pos.Y, pos.Z) + "\t"); fileWriters[user_id].Write(string.Format("{0:0.000000}\t{1:0.000000}\t{2:0.000000}", rot.Z, rot.X, rot.Y) + "\t"); } for (int i = 1; i < bonesList.Count; i++) { node = bonesList[i]; if (bones[node] != null) { Slot bone = bones[node]; float3 rot = bone.LocalRotationToSpace(floatQ.Identity, bones[boneParents[node]]).EulerAngles; //float3 rot = bone.LocalRotation.EulerAngles; //float3 pos = bone.LocalPointToSpace(float3.Zero, bones[boneParents[node]]); //float3 rot = floatQ.LookRotation(pos).EulerAngles; if (tracking_rotations[node]) { fileWriters[user_id].Write(string.Format("{0:0.000000}\t{1:0.000000}\t{2:0.000000}", rot.Z, rot.X, rot.Y) + "\t"); } } } fileWriters[user_id].Write("\n"); } } }
private async void StartPlayingInternal() { try { if (generateAnimation) { metagen_comp.World.RunSynchronously(() => { animationRecorder = metagen_comp.Slot.AttachComponent <RecordingTool>(); animationRecorder.metagen_comp = metagen_comp; }); } //Dictionary<RefID, User>.ValueCollection users = metagen_comp.World.AllUsers; avatarManager = new metagen.AvatarManager(); List <UserMetadata> userMetadatas = new List <UserMetadata>(); userMetadatas.Add(new UserMetadata { userId = "U-test", bodyNodes = "", devices = "", headDevice = "", isPublic = true, isRecording = true, platform = "", userRefId = "ID2B00" }); Dictionary <RefID, AudioOutput> audio_outputs = new Dictionary <RefID, AudioOutput>(); foreach (UserMetadata user in userMetadatas) { if (!user.isRecording || !user.isPublic) { continue; //at the moment we only allow playing back of public recording, for privacy reasons. In the future, we'll allow private access to the data } RefID user_id = RefID.Parse(user.userRefId); UniLog.Log(user_id.ToString()); user_ids.Add(user_id); channel = new Channel("127.0.0.1:" + (40052).ToString(), ChannelCredentials.Insecure); client = new DataComm.DataCommClient(channel); output_readers[user_id] = client.GetPose(new Empty()).ResponseStream; fake_proxies[user_id] = new List <Tuple <BodyNode, AvatarObjectSlot> >(); avatar_pose_nodes[user_id] = new List <Tuple <BodyNode, IAvatarObject> >(); avatar_stream_channels[user_id] = new Dictionary <BodyNode, Tuple <bool, bool, bool> >(); proxy_slots[user_id] = new Dictionary <BodyNode, Slot>(); if (avatarManager.avatar_template == null && avatar_template != null) { avatarManager.avatar_template = avatar_template; } Slot avatar = await avatarManager.GetAvatar(); UniLog.Log("AVATAR"); UniLog.Log(avatar.ToString()); avatars[user_id] = avatar; List <IAvatarObject> components = avatar.GetComponentsInChildren <IAvatarObject>(); List <AvatarObjectSlot> root_comps = avatar.GetComponentsInChildren <AvatarObjectSlot>(); boness[user_id] = avatar.GetComponentInChildren <Rig>()?.Bones.ToList(); VRIKAvatar avatarIK = avatar.GetComponentInChildren <VRIKAvatar>(); //READ absolute time //output_readers[user_id].ReadSingle(); //READ number of body nodes int numBodyNodes = 28; //TODO CHECK for (int i = 0; i < numBodyNodes; i++) { //READ body node type //int nodeInt = //READ if scale stream exists bool scale_exists = true; //READ if position stream exists bool pos_exists = true; //READ if rotation stream exists bool rot_exists = true; BodyNode bodyNodeType = VNetcBodyNodeConverter[i]; bool node_found = false; foreach (IAvatarObject comp in components) { foreach (AvatarObjectSlot comp2 in root_comps) { if (comp.Node == bodyNodeType && comp2.Node == bodyNodeType) { UniLog.Log((comp.Node, scale_exists, pos_exists, rot_exists)); if (bodyNodeType == BodyNode.Root) { proxy_slots[user_id][bodyNodeType] = avatar; } else { proxy_slots[user_id][bodyNodeType] = comp.Slot; } comp.Equip(comp2); if (bodyNodeType != BodyNode.Root) { SyncRef <Slot> sourceField = (SyncRef <Slot>)comp.GetType().GetField("_source", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(comp); sourceField.Target = null; FieldDrive <float3> posField = (FieldDrive <float3>)comp.GetType().GetField("_position", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(comp); posField.Target = null; FieldDrive <floatQ> rotField = (FieldDrive <floatQ>)comp.GetType().GetField("_rotation", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(comp); rotField.Target = null; } fake_proxies[user_id].Add(new Tuple <BodyNode, AvatarObjectSlot>(bodyNodeType, comp2)); avatar_pose_nodes[user_id].Add(new Tuple <BodyNode, IAvatarObject>(comp.Node, comp)); comp2.IsTracking.Value = true; if (bodyNodeType == BodyNode.LeftFoot || bodyNodeType == BodyNode.RightFoot) { avatarIK.ForceUseFeetProxies.Value = true; } if (bodyNodeType == BodyNode.LeftLowerLeg || bodyNodeType == BodyNode.RightLowerLeg) { avatarIK.ForceUseKneeProxies.Value = true; } if (bodyNodeType == BodyNode.LeftLowerArm || bodyNodeType == BodyNode.RightLowerArm) { avatarIK.ForceUseElbowProxies.Value = true; } if (bodyNodeType == BodyNode.Chest) { avatarIK.ForceUseChestProxy.Value = true; } if (bodyNodeType == BodyNode.Hips) { avatarIK.ForceUsePelvisProxy.Value = true; } node_found = true; break; } if (node_found) { break; } } } //if (!node_found) throw new Exception("Node " + bodyNodeType.ToString() + " not found in avatar!"); if (!node_found) { fake_proxies[user_id].Add(new Tuple <BodyNode, AvatarObjectSlot>(bodyNodeType, null)); avatar_pose_nodes[user_id].Add(new Tuple <BodyNode, IAvatarObject>(bodyNodeType, null)); } avatar_stream_channels[user_id][bodyNodeType] = new Tuple <bool, bool, bool>(scale_exists, pos_exists, rot_exists); } Slot avatarRootSlot = avatar.GetComponentInChildren <AvatarRoot>()?.Slot; if (avatarRootSlot != null) { avatarRootSlot.LocalPosition = new float3(0, 0, 0); avatarRootSlot.LocalRotation = new floatQ(0, 0, 0, 1); } //READ whether hands are being tracked hands_are_tracked[user_id] = false; //READ whether metacarpals are being tracked //output_readers[user_id].ReadBoolean(); List <HandPoser> these_hand_posers = avatar.GetComponentsInChildren <HandPoser>(null, excludeDisabled: false, includeLocal: false); UniLog.Log("getting finger rotation vars"); finger_slots[user_id] = new Dictionary <BodyNode, Slot>(); hand_posers[user_id] = new Dictionary <Chirality, HandPoser>(); finger_compensations[user_id] = new Dictionary <BodyNode, floatQ>(); foreach (HandPoser hand_poser in these_hand_posers) { UniLog.Log("HI"); hand_posers[user_id][hand_poser.Side] = hand_poser; BodyNode side1 = BodyNode.LeftThumb_Metacarpal.GetSide((Chirality)hand_poser.Side); BodyNode side2 = BodyNode.LeftPinky_Tip.GetSide((Chirality)hand_poser.Side); for (BodyNode nodee = side1; nodee <= side2; ++nodee) { int index = nodee - side1; FingerType fingerType = nodee.GetFingerType(); FingerSegmentType fingerSegmentType = nodee.GetFingerSegmentType(); HandPoser.FingerSegment fingerSegment = hand_poser[fingerType][fingerSegmentType]; if (fingerSegment != null && fingerSegment.Root.Target != null)//&& fingerSegment.RotationDrive.IsLinkValid) { UniLog.Log(nodee.ToString()); finger_slots[user_id][nodee] = fingerSegment.Root.Target; proxy_slots[user_id][nodee] = fingerSegment.Root.Target; finger_compensations[user_id][nodee] = fingerSegment.CoordinateCompensation.Value; fingerSegment.RotationDrive.Target = (IField <floatQ>)null; } } } UniLog.Log("got finger rotation vars"); //AUDIO PLAY audio_outputs[user_id] = null; //UniLog.Log("Setting up audio!"); //avatar.GetComponentInChildren<AudioOutput>().Source.Target = null; //for (int i = 0; i < 2; i++) //{ // string audio_file; // if (i==0) // { // if (!play_hearing) continue; // string[] files = Directory.GetFiles(reading_directory, user_id.ToString() + "*_hearing.ogg"); // audio_file = files.Length > 0 ? files[0] : null; // } else // { // if (!play_voice) continue; // string[] files = Directory.GetFiles(reading_directory, user_id.ToString() + "*_voice.ogg"); // audio_file = files.Length > 0 ? files[0] : null; // } // if (File.Exists(audio_file)) // { // AudioOutput audio_output = avatar.GetComponentInChildren<AudioOutput>(); // if (audio_output.Source.Target != null) audio_output = audio_output.Slot.AttachComponent<AudioOutput>(); // VisemeAnalyzer visemeAnalyzer = avatar.GetComponentInChildren<VisemeAnalyzer>(); // audio_output.Volume.Value = 1f; // audio_output.Enabled = true; // //audio_outputs[user_id] = audio_output; // //AudioX audioData = new AudioX(reading_directory + "/" + user_id.ToString() + "_audio.wav"); // //AssetRef<AudioClip> audioClip = new AssetRef<AudioClip>(); // Uri uri = this.World.Engine.LocalDB.ImportLocalAsset(audio_file, LocalDB.ImportLocation.Original, (string)null); // //ToWorld thing = new ToWorld(); // //var awaiter = thing.GetAwaiter(); // //awaiter.GetResult(); // StaticAudioClip audioClip = audio_output.Slot.AttachAudioClip(uri); // AudioClipPlayer player = audio_output.Slot.AttachComponent<AudioClipPlayer>(); // if (visemeAnalyzer != null) // { // visemeAnalyzer.Source.Target = player; // } // UniLog.Log("attaching clip to player"); // player.Clip.Target = (IAssetProvider<AudioClip>) audioClip; // UniLog.Log("attaching player to audio output"); // audio_output.Source.Target = (IAudioSource) player; // audio_output.Slot.AttachComponent<AudioMetadata>(true, (Action<AudioMetadata>)null).SetFromCurrentWorld(); // player.Play(); // } //} } avatars_finished_loading = true; isPlaying = true; if (generateAnimation) { animationRecorder.StartRecordingAvatars(avatars, audio_outputs); } if (generateBvh) { bvhRecorder.StartRecordingAvatars(avatars); } } catch (Exception e) { UniLog.Log("TwT: " + e.Message); UniLog.Log(e.StackTrace); } }
//Record one chunk from the voice audio of each user public void InteractAudio() { //Debug.Log("Recording audio"); foreach (var item in audio_outputs) { AudioOutput audio_output = item.Value; RefID user_id = item.Key; if (audio_output != null) { buffer.EnsureSize <float>(metagen_comp.Engine.AudioSystem.BufferSize, false); if (audio_output.Source.Target != null) { //AudioSystemConnector.InformOfDSPTime(AudioSettings.dspTime); FrooxEngine.Engine.Current.AudioRead(); audio_sources_ready = true; AudioStream <MonoSample> stream = (AudioStream <MonoSample>)audio_output.Source.Target; stream.Read <MonoSample>(buffer.AsMonoBuffer()); for (int i = 0; i < buffer.Length; i++) { buffer[i] = MathX.Clamp(buffer[i], -1, 1); } float max_val = 0; for (int i = 0; i < buffer.Length; i++) { float val_squared = (float)Math.Pow((double)buffer[i], (double)2); //if (val_squared > max_val) max_val = val_squared; if (val_squared > max_val) { max_val = val_squared; break; } } if (isRecording[user_id]) { audio_recorders[user_id].ConvertAndWrite(buffer); //counting the number of consecutive all-zero buffers if (max_val == 0) { number_of_zero_buffers += 1; } else { number_of_zero_buffers = 0; } if (number_of_zero_buffers > zero_buffer_num_threshold) { StopWritingFile(user_id); } } else { //UniLog.Log(max_val); if (max_val > 0) { StartWritingFile(user_id); if (prev_buffer != null) { audio_recorders[user_id].ConvertAndWrite(prev_buffer); } audio_recorders[user_id].ConvertAndWrite(buffer); } } prev_buffer = buffer; //Task.Run(() => { audio_recorders[user_id].ConvertAndWrite(buffer); }); //metagen_comp.StartTask(async () => { audio_recorders[user_id].ConvertAndWrite(buffer); }); //} } else { UniLog.Log("Audio Output Source target was null! (hmm should we restart it?). Did it happen coz a user left (in which case we shouldn't restart it), or something else?"); //UniLog.Log("Restarting audio recording coz audio output source target was null!"); //StopRecording(); //StartRecording(); } } } }
public void StartRecordingInternal() { RegisterUserStreams("streams"); foreach (var userItem in metagen_comp.userMetaData) { User user = userItem.Key; UserMetadata metadata = userItem.Value; if (!metadata.isRecording || (metagen_comp.LocalUser == user && !metagen_comp.record_local_user)) { continue; } RefID user_id = user.ReferenceID; avatar_stream_drivers[user_id] = new List <Tuple <BodyNode, TransformStreamDriver> >(); List <AvatarObjectSlot> components = user.Root.Slot.GetComponentsInChildren <AvatarObjectSlot>(); finger_stream_drivers[user_id] = user.Root.Slot.GetComponent <FingerPoseStreamManager>(); avatar_object_slots[user_id] = new List <Tuple <BodyNode, AvatarObjectSlot> >(); tracked_device_positioners[user_id] = new List <Tuple <BodyNode, TrackedDevicePositioner> >(); //WRITE the absolute time output_writers[user_id].Write((float)DateTimeOffset.Now.ToUnixTimeMilliseconds()); //absolute time int numValidNodes = 0; foreach (AvatarObjectSlot comp in components) { if (comp.IsTracking.Value) { if (comp.Node.Value == BodyNode.NONE) { continue; } //if (comp.Node.Value == BodyNode.LeftController || comp.Node.Value == BodyNode.RightController || comp.Node.Value == BodyNode.NONE) continue; //if (comp.Node.Value == BodyNode.LeftHand || comp.Node.Value == BodyNode.RightHand) //{ // TrackedDevicePositioner positioner = comp.Slot.Parent.GetComponent<TrackedDevicePositioner>(); // UniLog.Log(positioner.TrackedDevice.BodyNodePositionOffset); // UniLog.Log(positioner.TrackedDevice.BodyNodeRotationOffset); //} //avatar_pose_nodes[user_id].Add(new Tuple<BodyNode, IAvatarObject>(comp.Node, comp.Equipped?.Target)); avatar_object_slots[user_id].Add(new Tuple <BodyNode, AvatarObjectSlot>(comp.Node, comp)); TransformStreamDriver driver = comp.Slot.Parent.GetComponent <TransformStreamDriver>(); TrackedDevicePositioner positioner = comp.Slot.Parent.GetComponent <TrackedDevicePositioner>(); tracked_device_positioners[user_id].Add(new Tuple <BodyNode, TrackedDevicePositioner>(comp.Node.Value, positioner)); if (driver != null) { avatar_stream_drivers[user_id].Add(new Tuple <BodyNode, TransformStreamDriver>(comp.Node.Value, driver)); } else //if the driver is not in the parent, then it is in the slot (which is what happens for the root) { driver = comp.Slot.GetComponent <TransformStreamDriver>(); avatar_stream_drivers[user_id].Add(new Tuple <BodyNode, TransformStreamDriver>(comp.Node.Value, driver)); } numValidNodes += 1; } } float3 avatar_root_scale = user.Root.Slot.GetComponentInChildren <AvatarRoot>().Scale.Value; float3 relative_avatar_scale = user.Root.Slot.GetComponentInChildren <AvatarRoot>().Slot.LocalScale / avatar_root_scale; //WRITE version identifier output_writers[user_id].Write(1001); //int //WRITE relative avatar scale output_writers[user_id].Write(relative_avatar_scale.x); //float output_writers[user_id].Write(relative_avatar_scale.y); //float output_writers[user_id].Write(relative_avatar_scale.z); //float //WRITE the number of body nodes output_writers[user_id].Write(numValidNodes); //int foreach (var item in avatar_stream_drivers[user_id]) { TransformStreamDriver driver = item.Item2; //WRITE the the body node types output_writers[user_id].Write((int)item.Item1); //WRITE whether scaleStream is set output_writers[user_id].Write(driver.ScaleStream.Target != null); //WRITE whether positionStream is set output_writers[user_id].Write(driver.PositionStream.Target != null); //WRITE whether rotationStream is set output_writers[user_id].Write(driver.RotationStream.Target != null); } //WRITE whether hands are being tracked output_writers[user_id].Write(finger_stream_drivers[user_id] != null); //WRITE whether metacarpals are tracked (just used as metadata) if (finger_stream_drivers[user_id] != null) { output_writers[user_id].Write(finger_stream_drivers[user_id].TracksMetacarpals); } else { output_writers[user_id].Write(false); } current_users.Add(user_id); } if (!external_control) { isRecording = true; } }
public void StartRecording() { foreach (var userItem in metagen_comp.userMetaData) { User user = userItem.Key; UserMetadata metadata = userItem.Value; if (!metadata.isRecording || (metagen_comp.LocalUser == user && !metagen_comp.record_local_user)) { continue; } RefID user_id = user.ReferenceID; InputDeviceStreamDriver inputDeviceStreamDriver = InputDeviceStreamDriverExtensions.GetInputDeviceStreamDriver(user); if (inputDeviceStreamDriver != null) { RegisterUserStream(user_id, "input_streams"); input_streams[user_id] = inputDeviceStreamDriver; current_tracked_users.Add(user_id); digitalStreams[user_id] = new List <ValueStream <bool> >(); analogStreams[user_id] = new List <ValueStream <float> >(); analog2DStreams[user_id] = new List <ValueStream <float2> >(); analog3DStreams[user_id] = new List <ValueStream <float3> >(); //IStandardController controller = metagen_comp.InputInterface.GetDevice<IStandardController>(d => d.Side == Chirality.Left); foreach (InputDeviceStreamDriver.Device device in inputDeviceStreamDriver.Devices) { //InputDevice inputDevice = metagen_comp.InputInterface.GetDevice<InputDevice>(d => d.DeviceIndex == device.DeviceIndex); //IStandardController controller = inputDevice as IStandardController; //Nullable<Chirality> side = null; //if (controller != null) //{ // side = controller.Side; //} List <Tuple <string, int> > propertyIndices = new List <Tuple <string, int> >(); foreach (InputDeviceStreamDriver.Driver <bool> digitalDriver in device.Digital_Drivers) { int index = digitalDriver.PropertyIndex.Value; ValueStream <bool> stream = digitalDriver.Stream.Target; //ControllerProperty property = inputDevice.GetProperty<Digital>(index); //string name = property.Name; string name = stream.Name; propertyIndices.Add(new Tuple <string, int>(name, index)); digitalStreams[user_id].Add(stream); } foreach (InputDeviceStreamDriver.Driver <float> analogDriver in device.Analog_Drivers) { int index = analogDriver.PropertyIndex.Value; ValueStream <float> stream = analogDriver.Stream.Target; //ControllerProperty property = inputDevice.GetProperty<Digital>(index); //string name = property.Name; string name = stream.Name; propertyIndices.Add(new Tuple <string, int>(name, index)); analogStreams[user_id].Add(stream); } foreach (InputDeviceStreamDriver.Driver <float2> analog2DDriver in device.Analog2D_Drivers) { int index = analog2DDriver.PropertyIndex.Value; ValueStream <float2> stream = analog2DDriver.Stream.Target; //ControllerProperty property = inputDevice.GetProperty<Digital>(index); //string name = property.Name; string name = stream.Name; propertyIndices.Add(new Tuple <string, int>(name, index)); analog2DStreams[user_id].Add(stream); } foreach (InputDeviceStreamDriver.Driver <float3> analog3DDriver in device.Analog3D_Drivers) { int index = analog3DDriver.PropertyIndex.Value; ValueStream <float3> stream = analog3DDriver.Stream.Target; //ControllerProperty property = inputDevice.GetProperty<Digital>(index); //string name = property.Name; string name = stream.Name; propertyIndices.Add(new Tuple <string, int>(name, index)); analog3DStreams[user_id].Add(stream); } inputDeviceMetadatas[user_id].Add(new InputDeviceMetadata() { //Name = inputDevice.Name, DeviceIndex = device.DeviceIndex, //Type = inputDevice.GetType(), //Side = side, PropertyIndices = propertyIndices }); } //WRITE number of input devices output_writers[user_id].Write(inputDeviceMetadatas[user_id].Count); foreach (InputDeviceMetadata inputDeviceMetadata in inputDeviceMetadatas[user_id]) { //WRITE device index output_writers[user_id].Write(inputDeviceMetadata.DeviceIndex); //WRITE number of properties for device output_writers[user_id].Write(inputDeviceMetadata.PropertyIndices.Count); foreach (Tuple <string, int> tuple in inputDeviceMetadata.PropertyIndices) { //WRITE property index int index = tuple.Item2; output_writers[user_id].Write(index); } } //CommonToolStreamDriver... } } isRecording = true; }
public void StartRecording() { source_type = Source.FILE; //NEED to run this world-sycnrhonously World currentWorld = metagen_comp.World; int currentTotalUpdates = currentWorld.TotalUpdates; Slot logix_slot = metagen_comp.World.RootSlot.AddSlot("temporary logix slot"); bool added_logix = false; currentWorld.RunSynchronously(() => { foreach (var userItem in metagen_comp.userMetaData) { User user = userItem.Key; UserMetadata metadata = userItem.Value; if (!metadata.isRecording || (metagen_comp.LocalUser == user && !metagen_comp.record_local_user)) { continue; } RefID user_id = user.ReferenceID; current_tracked_users.Add(user_id); ReferenceRegister <User> userRegister = logix_slot.AttachComponent <ReferenceRegister <User> >(); userRegister.Target.Target = user; StandardController standardControllerLeft = logix_slot.AttachComponent <FrooxEngine.LogiX.Input.StandardController>(); EnumInput <Chirality> nodeEnum = logix_slot.AttachComponent <EnumInput <Chirality> >(); nodeEnum.Value.Value = Chirality.Left; standardControllerLeft.User.Target = userRegister; standardControllerLeft.Node.Target = nodeEnum; SyncRef <ValueStream <bool> > _primaryStreamLeft = (SyncRef <ValueStream <bool> >) typeof(StandardController).GetField("_primaryStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerLeft); SyncRef <ValueStream <bool> > _secondaryStreamLeft = (SyncRef <ValueStream <bool> >) typeof(StandardController).GetField("_secondaryStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerLeft); SyncRef <ValueStream <bool> > _grabStreamLeft = (SyncRef <ValueStream <bool> >) typeof(StandardController).GetField("_grabStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerLeft); SyncRef <ValueStream <bool> > _menuStreamLeft = (SyncRef <ValueStream <bool> >) typeof(StandardController).GetField("_menuStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerLeft); SyncRef <ValueStream <float> > _strengthStreamLeft = (SyncRef <ValueStream <float> >) typeof(StandardController).GetField("_strengthStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerLeft); SyncRef <ValueStream <float2> > _axisStreamLeft = (SyncRef <ValueStream <float2> >) typeof(StandardController).GetField("_axisStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerLeft); StandardController standardControllerRight = logix_slot.AttachComponent <FrooxEngine.LogiX.Input.StandardController>(); EnumInput <Chirality> nodeEnum2 = logix_slot.AttachComponent <EnumInput <Chirality> >(); nodeEnum2.Value.Value = Chirality.Right; standardControllerRight.User.Target = userRegister; standardControllerRight.Node.Target = nodeEnum2; SyncRef <ValueStream <bool> > _primaryStreamRight = (SyncRef <ValueStream <bool> >) typeof(StandardController).GetField("_primaryStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerRight); SyncRef <ValueStream <bool> > _secondaryStreamRight = (SyncRef <ValueStream <bool> >) typeof(StandardController).GetField("_secondaryStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerRight); SyncRef <ValueStream <bool> > _grabStreamRight = (SyncRef <ValueStream <bool> >) typeof(StandardController).GetField("_grabStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerRight); SyncRef <ValueStream <bool> > _menuStreamRight = (SyncRef <ValueStream <bool> >) typeof(StandardController).GetField("_menuStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerRight); SyncRef <ValueStream <float> > _strengthStreamRight = (SyncRef <ValueStream <float> >) typeof(StandardController).GetField("_strengthStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerRight); SyncRef <ValueStream <float2> > _axisStreamRight = (SyncRef <ValueStream <float2> >) typeof(StandardController).GetField("_axisStream", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(standardControllerRight); primaryStreamsRefs[user_id] = new Tuple <SyncRef <ValueStream <bool> >, SyncRef <ValueStream <bool> > >(_primaryStreamLeft, _primaryStreamRight); secondaryStreamsRefs[user_id] = new Tuple <SyncRef <ValueStream <bool> >, SyncRef <ValueStream <bool> > >(_secondaryStreamLeft, _secondaryStreamRight); grabStreamsRefs[user_id] = new Tuple <SyncRef <ValueStream <bool> >, SyncRef <ValueStream <bool> > >(_grabStreamLeft, _grabStreamRight); menuStreamsRefs[user_id] = new Tuple <SyncRef <ValueStream <bool> >, SyncRef <ValueStream <bool> > >(_menuStreamLeft, _menuStreamRight); strengthStreamsRefs[user_id] = new Tuple <SyncRef <ValueStream <float> >, SyncRef <ValueStream <float> > >(_strengthStreamLeft, _strengthStreamRight); axisStreamsRefs[user_id] = new Tuple <SyncRef <ValueStream <float2> >, SyncRef <ValueStream <float2> > >(_axisStreamLeft, _axisStreamRight); } added_logix = true; UniLog.Log("Added logix"); }); metagen_comp.StartTask(async() => { Task task = Task.Run(() => { bool all_streams_not_null = false; List <RefID> good_tracking_users = new List <RefID>(); //UniLog.Log("HO"); while (!all_streams_not_null & currentWorld.TotalUpdates <= currentTotalUpdates + 60) { if (!added_logix) { continue; } //UniLog.Log("HI"); bool all_user_streams_not_null = true; all_streams_not_null = true; foreach (RefID user_id in current_tracked_users) { //HMM: why does using .Target here rather than .RawTarget give a NullReferenceException?? bool primary_streams_not_null = (primaryStreamsRefs[user_id].Item1.RawTarget != null) & (primaryStreamsRefs[user_id].Item2.RawTarget != null); bool secondary_streams_not_null = (secondaryStreamsRefs[user_id].Item1.RawTarget != null) & (secondaryStreamsRefs[user_id].Item2.RawTarget != null); bool grab_streams_not_null = (grabStreamsRefs[user_id].Item1.RawTarget != null) & (grabStreamsRefs[user_id].Item2.RawTarget != null); bool menu_streams_not_null = (menuStreamsRefs[user_id].Item1.RawTarget != null) & (menuStreamsRefs[user_id].Item2.RawTarget != null); bool strength_streams_not_null = (strengthStreamsRefs[user_id].Item1.RawTarget != null) & (strengthStreamsRefs[user_id].Item2.RawTarget != null); bool axis_streams_not_null = (axisStreamsRefs[user_id].Item1.RawTarget != null) & (axisStreamsRefs[user_id].Item2.RawTarget != null); all_user_streams_not_null = primary_streams_not_null & secondary_streams_not_null & grab_streams_not_null & menu_streams_not_null & strength_streams_not_null & axis_streams_not_null; if (all_user_streams_not_null) { if (!good_tracking_users.Contains(user_id)) { good_tracking_users.Add(user_id); UniLog.Log("Added user " + user_id.ToString()); } } all_streams_not_null &= all_user_streams_not_null; } } current_tracked_users = good_tracking_users; //Get CommonToolStreamDriver List <RefID> good_tracking_users2 = new List <RefID>(); foreach (RefID user_id in current_tracked_users) { User user = currentWorld.GetUser(user_id); List <CommonToolStreamDriver> commonToolStreamDrivers = user.Root.Slot.GetComponents <CommonToolStreamDriver>(); ValueStream <bool> primaryBlockedStreamLeft = null; ValueStream <bool> secondaryBlockedStreamLeft = null; ValueStream <bool> laserActiveStreamLeft = null; ValueStream <bool> showLaserToOthersStreamLeft = null; ValueStream <float3> laserTargetStreamLeft = null; ValueStream <float> grabDistanceStreamLeft = null; ValueStream <bool> primaryBlockedStreamRight = null; ValueStream <bool> secondaryBlockedStreamRight = null; ValueStream <bool> laserActiveStreamRight = null; ValueStream <bool> showLaserToOthersStreamRight = null; ValueStream <float3> laserTargetStreamRight = null; ValueStream <float> grabDistanceStreamRight = null; foreach (CommonToolStreamDriver driver in commonToolStreamDrivers) { if (driver.Side.Value == Chirality.Left) { primaryBlockedStreamLeft = driver.PrimaryBlockedStream.Target; secondaryBlockedStreamLeft = driver.SecondaryBlockedStream.Target; laserActiveStreamLeft = driver.LaserActiveStream.Target; showLaserToOthersStreamLeft = driver.ShowLaserToOthersStream.Target; laserTargetStreamLeft = driver.LaserTargetStream.Target; grabDistanceStreamLeft = driver.GrabDistanceStream.Target; } else if (driver.Side.Value == Chirality.Right) { primaryBlockedStreamRight = driver.PrimaryBlockedStream.Target; secondaryBlockedStreamRight = driver.SecondaryBlockedStream.Target; laserActiveStreamRight = driver.LaserActiveStream.Target; showLaserToOthersStreamRight = driver.ShowLaserToOthersStream.Target; laserTargetStreamRight = driver.LaserTargetStream.Target; grabDistanceStreamRight = driver.GrabDistanceStream.Target; } } bool all_common_tool_streams_not_null = primaryBlockedStreamLeft != null & primaryBlockedStreamRight != null & secondaryBlockedStreamLeft != null & secondaryBlockedStreamRight != null & laserActiveStreamLeft != null & laserActiveStreamRight != null & showLaserToOthersStreamLeft != null & showLaserToOthersStreamRight != null & laserTargetStreamLeft != null & laserActiveStreamRight != null & grabDistanceStreamLeft != null & grabDistanceStreamRight != null; if (all_common_tool_streams_not_null) { good_tracking_users2.Add(user_id); primaryBlockedStreams[user_id] = new Tuple <ValueStream <bool>, ValueStream <bool> >(primaryBlockedStreamLeft, primaryBlockedStreamRight); secondaryBlockedStreams[user_id] = new Tuple <ValueStream <bool>, ValueStream <bool> >(secondaryBlockedStreamLeft, secondaryBlockedStreamRight); laserActiveStreams[user_id] = new Tuple <ValueStream <bool>, ValueStream <bool> >(laserActiveStreamLeft, laserActiveStreamRight); showLaserToOthersStreams[user_id] = new Tuple <ValueStream <bool>, ValueStream <bool> >(showLaserToOthersStreamLeft, showLaserToOthersStreamRight); laserTargetStreams[user_id] = new Tuple <ValueStream <float3>, ValueStream <float3> >(laserTargetStreamLeft, laserTargetStreamRight); grabDistanceStreams[user_id] = new Tuple <ValueStream <float>, ValueStream <float> >(grabDistanceStreamLeft, grabDistanceStreamRight); } } current_tracked_users = good_tracking_users2; foreach (RefID user_id in current_tracked_users) { primaryStreams[user_id] = new Tuple <ValueStream <bool>, ValueStream <bool> >(primaryStreamsRefs[user_id].Item1.RawTarget, primaryStreamsRefs[user_id].Item2.RawTarget); secondaryStreams[user_id] = new Tuple <ValueStream <bool>, ValueStream <bool> >(secondaryStreamsRefs[user_id].Item1.RawTarget, secondaryStreamsRefs[user_id].Item2.RawTarget); grabStreams[user_id] = new Tuple <ValueStream <bool>, ValueStream <bool> >(grabStreamsRefs[user_id].Item1.RawTarget, grabStreamsRefs[user_id].Item2.RawTarget); menuStreams[user_id] = new Tuple <ValueStream <bool>, ValueStream <bool> >(menuStreamsRefs[user_id].Item1.RawTarget, menuStreamsRefs[user_id].Item2.RawTarget); strengthStreams[user_id] = new Tuple <ValueStream <float>, ValueStream <float> >(strengthStreamsRefs[user_id].Item1.RawTarget, strengthStreamsRefs[user_id].Item2.RawTarget); axisStreams[user_id] = new Tuple <ValueStream <float2>, ValueStream <float2> >(axisStreamsRefs[user_id].Item1.RawTarget, axisStreamsRefs[user_id].Item2.RawTarget); RegisterUserStream(user_id, "controller_streams"); } //Destroy LogiX nodes currentWorld.RunSynchronously(() => { logix_slot.Destroy(); }); isRecording = true; }); //await CancelAfterAsync(ct=>task, TimeSpan.FromSeconds(30), CancellationToken.None); await task; }); }