コード例 #1
0
ファイル: VoiceFont.cs プロジェクト: JohnsonYuan/TTSFramework
        /// <summary>
        /// Extract acoustic features for a given script file.
        /// </summary>
        /// <param name="script">Script file instance.</param>
        /// <param name="fileMap">File list map.</param>
        /// <param name="segmentDir">Segmentation file directory.</param>
        /// <param name="wave16kDir">16k Hz waveform file directory.</param>
        /// <param name="epochDir">Epoch file directory.</param>
        /// <param name="targetFilePath">Target acoustic file path.</param>
        public static void ExtractAcoustic(ScriptFile script, FileListMap fileMap,
            string segmentDir, string wave16kDir, string epochDir, string targetFilePath)
        {
            // Parameters validation
            if (script == null)
            {
                throw new ArgumentNullException("script");
            }

            if (string.IsNullOrEmpty(script.FilePath))
            {
                throw new ArgumentException("script.FilePath is null");
            }

            if (script.Items == null)
            {
                throw new ArgumentException("script.Items is null");
            }

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

            if (fileMap.Map == null)
            {
                throw new ArgumentException("fileMap.Map is null");
            }

            if (fileMap.Map.Keys == null)
            {
                throw new ArgumentException("fileMap.Map.Keys is null");
            }

            if (string.IsNullOrEmpty(segmentDir))
            {
                throw new ArgumentNullException("segmentDir");
            }

            if (string.IsNullOrEmpty(wave16kDir))
            {
                throw new ArgumentNullException("wave16kDir");
            }

            if (string.IsNullOrEmpty(epochDir))
            {
                throw new ArgumentNullException("epochDir");
            }

            if (!Directory.Exists(segmentDir))
            {
                throw Helper.CreateException(typeof(DirectoryNotFoundException),
                    segmentDir);
            }

            if (!Directory.Exists(wave16kDir))
            {
                throw Helper.CreateException(typeof(DirectoryNotFoundException),
                    wave16kDir);
            }

            if (!Directory.Exists(epochDir))
            {
                throw Helper.CreateException(typeof(DirectoryNotFoundException),
                    epochDir);
            }

            if (string.IsNullOrEmpty(targetFilePath))
            {
                throw new ArgumentNullException("targetFilePath");
            }

            Helper.EnsureFolderExistForFile(targetFilePath);

            using (StreamWriter sw = new StreamWriter(targetFilePath))
            {
                // iterate each script item or sentence
                foreach (string sid in fileMap.Map.Keys)
                {
                    if (!script.Items.ContainsKey(sid))
                    {
                        string message = string.Format(CultureInfo.InvariantCulture,
                            "Sentence [{0}] does not exist in script file [{1}].",
                            sid, script.FilePath);
                        throw new InvalidDataException(message);
                    }

                    ExtractAcoustic(sw, script, sid, fileMap, segmentDir, wave16kDir, epochDir);
                }
            }
        }
コード例 #2
0
ファイル: VoiceFont.cs プロジェクト: JohnsonYuan/TTSFramework
        /// <summary>
        /// Check data file consistence between segment, and wave files with the file map.
        /// </summary>
        /// <param name="fileMap">File list map.</param>
        /// <param name="waveDir">Waveform file directory.</param>
        /// <param name="segmentDir">Segmentation file directory.</param>
        /// <returns>Data error set found.</returns>
        public static DataErrorSet ValidateDataAlignment(
            FileListMap fileMap, string waveDir, string segmentDir)
        {
            // Parameter validation
            if (fileMap == null)
            {
                throw new ArgumentNullException("fileMap");
            }

            if (fileMap.Map == null)
            {
                throw new ArgumentException("fileMap.Map is null");
            }

            if (fileMap.Map.Keys == null)
            {
                throw new ArgumentException("fileMap.Map.Keys is null");
            }

            DataErrorSet errorSet = new DataErrorSet();

            // go through the file list map for each sentence
            foreach (string sid in fileMap.Map.Keys)
            {
                try
                {
                    string alignmentFile = Path.Combine(segmentDir, fileMap.Map[sid] + ".txt");
                    string waveFile = Path.Combine(waveDir, fileMap.Map[sid] + ".wav");

                    StringBuilder error = new StringBuilder();

                    ValidateDataAlignment(alignmentFile, waveFile, error);
                    if (error.Length > 0)
                    {
                        errorSet.Errors.Add(new DataError(string.Empty, error.ToString(), sid));
                    }
                }
                catch (InvalidDataException ide)
                {
                    string message = Helper.BuildExceptionMessage(ide);
                    errorSet.Errors.Add(new DataError(string.Empty, message, sid));
                }
            }

            return errorSet;
        }
コード例 #3
0
ファイル: VoiceFont.cs プロジェクト: JohnsonYuan/TTSFramework
        /// <summary>
        /// Check data consistence between script file and segmentation files.
        /// </summary>
        /// <param name="fileMap">File list map.</param>
        /// <param name="script">Script file instance.</param>
        /// <param name="segmentDir">Segment file directory.</param>
        /// <returns>Data error set found.</returns>
        public static DataErrorSet ValidateDataAlignment(
            FileListMap fileMap, ScriptFile script, string segmentDir)
        {
            // Parameters validation
            if (string.IsNullOrEmpty(segmentDir))
            {
                throw new ArgumentNullException("segmentDir");
            }

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

            if (fileMap.Map == null)
            {
                throw new ArgumentException("fileMap.Map is null");
            }

            if (fileMap.Map.Keys == null)
            {
                throw new ArgumentException("fileMap.Map.Keys is null");
            }

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

            if (script.Items == null)
            {
                throw new ArgumentException("script.Items is null");
            }

            if (script.Items.Values == null)
            {
                throw new ArgumentException("script.Items.Values is null");
            } 

            DataErrorSet errorSet = new DataErrorSet();

            foreach (ScriptItem item in script.Items.Values)
            {
                try
                {
                    if (!fileMap.Map.ContainsKey(item.Id))
                    {
                        errorSet.Errors.Add(new DataError(script.FilePath,
                            "File list map does not contain sentences.", item.Id));
                        continue;
                    }

                    ValidateDataAlignment(script, item, fileMap, segmentDir, errorSet, false);
                }
                catch (InvalidDataException ide)
                {
                    errorSet.Errors.Add(new DataError(script.FilePath,
                        Helper.BuildExceptionMessage(ide), item.Id));
                }
            }

            foreach (string sid in fileMap.Map.Keys)
            {
                if (!script.Items.ContainsKey(sid))
                {
                    errorSet.Errors.Add(new DataError(script.FilePath,
                        "script file does not contain the sentence.", sid));
                }
            }

            return errorSet;
        }
