예제 #1
0
        /// <summary>
        /// Compiler.
        /// </summary>
        /// <param name="posSet">POS set.</param>
        /// <param name="outputStream">Output Stream.</param>
        /// <returns>ErrorSet.</returns>
        public static ErrorSet Compile(TtsPosSet posSet, Stream outputStream)
        {
            if (posSet == null)
            {
                throw new ArgumentNullException("posSet");
            }

            if (outputStream == null)
            {
                throw new ArgumentNullException("outputStream");
            }

            posSet.Validate();
            ErrorSet errorSet = posSet.ErrorSet;
            if (!errorSet.Contains(ErrorSeverity.MustFix))
            {
                SortedDictionary<uint, string> sortedPosSet = new SortedDictionary<uint, string>();
                foreach (KeyValuePair<uint, string> pair in posSet.IdItems)
                {
                    sortedPosSet.Add(pair.Key, pair.Value);
                }

                BinaryWriter bw = new BinaryWriter(outputStream);
                {
                    // write the size of the structure for verification purchase
                    bw.Write(((uint)Marshal.SizeOf(typeof(PosData))));

                    // write the phoneme count
                    bw.Write((uint)posSet.IdItems.Count);

                    // write phonemes array
                    foreach (KeyValuePair<uint, string> pair in sortedPosSet)
                    {
                        PosData posData = new PosData(pair.Value, pair.Key);
                        bw.Write(Helper.ToBytes(posData));
                    }
                }
            }

            return errorSet;
        }
