Source code for annotations.Align.models.acm.acmodelhtkio

"""
:filename: sppas.src.annotations.Align.models.acm.acmodelhtkio.py
:author:   Brigitte Bigi
:contact:  develop@sppas.org
:summary:  I/O for HTK acoustic models.

.. _This file is part of SPPAS: http://www.sppas.org/
..
    -------------------------------------------------------------------------

     ___   __    __    __    ___
    /     |  \  |  \  |  \  /              the automatic
    \__   |__/  |__/  |___| \__             annotation and
       \  |     |     |   |    \             analysis
    ___/  |     |     |   | ___/              of speech

    Copyright (C) 2011-2021  Brigitte Bigi
    Laboratoire Parole et Langage, Aix-en-Provence, France

    Use of this software is governed by the GNU Public License, version 3.

    SPPAS is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    SPPAS is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with SPPAS. If not, see <http://www.gnu.org/licenses/>.

    This banner notice must not be removed.

    -------------------------------------------------------------------------

"""

import os
import collections
import glob

from sppas.src.dependencies.grako.parsing import graken, Parser
from sppas.src.config.makeunicode import basestring

from ..modelsexc import MioFolderError, MioFileError

from .hmm import sppasHMM
from .acmbaseio import sppasBaseIO

# ---------------------------------------------------------------------------


def _to_ordered_dict(ast):
    result = collections.OrderedDict()
    for k, v in ast.items():
        result[k] = v

    return result

# ---------------------------------------------------------------------------