コード例 #4
0
ファイル: VoiceFont.cs プロジェクト: JohnsonYuan/TTSFramework
        /// <summary>
        /// Check data file consistence between script file and filemap file.
        /// </summary>
        /// <param name="fileMap">File list map.</param>
        /// <param name="script">Script file instance.</param>
        /// <returns>Data error set found.</returns>
        public static DataErrorSet ValidateDataAlignment(FileListMap fileMap,
            ScriptFile script)
        {
            // Parameters validation
            if (fileMap == null)
            {
                throw new ArgumentNullException("fileMap");
            }

            if (fileMap.Map == null)
            {
                throw new ArgumentException("fileMap.Map is null");
            }

            if (fileMap.Map.Keys == null)
            {
                throw new ArgumentException("fileMap.Map.Keys is null");
            }

            if (string.IsNullOrEmpty(fileMap.FilePath))
            {
                throw new ArgumentException("fileMap.FilePath is null");
            }

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

            if (script.Items == null)
            {
                throw new ArgumentException("script.Items is null");
            }

            if (script.Items.Keys == null)
            {
                throw new ArgumentException("script.Items.Keys is null");
            }

            if (string.IsNullOrEmpty(script.FilePath))
            {
                throw new ArgumentException("script.FilePath is null");
            }

            DataErrorSet errorSet = new DataErrorSet();

            // go through sentence ids listed in the filemap first
            foreach (string sid in fileMap.Map.Keys)
            {
                if (!script.Items.ContainsKey(sid))
                {
                    string message = string.Format(CultureInfo.InvariantCulture,
                        "Sentence [{0}] is found in the filemap [{1}], but not listed in script file [{2}].",
                        sid, fileMap.FilePath, script.FilePath);
                    errorSet.Errors.Add(new DataError(script.FilePath, message, sid));
                }
            }

            // check sentence ids in the script file
            foreach (string sid in script.Items.Keys)
            {
                if (!fileMap.Map.ContainsKey(sid))
                {
                    string message = string.Format(CultureInfo.InvariantCulture,
                        "Sentence [{0}] is found in the script [{1}], but not listed in filemap [{2}].",
                        sid, script.FilePath, fileMap.FilePath);
                    errorSet.Errors.Add(new DataError(script.FilePath, message, sid));
                }
            }

            return errorSet;
        }
コード例 #5
0
ファイル: VoiceFont.cs プロジェクト: JohnsonYuan/TTSFramework
        /// <summary>
        /// Check waveform files consistence between waveform and
        /// Referrence waveform files with the filemap.
        /// </summary>
        /// <param name="fileMap">File list map listed the sentences to validate.</param>
        /// <param name="waveDir">Base directory of waveform file.</param>
        /// <param name="refWaveDir">Directory of referrence waveform file.</param>
        /// <param name="refName">The name of the referrence waveform directory.</param>
        /// <returns>Data error set found.</returns>
        public static DataErrorSet ValidateWaveAlignment(FileListMap fileMap, string waveDir,
            string refWaveDir, string refName)
        {
            if (fileMap == null)
            {
                throw new ArgumentNullException("fileMap");
            }

            if (fileMap.Map == null)
            {
                throw new ArgumentException("fileMap.Map is null");
            }

            if (fileMap.Map.Keys == null)
            {
                throw new ArgumentException("fileMap.Map.Keys is null");
            }

            if (string.IsNullOrEmpty(refName))
            {
                throw new ArgumentNullException("refName");
            }

            if (string.IsNullOrEmpty(refWaveDir))
            {
                throw new ArgumentNullException("refWaveDir");
            }

            DataErrorSet errorSet = new DataErrorSet();

            foreach (string sid in fileMap.Map.Keys)
            {
                try
                {
                    string refFile = Path.Combine(refWaveDir, fileMap.Map[sid] + ".wav");
                    string waveFile = Path.Combine(waveDir, fileMap.Map[sid] + ".wav");

                    int waveSampleCount = 0;
                    int refSampleCount = 0;
                    WaveFormat waveFormat = new WaveFormat();
                    WaveFormat refWaveFormat = new WaveFormat();

                    StringBuilder sb = new StringBuilder();

                    // validate referrence file existance
                    if (!File.Exists(refFile))
                    {
                        sb.AppendFormat(CultureInfo.InvariantCulture,
                            "{0} file [{0}] does not exist.", refName, refFile);
                    }
                    else
                    {
                        refSampleCount = WaveFile.ReadSampleCount(refFile);
                        refWaveFormat = WaveFile.ReadFormat(refFile);
                    }

                    // validate waveform file existance
                    if (!File.Exists(waveFile))
                    {
                        sb.AppendFormat(CultureInfo.InvariantCulture,
                            "Wave file [{0}] does not exist.", waveFile);
                    }
                    else
                    {
                        waveSampleCount = WaveFile.ReadSampleCount(waveFile);
                        waveFormat = WaveFile.ReadFormat(waveFile);
                    }

                    // validate content consistence
                    if (waveSampleCount != 0 && refSampleCount != 0
                        && waveSampleCount != refSampleCount)
                    {
                        sb.AppendFormat(CultureInfo.InvariantCulture,
                            "The sample count is not the same between waveform file [{0}] and {1} file [{2}].",
                            waveFile, refName, refFile);
                    }

                    if (!waveFormat.Equals(refWaveFormat))
                    {
                        sb.AppendFormat(CultureInfo.InvariantCulture,
                            "The waveform format is not the same between waveform file [{0}] and {1} file [{2}].",
                            waveFile, refName, refFile);
                    }

                    if (sb.Length > 0)
                    {
                        errorSet.Errors.Add(new DataError(string.Empty, sb.ToString(), sid));
                    }
                }
                catch (InvalidDataException ide)
                {
                    string message = Helper.BuildExceptionMessage(ide);
                    errorSet.Errors.Add(new DataError(string.Empty, message, sid));
                }
            }

            return errorSet;
        }