예제 #2
0
 /// <summary>
 /// Initializes a new instance of the HtsFont class.
 /// </summary>
 /// <param name="phoneSet">Phone set.</param>
 /// <param name="posSet">Part of speech.</param>
 public HtsFont(TtsPhoneSet phoneSet, TtsPosSet posSet)
 {
     Helper.ThrowIfNull(phoneSet);
     Helper.ThrowIfNull(posSet);
     _phoneSet = phoneSet;
     _posSet = posSet;
 }
        public LinguistciFeatureExtractor(IEnumerable<LinguisticFeatureInfo> featureInfos, TtsPhoneSet phoneSet,
            TtsPosSet posSet, CustomizedFeaturePluginManager manager, ILogger logger)
        {
            if (featureInfos == null)
            {
                throw new ArgumentNullException("featureInfos");
            }

            if (phoneSet == null)
            {
                throw new ArgumentNullException("phoneSet");
            }

            if (posSet == null)
            {
                throw new ArgumentNullException("posSet");
            }

            Logger = logger ?? new NullLogger();
            PhoneSet = phoneSet;
            PosSet = posSet;

            // Builds the name of feature name set.
            FeatureNameSetName = Helper.NeutralFormat("VoiceModelTrainer.{0}", PhoneSet.Language.ToString());

            try
            {
                // Creates a feature extration engine.
                ExtractionEngine = new FeatureExtractionEngine();

                // Creates the feature meta data.
                FeatureMetas = ExtractionEngine.Convert(LabelFeatureNameSet.MandatoryFeatureNames.ToList());
                FeatureInfos = new List<LinguisticFeatureInfo>();
                FeatureValueRecords = new List<FeatureValueRecord>();
                for (int i = 0; i < LabelFeatureNameSet.MandatoryFeatureNames.Length; ++i)
                {
                    FeatureInfos.Add(null);
                    FeatureValueRecords.Add(new FeatureValueRecord());
                }

                foreach (LinguisticFeatureInfo info in featureInfos)
                {
                    FeatureValueRecords.Add(new FeatureValueRecord());
                    int index = Array.IndexOf(LabelFeatureNameSet.MandatoryFeatureNames, info.Name);
                    if (index < 0)
                    {
                        FeatureMetas.Add(ExtractionEngine.Convert(info.Name, info.ExtendedProperty));
                        FeatureInfos.Add(info);
                    }
                    else
                    {
                        FeatureInfos[index] = info;
                    }
                }
            }
            catch (EspException e)
            {
                throw new InvalidDataException("Feature extraction engine error", e);
            }

            // Checks whether need pos and ToBI accent.
            for (int i = 0; i < FeatureMetas.Count; ++i)
            {
                if (!NeedPos &&
                    (FeatureMetas[i].Property == TtsFeatureProperty.TTS_FEATURE_PROPERTY_POS ||
                        FeatureMetas[i].Property == TtsFeatureProperty.TTS_FEATURE_PROPERTY_POSTAGGER_POS))
                {
                    NeedPos = true;
                }

                if (!NeedToBI &&
                    (FeatureMetas[i].Property == TtsFeatureProperty.TTS_FEATURE_PROPERTY_PRIMARY_ACCENT_POSITION ||
                        FeatureMetas[i].Property == TtsFeatureProperty.TTS_FEATURE_PROPERTY_SYLL_NUM_FROM_LEFT_ACCENT ||
                        FeatureMetas[i].Property == TtsFeatureProperty.TTS_FEATURE_PROPERTY_SYLL_NUM_TO_RIGHT_ACCENT ||
                        FeatureMetas[i].Property == TtsFeatureProperty.TTS_FEATURE_PROPERTY_ACCENTED_SYLL_NUM_BEFORE_CURR_SYLL ||
                        FeatureMetas[i].Property == TtsFeatureProperty.TTS_FEATURE_PROPERTY_ACCENTED_SYLL_NUM_AFTER_CURR_SYLL ||
                        FeatureMetas[i].Property == TtsFeatureProperty.TTS_FEATURE_PROPERTY_ACCENT ||
                        FeatureMetas[i].Property == TtsFeatureProperty.TTS_FEATURE_PROPERTY_TOBI_ACCENT ||
                        FeatureMetas[i].Property == TtsFeatureProperty.TTS_FEATURE_PROPERTY_IS_ACCENTED ||
                        FeatureMetas[i].Property == TtsFeatureProperty.TTS_FEATURE_PROPERTY_TOBI_FINAL_BOUNDARY_TONE))
                {
                    NeedToBI = true;
                }
            }

            // Gets Phoneme according to phone set.
            MemoryStream phoneStream = new MemoryStream();
            ErrorSet errorSet = PhoneSetCompiler.Compile(phoneSet, phoneStream);
            if (errorSet.Count > 0)
            {
                foreach (Error error in errorSet.Errors)
                {
                    Logger.LogLine(error.ToString());
                }

                if (errorSet.Contains(ErrorSeverity.MustFix))
                {
                    throw new InvalidDataException("Error happens in tts phone set compiling");
                }
            }

            phoneStream.Seek(0, SeekOrigin.Begin);
            Phoneme = new Phoneme(phoneStream, (Language)phoneSet.Language);

            // Gets the utterance extenders.
            if (manager != null)
            {
                List<PluginInfo> pluginInfos = manager.GetPlugins(CustomizedFeaturePluginManager.AttachBeforeExtraction);
                if (pluginInfos != null)
                {
                    UtteranceExtenders = UtteranceExtenderFinder.LoadUtteranceExtenders(pluginInfos);
                }
            }

            // Initialize ZhToneIndexPlugin if the language is zh-CN
            if (Language.ZhCN == (Language)phoneSet.Language)
            {
                ChineseToneIndexExtractor = new ChineseToneIndexExtractor();
                ChineseToneIndexExtractor.Initialize(Phoneme);
            }

            // Creates feature name set.
            if (LabelFeatureNameSet.Exist(FeatureNameSetName))
            {
                FeatureNameSet = LabelFeatureNameSet.Query(FeatureNameSetName);
            }
            else
            {
                FeatureNameSet = LabelFeatureNameSet.Create(FeatureNameSetName,
                    FeatureMetas.Select(o => o.Name).ToList());
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="UtteranceBuilder"/> class.
        /// </summary>
        /// <param name="phoneSet">
        /// The phone set.
        /// </param>
        /// <param name="posSet">
        /// The pos set.
        /// </param>
        /// <param name="phoneme">
        /// The phoneme.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// Exception.
        /// </exception>
        public UtteranceBuilder(TtsPhoneSet phoneSet, TtsPosSet posSet, Phoneme phoneme)
        {
            if (phoneSet == null)
            {
                throw new ArgumentNullException("phoneSet");
            }

            if (posSet == null)
            {
                throw new ArgumentNullException("posSet");
            }

            if (phoneme == null)
            {
                throw new ArgumentNullException("phoneme");
            }

            PhoneSet = phoneSet;
            PosSet = posSet;
            Phoneme = phoneme;
            NeedPunctuation = false;
        }
예제 #5
0
        /// <summary>
        /// Validate Lexicon according to pos set and phone set.
        /// </summary>
        /// <param name="ttsPhoneSet">TTS phone set.</param>
        /// <param name="ttsPosSet">TTS POS set.</param>
        public void Validate(TtsPhoneSet ttsPhoneSet, TtsPosSet ttsPosSet)
        {
            if (ttsPosSet == null)
            {
                throw new ArgumentNullException("ttsPosSet");
            }

            if (ttsPhoneSet == null)
            {
                throw new ArgumentNullException("ttsPhoneSet");
            }

            if (!ttsPosSet.Language.Equals(Language))
            {
                throw new InvalidDataException(Error.BuildMessage(CommonError.NotConsistentLanguage,
                    Language.ToString(), "lexicon", ttsPosSet.Language.ToString(), "pos set"));
            }

            if (!ttsPhoneSet.Language.Equals(Language))
            {
                throw new InvalidDataException(Error.BuildMessage(CommonError.NotConsistentLanguage,
                    Language.ToString(), "lexicon", ttsPhoneSet.Language.ToString(), "phone set"));
            }

            Validate(ttsPhoneSet, ttsPosSet, null);
        }
예제 #6
0
        /// <summary>
        /// Validate Lexicon according to TTS phone set and pos set or lexical attribute schema.
        /// </summary>
        /// <param name="ttsPhoneSet">TTS phone set.</param>
        /// <param name="ttsPosSet">TTS POS set.</param>
        /// <param name="attributeSchema">Lexical attribute Schema.</param>
        private void Validate(TtsPhoneSet ttsPhoneSet, TtsPosSet ttsPosSet,
            LexicalAttributeSchema attributeSchema)
        {
            Debug.Assert(ttsPhoneSet != null);
            Debug.Assert(ttsPosSet != null || attributeSchema != null);
            bool dependentDataValid = true;
            ttsPhoneSet.Validate();
            if (ttsPhoneSet.ErrorSet.Contains(ErrorSeverity.MustFix))
            {
                ErrorSet.Add(LexiconError.InvalidDependentData, "Phone set");
                dependentDataValid = false;
            }

            if (ttsPosSet != null)
            {
                ttsPosSet.Validate();
                if (ttsPosSet.ErrorSet.Contains(ErrorSeverity.MustFix))
                {
                    ErrorSet.Add(LexiconError.InvalidDependentData, "POS set");
                    dependentDataValid = false;
                }
            }

            if (attributeSchema != null)
            {
                attributeSchema.Validate();
                if (attributeSchema.ErrorSet.Contains(ErrorSeverity.MustFix))
                {
                    ErrorSet.Add(LexiconError.InvalidDependentData, "Lexical Attribute Schema");
                    dependentDataValid = false;
                }
            }

            if (dependentDataValid)
            {
                bool containValidItem = false;
                foreach (LexicalItem lexItem in Items.Values)
                {
                    ErrorSet errorSet = lexItem.Validate(ttsPhoneSet, ttsPosSet, attributeSchema);
                    ErrorSet.Merge(errorSet);
                    containValidItem = containValidItem || lexItem.Valid;
                }

                if (!containValidItem)
                {
                    ErrorSet.Add(LexiconError.EmptyLexicon);
                }
            }

            validated = true;
        }
예제 #7
0
        /// <summary>
        /// Write the pst data.
        /// </summary>
        /// <param name="pstFile">The pst file name to be stored.</param>
        /// <param name="data">The pst data to be write.</param>
        /// <param name="ttsPhoneSet">The tts Phone set.</param>
        /// <param name="ttsPosSet">The tts pst set.</param>
        public void WritePSTData(string pstFile, PSTData data, TtsPhoneSet ttsPhoneSet, TtsPosSet ttsPosSet)
        {
            foreach (Question question in data.DecisionForest.QuestionList)
            {
                question.Language = ttsPhoneSet.Language;
                question.ValueSetToCodeValueSet(ttsPosSet, ttsPhoneSet, data.CustomFeatures);
            }

            FileStream file = new FileStream(pstFile, FileMode.Create);
            try
            {
                using (DataWriter writer = new DataWriter(file))
                {
                    file = null;
                    uint position = 0;

                    // Write header section place holder
                    PreselectionFileHeader header = new PreselectionFileHeader();
                    position += (uint)header.Write(writer);

                    HtsFontSerializer serializer = new HtsFontSerializer();

                    using (StringPool stringPool = new StringPool())
                    {
                        Dictionary<string, uint> questionIndexes = new Dictionary<string, uint>();

                        header.QuestionOffset = position;
                        header.QuestionSize = serializer.Write(
                            data.QuestionSet, writer, stringPool, questionIndexes, data.CustomFeatures);
                        position += header.QuestionSize;

                        // Write leaf referenced data to buffer
                        List<CandidateSetData> dataNodes = data.CadidateSets;
                        int val = data.CadidateSets.Sum(c => c.Candidates.Count);
                        using (MemoryStream candidateSetBuffer = new MemoryStream())
                        {
                            Dictionary<string, int> namedSetOffset = new Dictionary<string, int>();

                            int candidateSetSize = HtsFontSerializer.Write(
                                dataNodes, new DataWriter(candidateSetBuffer), namedSetOffset);

                            // Write decision forest
                            Dictionary<string, uint[]> namedOffsets =
                                namedSetOffset.ToDictionary(p => p.Key, p => new[] { (uint)p.Value });

                            header.DecisionTreeSectionOffset = position;

                            header.DecisionTreeSectionSize = (uint)Write(data.DecisionForest, data.TreeIndexes,
                                questionIndexes, data.QuestionSet, namedOffsets, new DecisionForestSerializer(), writer);
                            position += header.DecisionTreeSectionSize;

                            // Write string pool
                            header.StringPoolOffset = position;
                            header.StringPoolSize = HtsFontSerializer.Write(stringPool, writer);
                            position += header.StringPoolSize;

                            // Write leaf referenced data
                            header.CandidateSetSectionOffset = position;
                            header.CandidateSetSectionSize = writer.Write(candidateSetBuffer.ToArray());
                            position += header.CandidateSetSectionSize;
                        }

                        // Write header section place holder
                        using (PositionRecover recover = new PositionRecover(writer, 0))
                        {
                            header.Write(writer);
                        }
                    }
                }
            }
            finally
            {
                if (null != file)
                {
                    file.Dispose();
                }
            }
        }
예제 #8
0
        /// <summary>
        /// Compile the POS set into PosTaggerPos binary.
        /// </summary>
        /// <param name="posSet">POS set.</param>
        /// <param name="outputStream">Output stream.</param>
        /// <returns>Error set.</returns>
        public static ErrorSet CompilePosTaggerPos(TtsPosSet posSet, Stream outputStream)
        {
            if (posSet == null)
            {
                throw new ArgumentNullException("posSet");
            }

            if (outputStream == null)
            {
                throw new ArgumentNullException("outputStream");
            }

            posSet.Validate();
            ErrorSet errorSet = posSet.ErrorSet;
            if (!errorSet.Contains(ErrorSeverity.MustFix))
            {
                BinaryWriter bw = new BinaryWriter(outputStream);
                if (bw != null)
                {
                    bw.Write(Convert.ToUInt32(posSet.Items.Count));
                    foreach (KeyValuePair<string, uint> pair in posSet.Items)
                    {
                        // Warning: do not check the value whether larger than maximal of 16bit.
                        Debug.Assert(pair.Value <= 0xFFFE);
                        bw.Write(Convert.ToUInt16(pair.Value));
                    }
                }
            }

            return errorSet;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="XmlScriptValidateSetting"/> class.
        /// </summary>
        /// <param name="phoneSet">Phone set.</param>
        /// <param name="posSet">POS set.</param>
        public XmlScriptValidateSetting(TtsPhoneSet phoneSet, TtsPosSet posSet) 
        {
            _scope = XmlScriptValidationScope.None;

            if (phoneSet != null)
            {
                _scope |= XmlScriptValidationScope.Pronunciation;
            }

            if (posSet != null)
            {
                _scope |= XmlScriptValidationScope.POS;
            }

            _phoneSet = phoneSet;
            _posSet = posSet;
        }
예제 #10
0
        /// <summary>
        /// Load POS Set Data object.
        /// </summary>
        /// <param name="errorSet">ErrorSet.</param>
        /// <returns>POS Set Data object.</returns>
        internal override object LoadDataObject(ErrorSet errorSet)
        {
            if (errorSet == null)
            {
                throw new ArgumentNullException("errorSet");
            }

            TtsPosSet posSet = new TtsPosSet();
            posSet.Load(this.Path);
            return posSet;
        }
 /// <summary>
 /// Initializes a new instance of the PreSelectionSerializer class.
 /// </summary>
 /// <param name="phoneSet">Phone set object.</param>
 /// <param name="posSet">POS set object.</param>
 public PreSelectionSerializer(TtsPhoneSet phoneSet, TtsPosSet posSet)
 {
     _phoneSet = phoneSet;
     _posSet = posSet;
 }
예제 #12
0
        /// <summary>
        /// Validate lexicon item.
        /// </summary>
        /// <param name="ttsPhoneSet">Phone set to validate lexicon item's pronunciation.</param>
        /// <param name="ttsPosSet">Pos set of the lexicon item.</param>
        /// <param name="attributeSchema">Attribute schema.</param>
        /// <returns>Error set of the validation.</returns>
        public ErrorSet Validate(TtsPhoneSet ttsPhoneSet, TtsPosSet ttsPosSet,
            LexicalAttributeSchema attributeSchema)
        {
            Debug.Assert(ttsPhoneSet != null);
            Debug.Assert(ttsPosSet != null || attributeSchema != null);
            ErrorSet errorSet = new ErrorSet();

            // Merge duplicate pronunciation node
            Collection<LexiconPronunciation> distinctPronunciations = new Collection<LexiconPronunciation>();
            Dictionary<string, int> pronunciationIndex = new Dictionary<string, int>();
            int pronunciationCount = 0;
            foreach (LexiconPronunciation lexPron in Pronunciations)
            {
                // Validate duplicate pronunciation node
                if (pronunciationIndex.ContainsKey(lexPron.Symbolic))
                {
                    errorSet.Add(LexiconError.DuplicatePronunciationNode, Grapheme, lexPron.Symbolic);

                    lexPron.Valid = false;
                    foreach (LexiconItemProperty property in lexPron.Properties)
                    {
                        Collection<LexiconItemProperty> targetProperties =
                            distinctPronunciations[pronunciationIndex[lexPron.Symbolic]].Properties;
                        if (!targetProperties.Contains(property))
                        {
                            targetProperties.Add(property);
                        }
                        else
                        {
                            errorSet.Add(LexiconError.DuplicateProperty, Grapheme, lexPron.Symbolic);
                        }
                    }
                }
                else
                {
                    distinctPronunciations.Add(lexPron);
                    pronunciationIndex[lexPron.Symbolic] = pronunciationCount;
                    pronunciationCount++;
                }
            }

            _pronunciations = distinctPronunciations;

            int invalidPronNodeNum = 0;
            foreach (LexiconPronunciation lexPron in Pronunciations)
            {
                // lexPron.Valid will be false if contains error.
                ValidatePronunciation(Grapheme, lexPron, ttsPhoneSet, errorSet);

                // Validate the POS information
                int invalidPropertyNum = 0;
                foreach (LexiconItemProperty property in lexPron.Properties)
                {
                    // Lexicon schema ensures that the POS property is existed
                    Debug.Assert(property.PartOfSpeech != null);

                    if (PosItem.Validate(property.PartOfSpeech.Value,
                        ttsPosSet, attributeSchema).Count > 0)
                    {
                        errorSet.Add(LexiconError.UnrecognizedPos, Grapheme,
                            lexPron.Symbolic, property.PartOfSpeech.Value);
                        property.Valid = false;
                    }

                    if (attributeSchema != null)
                    {
                        ErrorSet attributeErrorSet = ValidateAttributeSet(property, attributeSchema);
                        foreach (Error error in attributeErrorSet.Errors)
                        {
                            errorSet.Add(LexiconError.AttributeError, error, Grapheme, lexPron.Symbolic);
                        }

                        if (attributeErrorSet.Contains(ErrorSeverity.MustFix))
                        {
                            property.Valid = false;
                        }
                    }

                    if (property.AttributeSet.Count > 0 &&
                        (property.Case != null || property.Gender != null || property.Number != null))
                    {
                        errorSet.Add(LexiconError.MixedPropertyDefinition, Grapheme, lexPron.Symbolic);
                        property.Valid = false;
                    }
                    else
                    {
                        ValidateCase(Grapheme, property, errorSet);
                        ValidateGender(Grapheme, property, errorSet);
                        ValidateNumber(Grapheme, property, errorSet);
                    }

                    if (!property.Valid)
                    {
                        invalidPropertyNum++;
                    }
                }

                if (lexPron.Properties.Count == invalidPropertyNum)
                {
                    lexPron.Valid = false;
                }

                if (!lexPron.Valid)
                {
                    invalidPronNodeNum++;
                }
            }

            if (Pronunciations.Count == invalidPronNodeNum)
            {
                Valid = false;
            }

            return errorSet;
        }
예제 #13
0
        /// <summary>
        /// Validate pos string.
        /// </summary>
        /// <param name="posStr">Pos string to be validated.</param>
        /// <param name="ttsPosSet">Tts pos set for validation.</param>
        /// <param name="attributeSchema">Lexicon attribute schema for validation.</param>
        /// <returns>Validate result.</returns>
        public static ErrorSet Validate(string posStr, TtsPosSet ttsPosSet,
            LexicalAttributeSchema attributeSchema)
        {
            ErrorSet errorSet = new ErrorSet();
            if ((attributeSchema != null && string.IsNullOrEmpty(attributeSchema.GenerateString(
                LexicalAttributeSchema.PosCategoryName, posStr))) ||
                (ttsPosSet != null && !ttsPosSet.Items.ContainsKey(posStr)))
            {
                errorSet.Add(PosError.UnrecognizedPos, posStr);
            }

            return errorSet;
        }