示例#1
0
    def recognition_callback(self, words, rule, words_are_dictation_mask):
        try:
            # Prepare the words and rule names for the element parsers
            rule_names = (rule.name,) + (('dgndictation',) if any(words_are_dictation_mask) else ())
            words_rules = tuple((word, 0 if not is_dictation else 1)
                for (word, is_dictation) in zip(words, words_are_dictation_mask))

            # Attempt to parse the recognition
            func = getattr(self.grammar, "process_recognition", None)
            if func:
                if not func(words):
                    return

            state = State(words_rules, rule_names, self.engine)
            state.initialize_decoding()
            for result in rule.decode(state):
                if state.finished():
                    root = state.build_parse_tree()
                    self.engine._recognition_observer_manager.notify_recognition(words, rule, root)
                    with debug_timer(self.engine._log.debug, "rule execution time"):
                        rule.process_recognition(root)
                    self.engine._recognition_observer_manager.notify_post_recognition(words, rule, root)
                    return

        except Exception as e:
            self.engine._log.error("Grammar %s: exception: %s" % (self.grammar._name, e), exc_info=True)

        # If this point is reached, then the recognition was not processed successfully
        self.engine._log.error("Grammar %s: failed to decode rule %s recognition %r." % (self.grammar._name, rule.name, words))
示例#2
0
    def recognition_callback(self, recognition):
        words = recognition.words
        rule = recognition.kaldi_rule.parent_rule
        words_are_dictation_mask = recognition.words_are_dictation_mask
        try:
            assert (rule.active and rule.exported
                    ), "Kaldi engine should only ever return the correct rule"

            # Prepare the words and rule names for the element parsers
            rule_names = (rule.name, ) + (
                ('dgndictation', ) if any(words_are_dictation_mask) else ())
            words_rules = tuple(
                (word, 0 if not is_dictation else 1)
                for (word,
                     is_dictation) in zip(words, words_are_dictation_mask))

            # Attempt to parse the recognition
            func = getattr(self.grammar, "process_recognition", None)
            if func:
                if not self._process_grammar_callback(
                        func, words=words, results=recognition):
                    # Return early if the method didn't return True or equiv.
                    return

            state = State(words_rules, rule_names, self.engine)
            state.initialize_decoding()
            for result in rule.decode(state):
                if state.finished():
                    root = state.build_parse_tree()
                    notify_args = (words, rule, root, recognition)
                    self.recobs_manager.notify_recognition(*notify_args)
                    with debug_timer(self.engine._log.debug,
                                     "rule execution time"):
                        rule.process_recognition(root)
                    self.recobs_manager.notify_post_recognition(*notify_args)
                    return

        except Exception as e:
            self.engine._log.error("Grammar %s: exception: %s" %
                                   (self.grammar._name, e),
                                   exc_info=True)

        # If this point is reached, then the recognition was not processed successfully
        self.engine._log.error(
            "Grammar %s: failed to decode rule %s recognition %r." %
            (self.grammar._name, rule.name, words))