コード例 #6
0
        /// <summary>
        /// Extracts features from the given script.
        /// </summary>
        /// <param name="script">
        /// The xml script file.
        /// </param>
        /// <param name="fileListMap">
        /// The file list map.
        /// </param>
        /// <param name="alignmentDir">
        /// The alignment directory.
        /// </param>
        /// <param name="waveDir">
        /// The wave directory.
        /// </param>
        /// <returns>
        /// The extracted features in training sentence set.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// Exception.
        /// </exception>
        public TrainingSentenceSet Extract(XmlScriptFile script, FileListMap fileListMap, string alignmentDir,
            string waveDir)
        {
            if (script == null)
            {
                throw new ArgumentNullException("script");
            }

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

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

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

            TrainingSentenceSet sentenceSet = new TrainingSentenceSet { FileListMap = fileListMap };
            List<string> errList = new List<string>();

            foreach (string sid in fileListMap.Map.Keys)
            {
                ScriptItem item = script.ItemDic[sid];

                try
                {
                    // Loads the segmentation file.
                    SegmentFile segmentFile = new SegmentFile();
                    segmentFile.Load(fileListMap.BuildPath(alignmentDir, sid, "txt"));

                    // Loads the waveform file to set the end time of the last segmentation.
                    WaveFile waveFile = new WaveFile();
                    waveFile.Load(fileListMap.BuildPath(waveDir, sid, FileExtensions.Waveform));
                    segmentFile.WaveSegments[segmentFile.WaveSegments.Count - 1].EndTime = waveFile.Duration;

                    // Extracts the single script item.
                    Sentence sentence = Extract(item, segmentFile);
                    sentence.TrainingSet = sentenceSet;
                    sentenceSet.Sentences.Add(sid, sentence);
                }
                catch (Exception e)
                {
                    if (!(e is InvalidDataException))
                    {
                        throw;
                    }

                    // Removes the error sentences.
                    Logger.Log(Helper.BuildExceptionMessage(e));
                    script.Remove(sid);
                    errList.Add(sid);
                }
            }

            fileListMap.RemoveItems(errList);
            return sentenceSet;
        }
コード例 #7
0
        /// <summary>
        /// Checks whether the data contains -sil- in within a word.
        /// </summary>
        /// <param name="script">Script file instance.</param>
        /// <param name="item">Script item.</param>
        /// <param name="fileMap">File list map.</param>
        /// <param name="segmentDir">Segment file directory.</param>
        /// <param name="errorSet">Data error set found.</param>
        public static void ValidateSilenceInWord(XmlScriptFile script, ScriptItem item,
            FileListMap fileMap, string segmentDir, ErrorSet errorSet)
        {
            string segmentFilePath = Path.Combine(segmentDir, fileMap.Map[item.Id] + ".txt");

            StringBuilder errorMessage = new StringBuilder();
            SegmentFile segmentFile = ValidateAlignmentFile(segmentFilePath, errorMessage);
            if (errorMessage.Length != 0)
            {
                errorSet.Add(ScriptError.OtherErrors, item.Id, errorMessage.ToString());
            }
            else
            {
                int indexOfSegment = 0;
                foreach (ScriptWord word in item.AllPronouncedNormalWords)
                {
                    ErrorSet errors = new ErrorSet();
                    Collection<string> phones = word.GetNormalPhoneNames(script.PhoneSet, errors);
                    if (errors.Count > 0)
                    {
                        errorSet.Merge(errors);
                        break;
                    }

                    if (segmentFile.WaveSegments[indexOfSegment].IsSilenceFeature)
                    {
                        ++indexOfSegment;
                    }

                    for (int i = 0; i < phones.Count; ++i, ++indexOfSegment)
                    {
                        if (segmentFile.WaveSegments[indexOfSegment].IsSilenceFeature)
                        {
                            errorSet.Add(ScriptError.OtherErrors,
                                item.Id,
                                Helper.NeutralFormat("Alignment file {0} is invalid, for silence in word {1}.", segmentFilePath, word.Grapheme));
                            ++indexOfSegment;
                        }

                        if (segmentFile.WaveSegments[indexOfSegment].Label != phones[i])
                        {
                            string message = string.Format(CultureInfo.InvariantCulture,
                                "phone [{0}/{1}] at {2} does not match between script and segment.",
                                WaveSegment.FormatLabel(phones[i]),
                                segmentFile.WaveSegments[indexOfSegment].Label,
                                i);
                            errorSet.Add(ScriptError.OtherErrors, item.Id, message);
                        }
                    }
                }
            }
        }
コード例 #8
0
        /// <summary>
        /// Check the file map is invalid or not.
        /// </summary>
        /// <param name="filePath">The file path.</param>
        /// <returns>Bool.</returns>
        public static bool IsValidFileListMap(string filePath)
        {
            bool isValidFileListMap = true;
            FileListMap fileListMap = new FileListMap();
            if (string.IsNullOrEmpty(filePath))
            {
                isValidFileListMap = false;
            }
            else
            {
                try
                {
                    fileListMap.Load(filePath);
                }
                catch
                {
                    isValidFileListMap = false;
                }
            }

            return isValidFileListMap;
        }
コード例 #9
0
        /// <summary>
        /// Build file path according to the given information.
        /// </summary>
        /// <param name="map">The given map. If it is null, the sentence id will be used directly.</param>
        /// <param name="folder">The given folder.</param>
        /// <param name="sid">Sentence id.</param>
        /// <param name="extension">Extension name.</param>
        /// <returns>File path.</returns>
        public static string BuildPath(FileListMap map, string folder, string sid, string extension)
        {
            if (string.IsNullOrEmpty(folder))
            {
                throw new ArgumentNullException("folder");
            }

            if (string.IsNullOrEmpty(sid))
            {
                throw new ArgumentNullException("sid");
            }

            // Here, extension can be null or emtpy.
            return map == null
                ? Path.Combine(folder, sid.AppendExtensionName(extension))
                : Path.Combine(folder, map.Map[sid].AppendExtensionName(extension));
        }
コード例 #10
0
 /// <summary>
 /// Build file list instance from given file directory,
 /// The value in the dictionary would be sorted by the key.
 /// </summary>
 /// <param name="items">Directory to search, in 2 levels.</param>
 /// <returns>FileListMap.</returns>
 public static FileListMap CreateInstance(Dictionary<string, string> items)
 {
     FileListMap fileList = new FileListMap();
     fileList._map = items;
     return fileList;
 }
コード例 #11
0
        /// <summary>
        /// Build file list instance from given file directory,
        /// The value in the dictionary would be sorted by the key.
        /// </summary>
        /// <param name="targetDir">Directory to search, in 2 levels.</param>
        /// <param name="fileExt">Such as ".wav" or ".txt".</param>
        /// <returns>FileListMap.</returns>
        public static FileListMap CreateInstance(string targetDir,
            string fileExt)
        {
            FileListMap fileList = new FileListMap();
            fileList._map = Build(targetDir, fileExt);

            return fileList;
        }