[docs]class sppasHtkIO(sppasBaseIO): """HTK-ASCII acoustic models reader/writer. This class is able to load and save HMM-based acoustic models from HTK-ASCII files. """
[docs] @staticmethod def detect(folder): """Return True if the folder contains the HTK-ASCII file(s) of an ACM. Expected files of this reader is mainly "hmmdefs". """ hmmdefs_files = glob.glob(os.path.join(folder, 'hmmdefs')) if len(hmmdefs_files) == 0: hmmdefs_files = glob.glob(os.path.join(folder, 'macros')) hmmdefs_files.extend(glob.glob(os.path.join(folder, 'vFloors'))) hmmdefs_files.extend(glob.glob(os.path.join(folder, '*.hmm'))) if len(hmmdefs_files) == 0: return False return True
# -----------------------------------------------------------------
[docs] def __init__(self, name=None): """Create a sppasHtkIO instances. :param name: (str) An identifier name for the Acoustic Model. By default, the name of the class is used. """ if name is None: name = self.__class__.__name__ super(sppasHtkIO, self).__init__(name)
# -----------------------------------------------------------------------
[docs] def read(self, folder, filename=None): """Load all known data from a folder or only the given file. The default file names are: - hmmdefs for an HTK-ASCII acoustic model; - macros for a separated macro description; - vFloors for a separated description allowing to construct the macro; - tiedlist for triphone models; - monophones.repl to map between phoneme representations. :param folder: (str) Folder name of the acoustic model :param filename: (str) Optional name of a single file to read """ # Find the hmmdefs file, or the other files if filename is None: hmmdefs_files = glob.glob(os.path.join(folder, "hmmdefs")) if len(hmmdefs_files) == 0: hmmdefs_files = glob.glob(os.path.join(folder, 'macros')) hmmdefs_files.extend(glob.glob(os.path.join(folder, '*.hmm'))) if len(hmmdefs_files) == 0: hmmdefs_files = glob.glob(os.path.join(folder, 'vFloors')) if len(hmmdefs_files) == 0: raise MioFolderError(folder) else: # Find the given file hmmdefs_files = glob.glob(os.path.join(folder, filename)) if len(hmmdefs_files) == 0: raise MioFolderError(folder) # Read the macros and the hmms try: self.read_macros_hmms(hmmdefs_files) except Exception: raise MioFolderError(folder) if filename is None: # Find and load the tiedlist file tiedlist_files = glob.glob(os.path.join(folder, 'tiedlist')) if len(tiedlist_files) == 1: self.read_tiedlist(tiedlist_files[0]) # Find and load the monophones.repl file repl_files = glob.glob(os.path.join(folder, 'monophones.repl')) if len(repl_files) == 1: self.read_phonesrepl(repl_files[0])
# -----------------------------------------------------------------------
[docs] def write(self, folder, filename="hmmdefs"): """Save the model into a file, in HTK-ASCII standard format. The default file names are: - hmmdefs (macros + hmms); - tiedlist (if triphones); - monophones.repl. :param folder: (str) Folder name of the acoustic model :param filename: (str) Optional name of the file to write macros and hmms """ if os.path.isdir(folder) is False: os.mkdir(folder) # Write macros and hmms in the hmmdefs file filename = os.path.join(folder, filename) with open(filename, 'w') as f: if self._macros is not None: if len(self._hmms) > 0: f.write(sppasHtkIO._serialize_macros(self._macros, variance=False, mean=False)) else: f.write(sppasHtkIO._serialize_macros(self._macros)) if len(self._hmms) > 0: f.write(sppasHtkIO._serialize_hmms(self._hmms)) # write tiedlist if self._tiedlist.is_empty() is False: self._tiedlist.save(os.path.join(folder, 'tiedlist')) # write monophones.repl if self._repllist.is_empty() is False: self._repllist.save_as_ascii(os.path.join(folder, 'monophones.repl'))
# -----------------------------------------------------------------------
[docs] @staticmethod def read_hmm(filename): """Return the (first) HMM described into the given filename. :param filename: (str) File to read. :returns: (sppasHMM) """ folder_name, file_name = os.path.split(filename) parser = sppasHtkIO() parser.read(folder_name, file_name) if len(parser.get_hmms()) < 1: raise MioFolderError(filename) return parser.get_hmms()[0]
# -----------------------------------------------------------------------
[docs] @staticmethod def write_hmm(hmm, filename): """Save a single hmm into the given filename. :param hmm: (sppasHMM) The HMM model to write :param filename: (str) Name of the file to write. """ result = sppasHtkIO._serialize_hmms([hmm]) with open(filename, 'w') as f: f.write(result)
# -----------------------------------------------------------------------
[docs] @staticmethod def write_hmm_proto(proto_size, proto_filename): """Write a `proto` file. The proto is based on a 5-states HMM. :param proto_size: (int) Number of mean and variance values. It's commonly either 25 or 39, it depends on the MFCC parameters. :param proto_filename: (str) Full name of the prototype to write. """ with open(proto_filename, "w") as fp: means = "0.0 " * proto_size variances = "1.0 " * proto_size means = means.strip() variances = variances.strip() fp.write("~h \"proto\"\n") fp.write("<BeginHMM>\n") fp.write("<NumStates> 5\n") for i in range(2, 5): fp.write("<State> {}\n".format(i)) fp.write("<NumMixes> 1\n") fp.write("<Mixture> 1 1.0\n") fp.write("<Mean> {:d}\n".format(proto_size)) fp.write("{:s}\n".format(means)) fp.write("<Variance> {:d}\n".format(proto_size)) fp.write("{:s}\n".format(variances)) fp.write("<Transp> 5\n") fp.write(" 0.0 1.0 0.0 0.0 0.0\n") fp.write(" 0.0 0.6 0.4 0.0 0.0\n") fp.write(" 0.0 0.0 0.6 0.4 0.0\n") fp.write(" 0.0 0.0 0.0 0.7 0.3\n") fp.write(" 0.0 0.0 0.0 0.0 0.0\n") fp.write("<EndHMM>\n")
# -----------------------------------------------------------------------
[docs] def read_macros_hmms(self, filenames): """Load an HTK-ASCII model from one or more files. :param filenames: Name of the files of the model (e.g. macros and/or hmms files and/or hmmdefs) """ text = '' for fnm in filenames: with open(fnm, 'r') as fp: for line in fp.readlines(): line = line.strip() if len(line) > 0: text += line + "\n" if len(text) == 0: raise MioFileError(" ".join(filenames)) parser = HtkModelParser() htk_model = HtkModelSemantics() # OrderedDict() model = parser.parse(text, rule_name='model', ignorecase=True, semantics=htk_model, comments_re="\(\*.*?\*\)", trace=False) self._macros = model['macros'] self._hmms = list() for h in model['hmms']: new_hmm = sppasHMM() new_hmm.set_name(h['name']) new_hmm.set_definition(h['definition']) self._hmms.append(new_hmm)
# ----------------------------------------------------------------------- # Private # ----------------------------------------------------------------------- @staticmethod def _serialize_macros(macros, options=True, transition=True, variance=True, mean=True, state=True, duration=True): """Serialize macros into a string, in HTK-ASCII standard format. :param macros: (OrderedDict) Macros to save :returns: The HTK-ASCII macros as a string. """ result = '' # First serialize the macros for macro in macros: if macro.get('options', None) and options is True: result += '~o ' for option in macro['options']['definition']: result += sppasHtkIO._serialize_option(option) elif macro.get('transition', None) and transition is True: result += '~t "{}"\n'.format(macro['transition']['name']) result += sppasHtkIO._serialize_transp(macro['transition']['definition']) elif macro.get('variance', None) and variance is True: result += '~v "{}"\n'.format(macro['variance']['name']) result += sppasHtkIO._serialize_variance(macro['variance']['definition']) elif macro.get('state', None) and state is True: result += '~s "{}"\n'.format(macro['state']['name']) result += sppasHtkIO._serialize_stateinfo(macro['state']['definition']) elif macro.get('mean', None) and mean is True: result += '~u "{}"\n'.format(macro['mean']['name']) result += sppasHtkIO._serialize_mean(macro['mean']['definition']) elif macro.get('duration', None) and duration is True: result += '~d "{}"\n'.format(macro['duration']['name']) result += sppasHtkIO._serialize_duration(macro['duration']['definition']) #else: # raise NotImplementedError('Cannot serialize {}'.format(macro)) return result # ----------------------------------- @staticmethod def _serialize_hmms(hmms): """Serialize hmms into a string, in HTK-ASCII standard format. :returns: The HTK-ASCII model as a string. """ result = '' for hmm_model in hmms: if hmm_model.name is not None: result += sppasHtkIO._serialize_name(hmm_model.name) result += sppasHtkIO._serialize_definition(hmm_model.definition) return result # ---------------------------------- @staticmethod def _serialize_name(name): return '~h "{}"\n'.format(name) # ---------------------------------- @staticmethod def _serialize_definition(definition): result = '' result += '<BeginHMM>\n' if definition.get('options', None): for option in definition['options']: result += sppasHtkIO._serialize_option(option) result += '<NumStates> {}\n'.format(definition['state_count']) for state in definition['states']: result += sppasHtkIO._serialize_state(state) if definition.get('regression_tree', None) is not None: raise NotImplementedError('Cannot serialize {}'.format(definition['regression_tree'])) result += sppasHtkIO._serialize_transp(definition['transition']) if definition.get('duration', None) is not None: result += sppasHtkIO._serialize_duration(definition['duration']) result += '<EndHMM>\n' return result # ---------------------------------- @staticmethod def _serialize_option(option): result = '' if option.get('hmm_set_id', None) is not None: result += '<HmmSetId> {}'.format(option['hmm_set_id']) if option.get('stream_info', None) is not None: result += '<StreamInfo> {}'.format(option['stream_info']['count']) if option['stream_info'].get('sizes', None) is not None: result += ' {}'.format(' '.join(['{:d}'.format(v) for v in option['stream_info']['sizes']])) if option.get('vector_size', None) is not None: result += '<VecSize> {:d}'.format(option['vector_size']) if option.get('input_transform', None) is not None: raise NotImplementedError('Serialization of {} ' 'is not implemented.'.format(option['input_transform'])) if option.get('covariance_kind', None) is not None: result += '<{}>'.format(option['covariance_kind']) if option.get('duration_kind', None) is not None: result += '<{}>'.format(option['duration_kind']) if option.get('parameter_kind', None) is not None: result += '<{}{}>'.format(option['parameter_kind']['base'], ''.join(option['parameter_kind']['options'])) result += '\n' return result # ---------------------------------- @staticmethod def _serialize_transp(definition): if isinstance(definition, basestring): return '~t "{}"\n'.format(definition) result = '' result += '<TransP> {}\n'.format(definition['dim']) result += '{}'.format(sppasHtkIO._matrix_to_htk(definition['matrix'])) return result # ---------------------------------- @staticmethod def _serialize_variance(definition): if isinstance(definition, basestring): return '~v {}\n'.format(definition) result = '' result += '<Variance> {}\n'.format(definition['dim']) result += '{}'.format(sppasHtkIO._array_to_htk(definition['vector'])) return result # ---------------------------------- @staticmethod def _serialize_mean(definition): if isinstance(definition, basestring): return '~u "{}"\n'.format(definition) result = '' result += '<Mean> {}\n'.format(definition['dim']) result += '{}'.format(sppasHtkIO._array_to_htk(definition['vector'])) return result # ---------------------------------- @staticmethod def _serialize_duration(definition): if isinstance(definition, basestring): return '~d "{}"\n'.format(definition) result = '' result += '<Duration> {}\n'.format(definition['dim']) result += '{}'.format(sppasHtkIO._array_to_htk(definition['vector'])) return result # ---------------------------------- @staticmethod def _serialize_weights(definition): if isinstance(definition, basestring): return '~w "{}"\n'.format(definition) result = '' result += '<SWeights> {}\n'.format(definition['dim']) result += '{}'.format(sppasHtkIO._array_to_htk(definition['vector'])) return result # ---------------------------------- @staticmethod def _serialize_covariance(definition): result = '' if definition['variance'] is not None: result += sppasHtkIO._serialize_variance(definition['variance']) else: raise NotImplementedError('Cannot serialize {}'.format(definition)) return result # ---------------------------------- @staticmethod def _serialize_mixpdf(definition): if isinstance(definition, basestring): return '~m "{}"\n'.format(definition) result = '' if definition.get('regression_class', None) is not None: result += '<RClass> {}\n'.format(definition['regression_class']) result += sppasHtkIO._serialize_mean(definition['mean']) result += sppasHtkIO._serialize_covariance(definition['covariance']) if definition.get('gconst', None) is not None: result += '<GConst> {:.6e}\n'.format(definition['gconst']) return result # ---------------------------------- @staticmethod def _serialize_mixture(definition): result = '' if definition.get('index', None) is not None: result += '<Mixture> {} {:.6e}\n'.format(definition['index'], definition['weight']) result += sppasHtkIO._serialize_mixpdf(definition['pdf']) return result # ---------------------------------- @staticmethod def _serialize_stream(definition): result = '' if definition.get('dim', None) is not None: result += '<Stream> {}\n'.format(definition['dim']) if definition.get('mixtures', None) is not None: for mixture in definition['mixtures']: result += sppasHtkIO._serialize_mixture(mixture) else: raise NotImplementedError('Cannot serialize {}'.format(definition)) return result # ---------------------------------- @staticmethod def _serialize_stateinfo(definition): if isinstance(definition, basestring): return '~s "{}"\n'.format(definition) result = '' if definition.get('streams_mixcount', None): result += '<NumMixes> {}\n'.format(' '.join(['{}'.format(v) for v in definition['streams_mixcount']])) if definition.get('weights', None) is not None: result += sppasHtkIO._serialize_weights(definition['weights']) for stream in definition['streams']: result += sppasHtkIO._serialize_stream(stream) if definition.get('duration', None) is not None: result += sppasHtkIO._serialize_duration(definition['duration']) return result # ---------------------------------- @staticmethod def _serialize_state(definition): result = '' result += '<State> {}\n'.format(definition['index']) result += sppasHtkIO._serialize_stateinfo(definition['state']) return result # ---------------------------------- @staticmethod def _array_to_htk(arr): return ' {}\n'.format(' '.join(['{:2.6e}'.format(value) for value in arr])) # ---------------------------------- @staticmethod def _matrix_to_htk(mat): result = '' for arr in mat: result = result + sppasHtkIO._array_to_htk(arr) return result
# --------------------------------------------------------------------------- # Semantic of an HTK acoustic model. Used to parse files. # ---------------------------------------------------------------------------
[docs]class HtkModelSemantics(object): """Part of the Inspire package: https://github.com/rikrd/inspire. :author: Ricard Marxer. :license: GPL, v2 """
[docs] def __init__(self): pass
[docs] def matrix(self, ast): # return [float(v) for v in ast.split(' ')] return [float(v) for v in ast.split()]
[docs] def vector(self, ast): return [float(v) for v in ast.split(' ')]
[docs] def short(self, ast): return int(ast)
[docs] def float(self, ast): return float(ast)
[docs] def transPdef(self, ast): d = _to_ordered_dict(ast) d['matrix'] = [] aarray = [] d['array'].append(None) # for the last serie to be appended! for a in d['array']: if len(aarray) == ast['dim']: d['matrix'].append(aarray) aarray = [a] else: aarray.append(a) # numpy solution: # d['matrix'] = d['array'].reshape((ast['dim'], ast['dim'])) d.pop('array') return d
def _default(self, ast): if isinstance(ast, collections.Mapping): return _to_ordered_dict(ast) return ast def _unquote(self, txt): if txt.startswith('"') and txt.endswith('"'): return txt[1:-1] return txt
[docs] def string(self, ast): return self._unquote(ast)
def __repr__(self): return ''
# --------------------------------------------------------------------------- # HTK-ASCII Acoustic Model: Set of rules for the parser # ---------------------------------------------------------------------------
[docs]class HtkModelParser(Parser):
[docs] def __init__(self, whitespace=None, nameguard=True, **kwargs): super(HtkModelParser, self).__init__( whitespace=whitespace, nameguard=nameguard, **kwargs )
@graken() def _model_(self): def block0(): self._macrodef_() self.ast.setlist('macros', self.last_node) self._closure(block0) def block2(): self._hmmmacro_() self.ast.setlist('hmms', self.last_node) self._closure(block2) self.ast._define( [], ['macros', 'hmms'] ) @graken() def _macrodef_(self): with self._choice(): with self._option(): self._transPmacro_() self.ast['transition'] = self.last_node with self._option(): self._stateinfomacro_() self.ast['state'] = self.last_node with self._option(): self._optmacro_() self.ast['options'] = self.last_node with self._option(): self._varmacro_() self.ast['variance'] = self.last_node with self._option(): self._meanmacro_() self.ast['mean'] = self.last_node with self._option(): self._durationmacro_() self.ast['duration'] = self.last_node self._error('no available options') self.ast._define( ['transition', 'state', 'options', 'variance', 'mean', 'duration'], [] ) @graken() def _hmmmacro_(self): with self._optional(): self._hmmref_() self.ast['name'] = self.last_node self._hmmdef_() self.ast['definition'] = self.last_node self.ast._define( ['name', 'definition'], [] ) @graken() def _optmacro_(self): self._token('~o') self._cut() self._globalOpts_() self.ast['definition'] = self.last_node self.ast._define( ['definition'], [] ) @graken() def _transPmacro_(self): self._transPref_() self.ast['name'] = self.last_node self._transPdef_() self.ast['definition'] = self.last_node self.ast._define( ['name', 'definition'], [] ) @graken() def _stateinfomacro_(self): self._stateinforef_() self.ast['name'] = self.last_node self._stateinfodef_() self.ast['definition'] = self.last_node self.ast._define( ['name', 'definition'], [] ) @graken() def _varmacro_(self): self._varref_() self.ast['name'] = self.last_node self._vardef_() self.ast['definition'] = self.last_node self.ast._define( ['name', 'definition'], [] ) @graken() def _meanmacro_(self): self._meanref_() self.ast['name'] = self.last_node self._meandef_() self.ast['definition'] = self.last_node self.ast._define( ['name', 'definition'], [] ) @graken() def _durationmacro_(self): self._durationref_() self.ast['name'] = self.last_node self._durationdef_() self.ast['definition'] = self.last_node self.ast._define( ['name', 'definition'], [] ) @graken() def _varref_(self): self._token('~v') self._cut() self._macro_() self.ast['@'] = self.last_node @graken() def _transPref_(self): self._token('~t') self._cut() self._macro_() self.ast['@'] = self.last_node @graken() def _stateinforef_(self): self._token('~s') self._cut() self._macro_() self.ast['@'] = self.last_node @graken() def _hmmref_(self): self._token('~h') self._cut() self._macro_() self.ast['@'] = self.last_node @graken() def _weightsref_(self): self._token('~w') self._cut() self._macro_() self.ast['@'] = self.last_node @graken() def _mixpdfref_(self): self._token('~m') self._cut() self._macro_() self.ast['@'] = self.last_node @graken() def _meanref_(self): self._token('~u') self._cut() self._macro_() self.ast['@'] = self.last_node @graken() def _durationref_(self): self._token('~d') self._cut() self._macro_() self.ast['@'] = self.last_node @graken() def _invref_(self): self._token('~i') self._cut() self._macro_() self.ast['@'] = self.last_node @graken() def _xformref_(self): self._token('~x') self._cut() self._macro_() self.ast['@'] = self.last_node @graken() def _inputXformref_(self): self._token('~j') self._cut() self._macro_() self.ast['@'] = self.last_node @graken() def _macro_(self): self._string_() @graken() def _hmmdef_(self): self._token('<BeginHMM>') self._cut() with self._optional(): self._globalOpts_() self.ast['options'] = self.last_node self._token('<NumStates>') self._cut() self._short_() self.ast['state_count'] = self.last_node def block2(): self._state_() self.ast.setlist('states', self.last_node) self._positive_closure(block2) with self._optional(): self._regTree_() self.ast['regression_tree'] = self.last_node self._transP_() self.ast['transition'] = self.last_node with self._optional(): self._duration_() self.ast['duration'] = self.last_node self._token('<EndHMM>') self.ast._define( ['options', 'state_count', 'regression_tree', 'transition', 'duration'], ['states'] ) @graken() def _globalOpts_(self): def block1(): self._option_() self._positive_closure(block1) self.ast['@'] = self.last_node @graken() def _option_(self): with self._choice(): with self._option(): self._token('<HmmSetId>') self._cut() self._string_() self.ast['hmm_set_id'] = self.last_node with self._option(): self._token('<StreamInfo>') self._cut() self._streaminfo_() self.ast['stream_info'] = self.last_node with self._option(): self._token('<VecSize>') self._cut() self._short_() self.ast['vector_size'] = self.last_node with self._option(): self._token('<InputXform>') self._cut() self._inputXform_() self.ast['input_transform'] = self.last_node with self._option(): self._covkind_() self.ast['covariance_kind'] = self.last_node with self._option(): self._durkind_() self.ast['duration_kind'] = self.last_node with self._option(): self._parmkind_() self.ast['parameter_kind'] = self.last_node self._error('no available options') self.ast._define( ['hmm_set_id', 'stream_info', 'vector_size', 'input_transform', 'covariance_kind', 'duration_kind', 'parameter_kind'], [] ) @graken() def _streaminfo_(self): self._short_() self.ast['count'] = self.last_node def block2(): self._short_() self._closure(block2) self.ast['sizes'] = self.last_node self.ast._define( ['count', 'sizes'], [] ) @graken() def _covkind_(self): self._token('<') with self._group(): with self._choice(): with self._option(): self._token('diagc') with self._option(): self._token('invdiagc') with self._option(): self._token('fullc') with self._option(): self._token('lltc') with self._option(): self._token('xformc') self._error('expecting one of: diagc fullc invdiagc lltc xformc') self.ast['@'] = self.last_node self._token('>') @graken() def _durkind_(self): self._token('<') with self._group(): with self._choice(): with self._option(): self._token('nulld') with self._option(): self._token('poissond') with self._option(): self._token('gammad') with self._option(): self._token('gen') self._error('expecting one of: gammad gen nulld poissond') self.ast['@'] = self.last_node self._token('>') @graken() def _parmkind_(self): self._token('<') self._basekind_() self.ast['base'] = self.last_node def block2(): with self._choice(): with self._option(): self._token('_D') with self._option(): self._token('_A') with self._option(): self._token('_T') with self._option(): self._token('_E') with self._option(): self._token('_N') with self._option(): self._token('_Z') with self._option(): self._token('_O') with self._option(): self._token('_0') with self._option(): self._token('_V') with self._option(): self._token('_C') with self._option(): self._token('_K') self._error('expecting one of: _A _C _D _E _K _N _O _0 _T _V _Z') self._closure(block2) self.ast['options'] = self.last_node self._token('>') self.ast._define( ['base', 'options'], [] ) @graken() def _basekind_(self): with self._choice(): with self._option(): self._token('discrete') with self._option(): self._token('lpc') with self._option(): self._token('lpcepstra') with self._option(): self._token('mfcc') with self._option(): self._token('fbank') with self._option(): self._token('melspec') with self._option(): self._token('lprefc') with self._option(): self._token('lpdelcep') with self._option(): self._token('user') self._error('expecting one of: discrete fbank lpc lpcepstra lpdelcep lprefc melspec mfcc user') @graken() def _state_(self): self._token('<State>') self._cut() self._short_() self.ast['index'] = self.last_node self._stateinfo_() self.ast['state'] = self.last_node self.ast._define( ['index', 'state'], [] ) @graken() def _stateinfo_(self): with self._choice(): with self._option(): self._stateinforef_() self.ast['@'] = self.last_node with self._option(): self._stateinfodef_() self.ast['@'] = self.last_node self._error('no available options') @graken() def _stateinfodef_(self): with self._optional(): self._mixes_() self.ast['streams_mixcount'] = self.last_node with self._optional(): self._weights_() self.ast['weights'] = self.last_node def block2(): self._stream_() self.ast.setlist('streams', self.last_node) self._positive_closure(block2) with self._optional(): self._duration_() self.ast['duration'] = self.last_node self.ast._define( ['streams_mixcount', 'weights', 'duration'], ['streams'] ) @graken() def _mixes_(self): self._token('<NumMixes>') self._cut() def block1(): self._short_() self._positive_closure(block1) self.ast['@'] = self.last_node @graken() def _weights_(self): with self._choice(): with self._option(): self._weightsref_() self.ast['@'] = self.last_node with self._option(): self._weightsdef_() self.ast['@'] = self.last_node self._error('no available options') @graken() def _weightsdef_(self): self._token('<SWeights>') self._cut() self._short_() self.ast['dim'] = self.last_node self._vector_() self.ast['vector'] = self.last_node self.ast._define( ['dim', 'vector'], [] ) @graken() def _stream_(self): with self._optional(): self._token('<Stream>') self._cut() self._short_() self.ast['dim'] = self.last_node with self._group(): with self._choice(): with self._option(): def block1(): self._mixture_() self.ast.setlist('mixtures', self.last_node) self._positive_closure(block1) with self._option(): self._tmixpdf_() self.ast['tmixpdf'] = self.last_node with self._option(): self._discpdf_() self.ast['discpdf'] = self.last_node self._error('no available options') self.ast._define( ['dim', 'tmixpdf', 'discpdf'], ['mixtures'] ) @graken() def _mixture_(self): with self._optional(): self._token('<Mixture>') self._cut() self._short_() self.ast['index'] = self.last_node self._float_() self.ast['weight'] = self.last_node self._mixpdf_() self.ast['pdf'] = self.last_node self.ast._define( ['index', 'weight', 'pdf'], [] ) @graken() def _tmixpdf_(self): self._token('<TMix>') self._cut() self._macro_() self._weightList_() @graken() def _weightList_(self): def block0(): self._repShort_() self._positive_closure(block0) @graken() def _repShort_(self): self._short_() with self._optional(): self._token('*') self._cut() self._char_() @graken() def _discpdf_(self): self._token('<DProb>') self._cut() self._weightList_() @graken() def _mixpdf_(self): with self._choice(): with self._option(): self._mixpdfref_() self.ast['@'] = self.last_node with self._option(): self._mixpdfdef_() self.ast['@'] = self.last_node self._error('no available options') @graken() def _mixpdfdef_(self): with self._optional(): self._rclass_() self.ast['regression_class'] = self.last_node self._mean_() self.ast['mean'] = self.last_node self._cov_() self.ast['covariance'] = self.last_node with self._optional(): self._token('<GConst>') self._cut() self._float_() self.ast['gconst'] = self.last_node self.ast._define( ['regression_class', 'mean', 'covariance', 'gconst'], [] ) @graken() def _rclass_(self): self._token('<RClass>') self._cut() self._short_() self.ast['@'] = self.last_node @graken() def _mean_(self): with self._choice(): with self._option(): self._meanref_() self.ast['@'] = self.last_node with self._option(): self._meandef_() self.ast['@'] = self.last_node self._error('no available options') @graken() def _meandef_(self): self._token('<Mean>') self._cut() self._short_() self.ast['dim'] = self.last_node self._vector_() self.ast['vector'] = self.last_node self.ast._define( ['dim', 'vector'], [] ) @graken() def _cov_(self): with self._choice(): with self._option(): self._var_() self.ast['variance'] = self.last_node with self._option(): self._inv_() with self._option(): self._xform_() self._error('no available options') self.ast._define( ['variance'], [] ) @graken() def _var_(self): with self._choice(): with self._option(): self._varref_() self.ast['@'] = self.last_node with self._option(): self._vardef_() self.ast['@'] = self.last_node self._error('no available options') @graken() def _vardef_(self): self._token('<Variance>') self._cut() self._short_() self.ast['dim'] = self.last_node self._vector_() self.ast['vector'] = self.last_node self.ast._define( ['dim', 'vector'], [] ) @graken() def _inv_(self): with self._choice(): with self._option(): self._invref_() self.ast['@'] = self.last_node with self._option(): self._invdef_() self.ast['@'] = self.last_node self._error('no available options') @graken() def _invdef_(self): with self._group(): with self._choice(): with self._option(): self._token('<InvCovar>') with self._option(): self._token('<LLTCovar>') self._error('expecting one of: <InvCovar> <LLTCovar>') self.ast['type'] = self.last_node self._cut() self._short_() self.ast['dim'] = self.last_node self._tmatrix_() self.ast['matrix'] = self.last_node self.ast._define( ['type', 'dim', 'matrix'], [] ) @graken() def _xform_(self): with self._choice(): with self._option(): self._xformref_() self.ast['@'] = self.last_node with self._option(): self._xformdef_() self.ast['@'] = self.last_node self._error('no available options') @graken() def _xformdef_(self): self._token('<Xform>') self._cut() self._short_() self.ast['dim1'] = self.last_node self._short_() self.ast['dim2'] = self.last_node self._matrix_() self.ast['matrix'] = self.last_node self.ast._define( ['dim1', 'dim2', 'matrix'], [] ) @graken() def _tmatrix_(self): self._matrix_() @graken() def _duration_(self): with self._choice(): with self._option(): self._durationref_() self.ast['@'] = self.last_node with self._option(): self._durationdef_() self.ast['@'] = self.last_node self._error('no available options') @graken() def _durationdef_(self): self._token('<Duration>') self._cut() self._short_() self.ast['dim'] = self.last_node self._vector_() self.ast['vector'] = self.last_node self.ast._define( ['dim', 'vector'], [] ) @graken() def _regTree_(self): self._token('~r') self._cut() self._macro_() self.ast['@'] = self.last_node self._tree_() self.ast['tree'] = self.last_node self.ast._define( ['tree'], [] ) @graken() def _tree_(self): self._token('<RegTree>') self._cut() self._short_() self._nodes_() @graken() def _nodes_(self): with self._group(): with self._choice(): with self._option(): self._token('<Node>') self._cut() self._short_() self._short_() self._short_() with self._option(): self._token('<TNode>') self._cut() self._short_() self._int_() self._error('no available options') with self._optional(): self._nodes_() @graken() def _transP_(self): with self._choice(): with self._option(): self._transPref_() self.ast['@'] = self.last_node with self._option(): self._transPdef_() self.ast['@'] = self.last_node self._error('no available options') @graken() def _transPdef_(self): self._token('<TransP>') self._cut() self._short_() self.ast['dim'] = self.last_node self._matrix_() self.ast['array'] = self.last_node self.ast._define( ['dim', 'array'], [] ) @graken() def _inputXform_(self): with self._choice(): with self._option(): self._inputXformref_() self.ast['@'] = self.last_node with self._option(): self._inhead_() self._inmatrix_() self._error('no available options') @graken() def _inhead_(self): self._token('<MMFIdMask>') self._cut() self._string_() self._parmkind_() with self._optional(): self._token('<PreQual>') @graken() def _inmatrix_(self): self._token('<LinXform>') self._token('<VecSize>') self._cut() self._short_() self._token('<BlockInfo>') self._cut() self._short_() def block0(): self._short_() self._positive_closure(block0) def block1(): self._block_() self._positive_closure(block1) @graken() def _block_(self): self._token('<Block>') self._cut() self._short_() self._xform_() @graken() def _string_(self): self._pattern(r'.*') @graken() def _vector_(self): self._pattern(r'[\d.\-\+eE \n]+') @graken() def _matrix_(self): self._pattern(r'[\d.\-\+eE \n]+') @graken() def _short_(self): self._pattern(r'\d+') @graken() def _float_(self): self._pattern(r'[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?') @graken() def _char_(self): self._pattern(r'.') @graken() def _int_(self): self._pattern(r'[-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+)')