示例#3
0
    def recognition_callback(self, StreamNumber, StreamPosition,
                             RecognitionType, Result):
        try:
            newResult = Dispatch(Result)
            phrase_info = newResult.PhraseInfo
            rule_name = phrase_info.Rule.Name

            #---------------------------------------------------------------
            # Build a list of rule names for each element.

            # First populate it with the top level rule name.
            element = phrase_info.Rule
            name = element.Name
            start = element.FirstElement
            count = element.NumberOfElements
            rule_names = [name] * count

            # Walk the tree of child rules and put their names in the list.
            stack = [collection_iter(phrase_info.Rule.Children)]
            while stack:
                try:
                    element = next(stack[-1])
                except StopIteration:
                    stack.pop()
                    continue
                name = element.Name
                start = element.FirstElement
                count = element.NumberOfElements
                rule_names[start:start + count] = [name] * count
                if element.Children:
                    stack.append(collection_iter(element.Children))

            #---------------------------------------------------------------
            # Prepare the words and rule names for the element parsers.

            replacements = [False] * len(rule_names)
            if phrase_info.Replacements:
                for replacement in collection_iter(phrase_info.Replacements):
                    begin = replacement.FirstElement
                    end = begin + replacement.NumberOfElements
                    replacements[begin] = replacement.Text
                    for index in range(begin + 1, end):
                        replacements[index] = True

            results = []
            rule_set = list(set(rule_names))

            elements = phrase_info.Elements
            for index in range(len(rule_names)):
                element = elements.Item(index)
                rule_id = rule_set.index(rule_names[index])

                # Map dictation rule IDs to 1M so that dragonfly recognizes
                # the words as dictation.
                if rule_names[index] == "dgndictation":
                    rule_id = 1000000

                replacement = replacements[index]
                info = [
                    element.LexicalForm, rule_id, element.DisplayText,
                    element.DisplayAttributes, replacement
                ]
                results.append(info)

            #---------------------------------------------------------------
            # Retain audio

            # Only write audio data and metadata if the directory exists.
            retain_dir = self.engine._retain_dir
            if retain_dir and not os.path.isdir(retain_dir):
                self.engine._log.warning(
                    "Audio was not retained because '%s' was not a "
                    "directory" % retain_dir)
            elif retain_dir:
                try:
                    file_stream = Dispatch("SAPI.SpFileStream")
                    # Note: application can also retrieve smaller portions
                    # of the audio stream by specifying a starting phrase
                    # element and phrase element length.
                    audio_stream = newResult.Audio()

                    # Make sure we have audio data, which we wouldn't from a
                    # mimic or if the retain flag wasn't set above.
                    if audio_stream:
                        # Write audio data.
                        file_stream.Format = audio_stream.Format
                        now = datetime.now()
                        filename = ("retain_%s.wav" %
                                    now.strftime("%Y-%m-%d_%H-%M-%S_%f"))
                        wav_path = os.path.join(retain_dir, filename)
                        flags = constants.SSFMCreateForWrite
                        file_stream.Open(wav_path, flags)
                        try:
                            file_stream.Write(audio_stream.GetData())
                        finally:
                            file_stream.Close()

                        # Write metadata
                        words = ' '.join([r[2] for r in results])
                        audio_length = int(newResult.Times.Length) / 1e7
                        tsv_path = os.path.join(retain_dir, "retain.tsv")
                        with open(tsv_path, "a") as tsv_file:
                            tsv_file.write('\t'.join([
                                filename,
                                str(audio_length), self.grammar.name,
                                rule_name, words
                            ]) + '\n')
                except:
                    self.engine._log.exception("Exception retaining audio")

            #---------------------------------------------------------------
            # Attempt to parse the recognition.

            func = getattr(self.grammar, "process_recognition", None)
            words = tuple([r[0] for r in results])
            if func:
                if not self._process_grammar_callback(
                        func, words=words, results=newResult):
                    return

            s = State(results, rule_set, self.engine)
            for r in self.grammar.rules:
                if not (r.active and r.exported):
                    continue

                s.initialize_decoding()
                for result in r.decode(s):
                    if s.finished():
                        # Notify recognition observers, then process the
                        # rule.
                        root = s.build_parse_tree()
                        notify_args = (words, r, root, newResult)
                        self.recobs_manager.notify_recognition(*notify_args)
                        r.process_recognition(root)
                        self.recobs_manager.notify_post_recognition(
                            *notify_args)
                        return

        except Exception as e:
            Sapi5Engine._log.error("Grammar %s: exception: %s" %
                                   (self.grammar._name, e),
                                   exc_info=True)

        #-------------------------------------------------------------------
        # If this point is reached, then the recognition was not
        #  processed successfully..

        self.engine._log.error("Grammar %s: failed to decode"
                               " recognition %r." %
                               (self.grammar._name, [r[0] for r in results]))