コード例 #12
0
        /// <summary>
        /// Checks whether the data contains -sil- in within a word.
        /// </summary>
        /// <param name="fileMap">File list map.</param>
        /// <param name="script">Script file instance.</param>
        /// <param name="segmentDir">Segment file directory.</param>
        /// <returns>Data error set found.</returns>
        public static ErrorSet ValidateSilenceInWord(FileListMap fileMap, XmlScriptFile script, string segmentDir)
        {
            // Parameters validation
            if (string.IsNullOrEmpty(segmentDir))
            {
                throw new ArgumentNullException("segmentDir");
            }

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

            if (fileMap.Map == null)
            {
                throw new ArgumentException("fileMap.Map is null");
            }

            if (fileMap.Map.Keys == null)
            {
                throw new ArgumentException("fileMap.Map.Keys is null");
            }

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

            ErrorSet errorSet = new ErrorSet();

            foreach (ScriptItem item in script.Items)
            {
                try
                {
                    if (!fileMap.Map.ContainsKey(item.Id))
                    {
                        errorSet.Add(ScriptError.OtherErrors, item.Id, "File list map does not contain item");
                        continue;
                    }

                    ValidateSilenceInWord(script, item, fileMap, segmentDir, errorSet);
                }
                catch (InvalidDataException ide)
                {
                    errorSet.Add(ScriptError.OtherErrors, item.Id, Helper.BuildExceptionMessage(ide));
                }
            }

            foreach (string sid in fileMap.Map.Keys)
            {
                if (!script.ItemDic.ContainsKey(sid))
                {
                    errorSet.Add(ScriptError.OtherErrors, sid, "script file does not contain item");
                }
            }

            return errorSet;
        }
コード例 #13
0
        /// <summary>
        /// Check data file consistence between segment, epoch and wave16k files with the filemap.
        /// </summary>
        /// <param name="fileMap">File list map.</param>
        /// <param name="wave16kDir">16k Hz waveform file directory.</param>
        /// <param name="epochDir">Epoch file directory.</param>
        /// <param name="segmentDir">Segmentation file directory.</param>
        /// <returns>Data error set found.</returns>
        public static ErrorSet ValidateDataAlignment(
            FileListMap fileMap, string wave16kDir, string epochDir, string segmentDir)
        {
            // Parameter validation
            if (fileMap == null)
            {
                throw new ArgumentNullException("fileMap");
            }

            if (fileMap.Map == null)
            {
                throw new ArgumentException("fileMap.Map is null");
            }

            if (fileMap.Map.Keys == null)
            {
                throw new ArgumentException("fileMap.Map.Keys is null");
            }

            ErrorSet errorSet = new ErrorSet();

            // go throught the file list map for each sentence
            foreach (string sid in fileMap.Map.Keys)
            {
                try
                {
                    string alignmentFile = Path.Combine(segmentDir, fileMap.Map[sid] + ".txt");
                    string epochFile = Path.Combine(epochDir, fileMap.Map[sid] + ".epoch");
                    string wave16kFile = Path.Combine(wave16kDir, fileMap.Map[sid] + ".wav");

                    StringBuilder error = new StringBuilder();

                    StringBuilder warning = ValidateDataAlignment(alignmentFile, epochFile, wave16kFile, error);
                    if (error.Length > 0)
                    {
                        errorSet.Add(ScriptError.OtherErrors, sid, error.ToString());
                    }
                }
                catch (InvalidDataException ide)
                {
                    string message = Helper.BuildExceptionMessage(ide);
                    errorSet.Add(ScriptError.OtherErrors, sid, message);
                }
            }

            return errorSet;
        }
コード例 #14
0
        /// <summary>
        /// Check data consistence between script item and segmentation file.
        /// </summary>
        /// <param name="item">Script item.</param>
        /// <param name="phoneme">Phoneme used to get units.</param>
        /// <param name="sliceData">Slice data used to get units.</param>
        /// <param name="fileMap">File list map.</param>
        /// <param name="segmentDir">Segment file directory.</param>
        /// <param name="errorSet">Data error set found.</param>
        public static void ValidateDataAlignment(ScriptItem item,
            Phoneme phoneme, SliceData sliceData, FileListMap fileMap, string segmentDir, ErrorSet errorSet)
        {
            string segmentFilePath = Path.Combine(segmentDir, fileMap.Map[item.Id] + ".txt");

            StringBuilder errorMessage = new StringBuilder();
            SegmentFile segmentFile = ValidateAlignmentFile(segmentFilePath, errorMessage);
            if (errorMessage.Length != 0)
            {
                errorSet.Add(ScriptError.OtherErrors, item.Id, errorMessage.ToString());
            }
            else
            {
                Collection<TtsUnit> units = item.GetUnits(phoneme, sliceData);

                if (segmentFile.WaveSegments.Count == 0)
                {
                    string message = Helper.NeutralFormat(
                        "There is no valid alignment data in alignment file {0}.", segmentFilePath);
                    errorSet.Add(ScriptError.OtherErrors, item.Id, message);
                }
                else if (!segmentFile.WaveSegments[segmentFile.WaveSegments.Count - 1].IsSilenceFeature)
                {
                    string message = Helper.NeutralFormat(
                        "Alignment file {0} is invalid, for without silence segment at the end.", segmentFilePath);
                    errorSet.Add(ScriptError.OtherErrors, item.Id, message);
                }
                else if (units.Count != segmentFile.NonSilenceWaveSegments.Count)
                {
                    string message = Helper.NeutralFormat(
                        "script units {0} do not match with non-silence " +
                            "segments {1} in segmentation file.",
                        units.Count,
                        segmentFile.NonSilenceWaveSegments.Count);
                    errorSet.Add(ScriptError.OtherErrors, item.Id, message);
                }
                else
                {
                    // go through each segments
                    for (int i = 0; i < segmentFile.NonSilenceWaveSegments.Count; i++)
                    {
                        WaveSegment segment = segmentFile.NonSilenceWaveSegments[i];
                        TtsUnit unit = units[i];

                        if (segment.Label != WaveSegment.FormatLabel(unit.MetaUnit.Name))
                        {
                            string message = Helper.NeutralFormat(
                                "units [{0}/{1}] at {2} do not match between script and segment.",
                                WaveSegment.FormatLabel(unit.MetaUnit.Name),
                                segment.Label,
                                i);
                            errorSet.Add(ScriptError.OtherErrors, item.Id, message);
                        }
                    }
                }
            }
        }
