From 6125c7e8e6c7fa9109cd53754db75050e096469a Mon Sep 17 00:00:00 2001 From: yum Date: Sat, 15 Oct 2022 20:54:41 -0700 Subject: Add libunity.addTransition * Implement basic board toggle using new transition logic * Metadata can now restore from file --- Animations/TaSTT_Toggle_Off.anim | 20 +++++++- Animations/TaSTT_Toggle_On.anim | 20 +++++++- README.md | 2 + libunity.py | 99 ++++++++++++++++++++++++++++++++++++++++ transcribe.py | 13 +++++- 5 files changed, 151 insertions(+), 3 deletions(-) diff --git a/Animations/TaSTT_Toggle_Off.anim b/Animations/TaSTT_Toggle_Off.anim index 69b487a..7a604bc 100644 --- a/Animations/TaSTT_Toggle_Off.anim +++ b/Animations/TaSTT_Toggle_Off.anim @@ -29,6 +29,15 @@ AnimationClip: weightedMode: 0 inWeight: 0 outWeight: 0 + - serializedVersion: 3 + time: 0.016666668 + value: 0 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 @@ -57,7 +66,7 @@ AnimationClip: m_AdditiveReferencePoseClip: {fileID: 0} m_AdditiveReferencePoseTime: 0 m_StartTime: 0 - m_StopTime: 0 + m_StopTime: 0.016666668 m_OrientationOffsetY: 0 m_Level: 0 m_CycleOffset: 0 @@ -85,6 +94,15 @@ AnimationClip: weightedMode: 0 inWeight: 0 outWeight: 0 + - serializedVersion: 3 + time: 0.016666668 + value: 0 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 diff --git a/Animations/TaSTT_Toggle_On.anim b/Animations/TaSTT_Toggle_On.anim index 874daf1..667cfdf 100644 --- a/Animations/TaSTT_Toggle_On.anim +++ b/Animations/TaSTT_Toggle_On.anim @@ -29,6 +29,15 @@ AnimationClip: weightedMode: 0 inWeight: 0 outWeight: 0 + - serializedVersion: 3 + time: 0.016666668 + value: 1 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 @@ -57,7 +66,7 @@ AnimationClip: m_AdditiveReferencePoseClip: {fileID: 0} m_AdditiveReferencePoseTime: 0 m_StartTime: 0 - m_StopTime: 0 + m_StopTime: 0.016666668 m_OrientationOffsetY: 0 m_Level: 0 m_CycleOffset: 0 @@ -85,6 +94,15 @@ AnimationClip: weightedMode: 0 inWeight: 0 outWeight: 0 + - serializedVersion: 3 + time: 0.016666668 + value: 1 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 diff --git a/README.md b/README.md index 8cc14bf..e4940ec 100644 --- a/README.md +++ b/README.md @@ -162,6 +162,8 @@ To use the STT: that the parameter memory usage may not decrease. 2. Optimize FX layer. We have 14k animations and a 1.2 million line FX layer. Something must be rethought to bring these numbers down. + 3. Implement multicore YAML parsing. This will make working with large + animators much more practical. 5. Bugfixes 1. The whisper STT says "Thank you." when there's no audio? diff --git a/libunity.py b/libunity.py index 9d7fac0..365529f 100644 --- a/libunity.py +++ b/libunity.py @@ -169,10 +169,45 @@ AnimatorState: m_TimeParameter: """[1:][:-1] +TRANSITION_TEMPLATE = """ +--- !u!1101 &110100000 +AnimatorStateTransition: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: + m_Conditions: [] + m_DstStateMachine: {fileID: 0} + m_DstState: {fileID: 0} + m_Solo: 0 + m_Mute: 0 + m_IsExit: 0 + serializedVersion: 3 + m_TransitionDuration: 0 + m_TransitionOffset: 0 + m_ExitTime: 1.0 + m_HasExitTime: 1 + m_HasFixedDuration: 1 + m_InterruptionSource: 0 + m_OrderedInterruption: 1 + m_CanTransitionToSelf: 1 +"""[1:][:-1] + class Metadata: def __init__(self): self.guid = "%032x" % random.randrange(16 ** 32) + def load(self, path): + if not path.endswith(".meta"): + path = path + ".meta" + + self.guid = None + with open(path, "r") as f: + for line in f: + if line.startswith("guid"): + self.guid = line.split()[1] + def __str__(self): return METADATA_TEMPLATE.replace("REPLACEME_GUID", self.guid) @@ -621,6 +656,22 @@ class UnityAnimator(): return node + def addTransition(self, dst_state_id): + # Create animation state + parser = UnityParser() + parser.parse(TRANSITION_TEMPLATE) + new_transition = UnityAnimator() + new_transition.addNodes(parser.nodes) + node = new_transition.nodes[0] + + new_id = self.allocateId('1101') + node.anchor = str(new_id) + state = node.mapping['AnimatorStateTransition'] + state.mapping['m_DstState'].mapping['fileID'] = dst_state_id + self.nodes.append(node) + + return node + def fixWriteDefaults(self, guid_map, generated_anim_path): # TODO(yum) we should have an Animation class which encapsulates all # this stuff. @@ -705,6 +756,38 @@ class UnityAnimator(): #print("generated layer: {}".format(str(layer)), file=sys.stderr) #print("generated state: {}".format(str(state)), file=sys.stderr) + # TODO(yum) this should be factored out into generate_fx.py + def addTasttToggle(self, off_anim_path, on_anim_path, toggle_param): + self.addParameter(toggle_param, bool) + + off_anim_meta = Metadata() + off_anim_meta.load(off_anim_path) + + on_anim_meta = Metadata() + on_anim_meta.load(on_anim_path) + + layer = self.addLayer('TaSTT_Toggle') + off_anim = self.addAnimatorState(layer, 'TaSTT_Toggle_Off', off_anim_meta.guid, is_default_state = True) + on_anim = self.addAnimatorState(layer, 'TaSTT_Toggle_On', on_anim_meta.guid) + + # TODO(yum) make a Transition class with methods for adding boolean + # conditions + off_to_on = self.addTransition(on_anim.anchor) + cond = off_to_on.mapping['AnimatorStateTransition'].mapping['m_Conditions'].addChildMapping() + cond.mapping['m_ConditionMode'] = '1' + cond.mapping['m_ConditionEvent'] = toggle_param + cond.mapping['m_EventThreshold'] = '0' + trans = off_anim.mapping['AnimatorState'].mapping['m_Transitions'].addChildMapping() + trans.mapping['fileID'] = off_to_on.anchor + + on_to_off = self.addTransition(off_anim.anchor) + cond = on_to_off.mapping['AnimatorStateTransition'].mapping['m_Conditions'].addChildMapping() + cond.mapping['m_ConditionMode'] = '2' + cond.mapping['m_ConditionEvent'] = toggle_param + cond.mapping['m_EventThreshold'] = '0' + trans = on_anim.mapping['AnimatorState'].mapping['m_Transitions'].addChildMapping() + trans.mapping['fileID'] = on_to_off.anchor + def unityAnimatorToString(nodes): lines = [] preamble = """ @@ -942,6 +1025,22 @@ if __name__ == "__main__": anim.fixWriteDefaults(guid_map, "generated/animations/TaSTT_Reset_Animation.anim") print(str(anim)) + elif args.cmd == "add_toggle": + if not args.fx0: + print("--fx0 required") + parser.print_help() + parser.exit(1) + + print("Parsing {}".format(args.fx0), file=sys.stderr) + parser0 = UnityParser() + parser0.parseFile(args.fx0) + + anim = UnityAnimator() + anim.addNodes(parser0.nodes) + anim.addTasttToggle("Animations/TaSTT_Toggle_Off.anim", + "Animations/TaSTT_Toggle_On.anim", "TaSTT_Toggle") + print(str(anim)) + else: print("Unrecognized command: {}".format(args.cmd)) diff --git a/transcribe.py b/transcribe.py index ea83520..9170152 100644 --- a/transcribe.py +++ b/transcribe.py @@ -173,11 +173,22 @@ def transcribeAudio(audio_state, model): # 3. If the transcription is somewhat long and the # first few characters change, we assume this is due to a # trim event and immediately accept the transcription. + commit_transcription = False if text == audio_state.text_candidate or text.startswith(audio_state.text_candidate): - audio_state.text = text + commit_transcription = True elif len(text) > 30 and len(audio_state.text_candidate) >= 10 and text[0:10] != audio_state.text_candidate[0:10]: audio_state.text = text + commit_transcription = True + + if commit_transcription: + old_len = len(audio_state.text_candidate) + new_len = len(text) + min_len = min(old_len, new_len) + overlap_fraction = 0.2 + overlap_len = int(0.2 * min_len) + if audio_state.text_candidate[old_len - overlap_len:old_len] == text_state[0:overlap_len] + audio_state.text = text audio_state.text_candidate = text audio_state.text_lock.release() -- cgit v1.2.3