コード例 #15
0
ファイル: VoiceFont.cs プロジェクト: JohnsonYuan/TTSFramework
        /// <summary>
        /// Check data consistence between script item and segmentation file.
        /// </summary>
        /// <param name="script">Script file instance.</param>
        /// <param name="item">Script item.</param>
        /// <param name="fileMap">File list map.</param>
        /// <param name="segmentDir">Segment file directory.</param>
        /// <param name="errorSet">Data error set found.</param>
        /// <param name="phoneBasedSegment">Phone based alignment or unit based alignment.</param>
        public static void ValidateDataAlignment(ScriptFile script, ScriptItem item,
            FileListMap fileMap, string segmentDir, DataErrorSet errorSet, bool phoneBasedSegment)
        {
            string segmentFilePath = Path.Combine(segmentDir, fileMap.Map[item.Id] + ".txt");

            SegmentFile segmentFile = new SegmentFile();
            segmentFile.Load(segmentFilePath);

            if (segmentFile.WaveSegments.Count == 0)
            {
                string message = string.Format(CultureInfo.InvariantCulture,
                    "There is no valid alignment data into alignment file.");
                errorSet.Errors.Add(new DataError(segmentFilePath, message, item.Id));
            }
            else if (!segmentFile.WaveSegments[segmentFile.WaveSegments.Count - 1].IsSilencePhone)
            {
                string message = string.Format(CultureInfo.InvariantCulture,
                    "The alignment file is invalid, for without silence segment at the end.");
                errorSet.Errors.Add(new DataError(segmentFilePath, message, item.Id));
            }
            else if (!phoneBasedSegment && item.Units.Count != segmentFile.NonSilenceWaveSegments.Count)
            {
                string message = string.Format(CultureInfo.InvariantCulture,
                    "script units {0} do not match with non-silence segments {1} in segmentation file.",
                    item.Units.Count, segmentFile.NonSilenceWaveSegments.Count);
                errorSet.Errors.Add(new DataError(script.FilePath, message, item.Id));
            }
            else if (phoneBasedSegment && item.GetPhones().Length != segmentFile.NonSilenceWaveSegments.Count)
            {
                string message = string.Format(CultureInfo.InvariantCulture,
                    "script phones {0} do not match with non-silence segments {1} in segmentation file.",
                    item.GetPhones().Length, segmentFile.NonSilenceWaveSegments.Count);
                errorSet.Errors.Add(new DataError(script.FilePath, message, item.Id));
            } 
            else
            {
                // go through each segments
                if (phoneBasedSegment)
                {
                    string[] phones = item.GetPhones();
                    for (int i = 0; i < segmentFile.NonSilenceWaveSegments.Count; i++)
                    {
                        WaveSegment segment = segmentFile.NonSilenceWaveSegments[i];
                        
                        if (segment.Label != phones[i])
                        {
                            string message = string.Format(CultureInfo.InvariantCulture,
                                "phone [{0}/{1}] at {2} does not match between script and segment.",
                                WaveSegment.FormatLabel(phones[i]), segment.Label, i);
                            errorSet.Errors.Add(new DataError(script.FilePath, message, item.Id));
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < segmentFile.NonSilenceWaveSegments.Count; i++)
                    {
                        WaveSegment segment = segmentFile.NonSilenceWaveSegments[i];
                        TtsUnit unit = item.Units[i];

                        if (segment.Label != WaveSegment.FormatLabel(unit.MetaUnit.Name))
                        {
                            string message = string.Format(CultureInfo.InvariantCulture,
                                "units [{0}/{1}] at {2} do not match between script and segment.",
                                WaveSegment.FormatLabel(unit.MetaUnit.Name), segment.Label, i);
                            errorSet.Errors.Add(new DataError(script.FilePath, message, item.Id));
                        }
                    }
                }
            }
        }
コード例 #16
0
ファイル: VoiceFont.cs プロジェクト: JohnsonYuan/TTSFramework
        public void ParseConfig(XmlElement config)
        {
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            Debug.Assert(!string.IsNullOrEmpty(config.GetAttribute("language")));
            Debug.Assert(!string.IsNullOrEmpty(config.GetAttribute("engine")));
            _primaryLanguage = Localor.StringToLanguage(
                                            config.GetAttribute("language"));
            _engineType = (EngineType)Enum.Parse(typeof(EngineType),
                                            config.GetAttribute("engine"));

            XmlElement eleLangData = config.SelectSingleNode("languageData") as XmlElement;
            VoiceCreationLanguageData languageData = new VoiceCreationLanguageData();
            if (eleLangData != null)
            {
                languageData.ParseLanguageDataFromXmlElement(true, eleLangData);
                languageData.SetLanguageData(_primaryLanguage);
            }
            else
            {
                languageData.CartQuestions = config.SelectSingleNode("question/@path").InnerText;
            }

            _voiceName = config.GetAttribute("voiceName");
            _tokenId = config.GetAttribute("tokenId");

            _fontPath = config.SelectSingleNode("font/@path").InnerText;

            ScriptFile = Localor.CreateScriptFile(_primaryLanguage, _engineType);
            ScriptFile.Load(config.SelectSingleNode("script/@path").InnerText);

            FileMap = new FileListMap();
            FileMap.Load(config.SelectSingleNode("filemap/@path").InnerText);

            _weightTable = new WeightTable(_primaryLanguage, _engineType);
            _weightTable.Load(config.SelectSingleNode("weighttable/@path").InnerText);

            _cartTreeManager = new CartTreeManager();
            _cartTreeManager.CartTreeDir = config.SelectSingleNode("treedir/@path").InnerText;
            if (!Directory.Exists(_cartTreeManager.CartTreeDir))
            {
                string message = string.Format(CultureInfo.InvariantCulture,
                    "The treeDir path does not exist at [{0}]",
                    _cartTreeManager.CartTreeDir);
                throw new DirectoryNotFoundException(message);
            }

            _cartTreeManager.CartQuestionFile = languageData.CartQuestions;
            if (!File.Exists(_cartTreeManager.CartQuestionFile))
            {
                string message = string.Format(CultureInfo.InvariantCulture,
                    "The tree question file path does not exist at [{0}]",
                    _cartTreeManager.CartQuestionFile);
                throw new DirectoryNotFoundException(message);
            }

            _cartTreeManager.UnitDescriptFile = config.SelectSingleNode("unitdescript/@path").InnerText;
            if (!File.Exists(_cartTreeManager.UnitDescriptFile))
            {
                string message = string.Format(CultureInfo.InvariantCulture,
                    "The unit description file path does not exist at [{0}]",
                    _cartTreeManager.UnitDescriptFile);
                throw new DirectoryNotFoundException(message);
            }

            _unitFeatureFilePath = config.SelectSingleNode("wavesequence/@path").InnerText;
            if (!File.Exists(_unitFeatureFilePath))
            {
                string message = string.Format(CultureInfo.InvariantCulture,
                    "The wave sequence file path does not exist at [{0}]",
                    _unitFeatureFilePath);
                throw new DirectoryNotFoundException(message);
            }

            _wave16kDirectories.Clear();
            foreach (XmlNode dirNode in config.SelectNodes("wave16k/@path"))
            {
                string waveDir = dirNode.InnerText.Trim();
                if (!Directory.Exists(waveDir))
                {
                    string message = string.Format(CultureInfo.InvariantCulture,
                        "The wave16k path does not exist at [{0}]",
                        waveDir);
                    throw new DirectoryNotFoundException(message);
                }

                _wave16kDirectories.Add(waveDir);
            }

            _segmentDirectories.Clear();
            foreach (XmlNode dirNode in config.SelectNodes("segment/@path"))
            {
                string alignmentDir = dirNode.InnerText.Trim();
                if (!Directory.Exists(alignmentDir))
                {
                    string message = string.Format(CultureInfo.InvariantCulture,
                        "The alignment path does not exist at [{0}]",
                        alignmentDir);
                    throw new DirectoryNotFoundException(message);
                }

                _segmentDirectories.Add(alignmentDir);
            }
        }
コード例 #17
0
        /// <summary>
        /// Initializes a new instance of the <see cref="F0ExtractorCOSMOS" /> class.
        /// </summary>
        /// <param name="fileMap">File list map.</param>
        /// <param name="waveDir">Input wave directory.</param>
        /// <param name="workDir">Output data direcotry.</param>
        /// <param name="getF0Tool">The path of get_f0.exe file.</param>
        /// <param name="getF0Config">The path of get_f0.config file.</param>
        /// <param name="straightTool">The path of straight_all.exe file.</param>
        /// <param name="svmScaleTool">The path of svm-scale.exe file.</param>
        /// <param name="svmPredictTool">The path of svm-predit.exe file.</param>
        /// <param name="modelFilePath">Svm model file path.</param>
        /// <param name="minF0">The min f0 value.</param>
        /// <param name="maxF0">The max f0 value.</param>
        /// <param name="secondsPerFrame">The length of one frame in seconds.</param>
        /// <param name="samplesPerSecond">The sample number in one second.</param>
        /// <param name="dimension">Uv feature dimension.</param>
        /// <param name="frameBias">Frame bias of f0.</param>
        /// <param name="logger">The logger.</param>
        /// <param name="enableCosmos">Enable cosmos.</param>
        /// <param name="cosmosPath">Cosmos path.</param>
        /// <param name="fileSS">The structured stream file.</param>
        /// <exception cref="DirectoryNotFoundException">Exception.</exception>
        /// <exception cref="FileNotFoundException">Exception.</exception>
        /// <exception cref="ArgumentNullException">Exception.</exception>
        /// <exception cref="ArgumentException">Exception</exception>
        public F0ExtractorCOSMOS(string fileMap, string waveDir, string workDir, string getF0Tool, string getF0Config, string straightTool, string svmScaleTool, string svmPredictTool, string modelFilePath,
            float minF0, float maxF0, float secondsPerFrame, int samplesPerSecond, int dimension, int frameBias, ILogger logger,
            bool enableCosmos = false, string cosmosPath = " ", string fileSS = " ")
        {
            // check input arguments
            Helper.ThrowIfDirectoryNotExist(waveDir);
            Helper.ThrowIfFileNotExist(modelFilePath);

            // check dimensions
            if (dimension != BasicDimension && dimension != ExpandDimension && dimension != DeltaDimension)
            {
                throw new ArgumentException("Invalid dimension value, it should be 6/18/54");
            }

            // check f0 range
            if (minF0 > maxF0 || minF0 < 0)
            {
                throw new ArgumentException("Invalid F0 range.");
            }

            // check seconds per frame
            if (secondsPerFrame <= Minimum)
            {
                throw new ArgumentException("Invalid seconds of per frame.");
            }

            // check sample rate 
            if (samplesPerSecond <= Minimum)
            {
                throw new ArgumentException("Invalid sample rate.");
            }

            // check frame bias 
            if (frameBias < -10 || frameBias > 10)
            {
                throw new ArgumentException("Frame bias of f0 should be in the range [-10, 10].");
            }

            // assign values to fields
            WorkDir = workDir;
            Helper.EnsureFolderExist(workDir);
            WaveDir = waveDir;
            ModelFilePath = modelFilePath;
            Dimension = dimension;
            MinF0Value = minF0;
            MaxF0Value = maxF0;
            SecondsPerFrame = secondsPerFrame;
            FrameShift = (int)Math.Ceiling(samplesPerSecond * secondsPerFrame);
            FrameLength = FrameShift * 2;
            FrameBias = frameBias;

            // check logger
            Logger = (logger == null) ? new NullLogger() : logger;

            // get file list
            if (string.IsNullOrWhiteSpace(fileMap) || !File.Exists(fileMap))
            {
                FileMap = FileListMap.CreateInstance(waveDir, string.Empty.AppendExtensionName(FileExtensions.Waveform.ToLowerInvariant()));
            }
            else
            {
                FileMap = new FileListMap();
                FileMap.Load(fileMap);
            }

            if (FileMap.Map.Count == 0)
            {
                throw new ArgumentException("Empty wave folder!");
            }

            EnableCosmos = enableCosmos;
            CosmosPath = cosmosPath;
            FileSS = fileSS;

            // make intermediate directories
            IntermediateDir = Path.Combine(workDir, "Intermediate");
            GetF0Tool = getF0Tool;
            Helper.ThrowIfFileNotExist(GetF0Tool);
            GetF0Config = getF0Config;
            Helper.ThrowIfFileNotExist(GetF0Config);
            StraightTool = straightTool;
            Helper.ThrowIfFileNotExist(StraightTool);
            SvmScaleTool = svmScaleTool;
            Helper.ThrowIfFileNotExist(SvmScaleTool);
            SvmPredictTool = svmPredictTool;
            Helper.ThrowIfFileNotExist(SvmPredictTool);
            F0NccfDir = Path.Combine(IntermediateDir, "get_f0");
            Helper.EnsureFolderExist(F0NccfDir);
            RealtedFeaDir = Path.Combine(IntermediateDir, "relatedFeatures");
            Helper.EnsureFolderExist(RealtedFeaDir);
            NccfDir = Path.Combine(IntermediateDir, "nccf");
            Helper.EnsureFolderExist(NccfDir);
            LPCDir = Path.Combine(IntermediateDir, "lpc");
            Helper.EnsureFolderExist(LPCDir);
            ResidualDir = Path.Combine(IntermediateDir, "residual");
            Helper.EnsureFolderExist(ResidualDir);
            F0Dir = Path.Combine(IntermediateDir, "if0");
            Helper.EnsureFolderExist(F0Dir);
            MergedFeaDir = Path.Combine(IntermediateDir, "mergedFea");
            Helper.EnsureFolderExist(MergedFeaDir);
            ExpandFeaDir = Path.Combine(IntermediateDir, "expandedFea");
            Helper.EnsureFolderExist(ExpandFeaDir);
            SvmFeaDir = Path.Combine(IntermediateDir, "formatFea");
            Helper.EnsureFolderExist(SvmFeaDir);
            ScaledSvmFeaDir = Path.Combine(IntermediateDir, "scaledFea");
            Helper.EnsureFolderExist(ScaledSvmFeaDir);
            UVDir = Path.Combine(IntermediateDir, "uv");
            Helper.EnsureFolderExist(UVDir);
            SmoothedF0Dir = Path.Combine(WorkDir, "sf0");
            Helper.EnsureFolderExist(SmoothedF0Dir);
        }
コード例 #18
0
ファイル: VoiceFont.cs プロジェクト: JohnsonYuan/TTSFramework
        /// <summary>
        /// Extract acoustic features for a given sentence.
        /// </summary>
        /// <param name="writer">Stream writer to write acoustic features.</param>
        /// <param name="script">Script file instance.</param>
        /// <param name="sid">Sentence id.</param>
        /// <param name="fileMap">File list map.</param>
        /// <param name="segmentDir">Segmentation file directory.</param>
        /// <param name="wave16kDir">16k Hz waveform file directory.</param>
        /// <param name="epochDir">Epoch file directory.</param>
        private static void ExtractAcoustic(StreamWriter writer, ScriptFile script, string sid,
            FileListMap fileMap, string segmentDir, string wave16kDir, string epochDir)
        {
            ScriptItem scriptItem = script.Items[sid];

            // find the absolute file paths for each kind data file 
            string wave16kFilePath = Path.Combine(wave16kDir, fileMap.Map[scriptItem.Id] + ".wav");
            string epochFilePath = Path.Combine(epochDir, fileMap.Map[scriptItem.Id] + ".epoch");
            string segmentFilePath = Path.Combine(segmentDir, fileMap.Map[scriptItem.Id] + ".txt");

            // load data files
            SegmentFile segFile = new SegmentFile();
            segFile.Load(segmentFilePath);

            EggAcousticFeature eggFile = new EggAcousticFeature();
            eggFile.LoadEpoch(epochFilePath);

            WaveAcousticFeature waveFile = new WaveAcousticFeature();
            waveFile.Load(wave16kFilePath);

            // calculate acoustic features for each segments in the files
            int totalCount = segFile.NonSilenceWaveSegments.Count;
            if (scriptItem.Units.Count != totalCount)
            {
                string str1 = "Unit number mis-matched between sentence [{0}] in ";
                string str2 = "script file [{1}] and in the alignment file [{2}]. ";
                string str3 = "There are {3} units in script but {4} units in alignment.";
                string message = string.Format(CultureInfo.InvariantCulture,
                    str1 + str2 + str3,
                    sid, script.FilePath, segmentFilePath,
                    scriptItem.Units.Count, totalCount);
                throw new InvalidDataException(message);
            }

            for (int i = 0; i < totalCount; i++)
            {
                // for each wave segment
                WaveSegment ws = segFile.NonSilenceWaveSegments[i];

                // get unit sample scope
                int sampleOffset = (int)(ws.StartTime * waveFile.SamplesPerSecond);
                int sampleLength = (int)(ws.Duration * waveFile.SamplesPerSecond);
                int sampleEnd = sampleOffset + sampleLength;

                int epochOffset = 0;
                int epochEnd = 0;

                // calculate average pitch, pitch average
                float averagePitch, pitchRange;
                eggFile.GetPitchAndRange(sampleOffset,
                    sampleLength, out averagePitch, out pitchRange);
                ws.AveragePitch = averagePitch;
                ws.PitchRange = pitchRange;

                // calculate root mean square, and before that ajust the segment alignment with
                // the epoch data
                epochOffset = eggFile.AdjustAlignment(ref sampleOffset);
                epochEnd = eggFile.AdjustAlignment(ref sampleEnd);

                if (epochOffset > epochEnd)
                {
                    string info = string.Format(CultureInfo.InvariantCulture,
                        "epochOffset[{0}] should not be bigger than epochEnd[{1}]",
                        epochOffset, epochEnd);
                    throw new InvalidDataException(info);
                }

                if (sampleEnd > waveFile.SampleNumber)
                {
                    string str1 = "Mis-match found between alignment file [{0}] and waveform file [{1}], ";
                    string str2 = "for the end sample of alignment is [{2}] but";
                    string str3 = " the total sample number of waveform file is [{3}].";
                    string info = string.Format(CultureInfo.InvariantCulture,
                        str1 + str2 + str3,
                        segmentFilePath, wave16kFilePath,
                        epochEnd, waveFile.SampleNumber);

                    throw new InvalidDataException(info);
                }

                ws.RootMeanSquare = waveFile.CalculateRms(sampleOffset, sampleEnd - sampleOffset);

                // calculate epoch
                int epoch16KCompressLength = EpochFile.CompressEpoch(eggFile.Epoch,
                    epochOffset, epochEnd - epochOffset, null);
                int epoch8KCompressLength = EpochFile.CompressEpoch(eggFile.Epoch8k,
                    epochOffset, epochEnd - epochOffset, null);

                // leave (epoch offset in sentence) (epoch length)
                // (16k compressed epoch lenght) (8k compressed epoch lenght) as zero
                string message = string.Format(CultureInfo.InvariantCulture,
                    "{0,12} {1,3} {2,9:0.000000} {3,9:0.000000} {4,7} {5,5} {6,4} {7,3} {8,3} {9,3} {10,7:0.0} {11,5:0.0} {12,4:0.0} {13}",
                    scriptItem.Id, i,
                    ws.StartTime, ws.Duration, sampleOffset, sampleEnd - sampleOffset,
                    epochOffset, epochEnd - epochOffset,
                    epoch16KCompressLength, epoch8KCompressLength,
                    ws.RootMeanSquare, ws.AveragePitch, ws.PitchRange,
                    scriptItem.Units[i].FullName);

                writer.WriteLine(message);
            }
        }
コード例 #19
0
        /// <summary>
        /// Extract epoch data from EGG files.
        /// </summary>
        /// <param name="mapFile">Map file list.</param>
        /// <param name="wave16kDir">16k Hz waveform directory.</param>
        /// <param name="egg16kDir">16k Hz EGG directory.</param>
        /// <param name="epochDir">Epoch directory.</param>
        /// <param name="skipExist">Falg to indicate whether skipping existing target file.</param>
        public static void EggToEpoch(string mapFile, string wave16kDir,
            string egg16kDir, string epochDir, bool skipExist)
        {
            // Const parameter used to generate epoch from wave16k and egg16k file.
            const double FilterLowFreq = 60.0;
            const double FilterHighFreq = 3600.0;
            const int BandPassOrder = 1000;
            const int LarEpochMinPitch = 110;
            const int LarEpochMaxPitch = 500;
            const int FrameSize = checked((int)(0.025f * 16000));
            const int LpcOrder = 20;
            const int AdjustFreqOffset = 10;

            // Validate file/dir parameter
            if (!File.Exists(mapFile))
            {
                throw Helper.CreateException(typeof(FileNotFoundException),
                    mapFile);
            }

            if (!Directory.Exists(wave16kDir))
            {
                throw Helper.CreateException(typeof(DirectoryNotFoundException),
                    wave16kDir);
            }

            if (!Directory.Exists(egg16kDir))
            {
                throw Helper.CreateException(typeof(DirectoryNotFoundException),
                    egg16kDir);
            }

            if (string.IsNullOrEmpty(epochDir))
            {
                throw new ArgumentNullException("epochDir");
            }

            FileListMap fileMap = new FileListMap();
            fileMap.Load(mapFile);

            ConsoleLogger logger = new ConsoleLogger();

            // Validate the consistence between the EGG and waveform files
            DataErrorSet errorSet = VoiceFont.ValidateWaveAlignment(fileMap, wave16kDir,
                egg16kDir, "EGG");
            if (errorSet.Errors.Count > 0)
            {
                foreach (DataError error in errorSet.Errors)
                {
                    logger.LogLine(error.ToString());

                    if (fileMap.Map.ContainsKey(error.SentenceId))
                    {
                        fileMap.Map.Remove(error.SentenceId);
                    }
                }
            }

            // Performance converting
            Helper.EnsureFolderExist(epochDir);
            foreach (string sid in fileMap.Map.Keys)
            {
                string wave16kFile = Path.Combine(wave16kDir,
                    fileMap.Map[sid] + ".wav");
                string egg16kFile = Path.Combine(egg16kDir,
                    fileMap.Map[sid] + ".wav");
                string epochFile = Path.Combine(epochDir,
                    fileMap.Map[sid] + ".epoch");

                if (!File.Exists(wave16kFile) || !File.Exists(egg16kFile))
                {
                    if (!File.Exists(wave16kFile))
                    {
                        logger.LogLine("Can't find file : {0}", wave16kFile);
                    }
                    else if (!File.Exists(egg16kFile))
                    {
                        logger.LogLine("Can't find file : {0}", egg16kFile);
                    }

                    continue;
                }

                Helper.EnsureFolderExistForFile(epochFile);

                // Performance EGG to Epoch conversion while
                // 1. not skipping the existing epoch file is asked
                // 2. Or the target epoch file does not exist
                // 3. Or the target epoch file is with zero length
                if (!skipExist ||
                    !File.Exists(epochFile) ||
                    new FileInfo(epochFile).Length == 0)
                {
                    EggAcousticFeature.Egg2Epoch(wave16kFile, egg16kFile,
                        epochFile, FilterLowFreq, FilterHighFreq, BandPassOrder,
                        LarEpochMinPitch, LarEpochMaxPitch, FrameSize, LpcOrder,
                        AdjustFreqOffset);
                }
            }
        }
コード例 #20
0
        /// <summary>
        /// Check phone based data consistence between script item and segmentation file.
        /// </summary>
        /// <param name="script">Script file instance.</param>
        /// <param name="item">Script item.</param>
        /// <param name="fileMap">File list map.</param>
        /// <param name="segmentDir">Segment file directory.</param>
        /// <param name="errorSet">Data error set found.</param>
        public static void ValidateDataAlignment(XmlScriptFile script, ScriptItem item,
            FileListMap fileMap, string segmentDir, ErrorSet errorSet)
        {
            string segmentFilePath = Path.Combine(segmentDir, fileMap.Map[item.Id] + ".txt");

            StringBuilder errorMessage = new StringBuilder();
            SegmentFile segmentFile = ValidateAlignmentFile(segmentFilePath, errorMessage);
            if (errorMessage.Length != 0)
            {
                errorSet.Add(ScriptError.OtherErrors, item.Id, errorMessage.ToString());
            }
            else
            {
                ErrorSet errors = new ErrorSet();
                Collection<string> phones = item.GetNormalPhoneNames(script.PhoneSet, errors);
                errorSet.Merge(errors);

                if (segmentFile.WaveSegments.Count == 0)
                {
                    string message = Helper.NeutralFormat(
                        "There is no valid alignment data in alignment file {0}.", segmentFilePath);
                    errorSet.Add(ScriptError.OtherErrors, item.Id, message);
                }
                else if (!segmentFile.WaveSegments[segmentFile.WaveSegments.Count - 1].IsSilencePhone)
                {
                    string message = Helper.NeutralFormat(
                        "Alignment file {0} is invalid, for without silence segment at the end.", segmentFilePath);
                    errorSet.Add(ScriptError.OtherErrors, item.Id, message);
                }
                else if (phones.Count != segmentFile.NonSilenceWaveSegments.Count)
                {
                    string message = Helper.NeutralFormat(
                        "units number {0} in script file does not equal to non-silence " +
                            "segments number {1} in segmentation file.",
                        phones.Count,
                        segmentFile.NonSilenceWaveSegments.Count);
                    errorSet.Add(ScriptError.OtherErrors, item.Id, message);
                }
                else
                {
                    // go through each segments
                    for (int i = 0; i < segmentFile.NonSilenceWaveSegments.Count; i++)
                    {
                        WaveSegment segment = segmentFile.NonSilenceWaveSegments[i];

                        if (segment.Label != phones[i])
                        {
                            string message = string.Format(CultureInfo.InvariantCulture,
                                "phone [{0}/{1}] at {2} does not match between script and segment.",
                                WaveSegment.FormatLabel(phones[i]),
                                segment.Label,
                                i);
                            errorSet.Add(ScriptError.OtherErrors, item.Id, message);
                        }
                    }
                }
            }
        }