/// <summary>
        /// Start the pruning.
        /// </summary>
        /// <param name="fontPath">Voice font path, like .\1033 .</param>
        /// <param name="configFile">Config file which will tell how many sentence will be include in each sub wve.</param>
        /// <param name="bFillData">Whether fill data if the sub WVE can't be exact division.</param>
        /// <param name="outputFolder">Target directory.</param>
        /// <returns>New WVE File path List.</returns>
        public static List<string> InventorySplit(string fontPath, string configFile, bool bFillData, string outputFolder)
        {
            string unitfile = fontPath + ".unt";
            string wihFile = fontPath + ".wih";
            string wveFile = fontPath + ".wve";
            string outputUnit = Path.Combine(outputFolder, Path.GetFileNameWithoutExtension(unitfile) + ".Splited.unt");

            PrintLog("Start to update split the WVE file...", true);

            // spliet the file.
            List<string> newWVEFileList = new List<string>();

            // Load the WIH file.
            WaveInfoHeader header = new WaveInfoHeader();
            header.Load(wihFile);
            const uint CompressFrameSize = 640;

            Dictionary<string, uint> untFrameUpdateList = new Dictionary<string, uint>();
            Dictionary<string, uint> acdFrameUpdateList = new Dictionary<string, uint>();
            uint curFillFrameCount = 0;
            Dictionary<string, int> namedUnitTypeId = new Dictionary<string, int>();
            Dictionary<int, WaveCandidateInfo> updatedCandidates = new Dictionary<int, WaveCandidateInfo>();
            using (UnitIndexingFile indexFile = new UnitIndexingFile(namedUnitTypeId))
            {
                indexFile.Load(unitfile);

                uint bytesPerFrame = indexFile.SamplePerFrame * header.BytesPerSample;
                uint compressFrameCount = CompressFrameSize / bytesPerFrame;

                // Get all sentence id information from the index file canidate, and save them in a sorted dictionary.
                // Because the sentece is sorted by a sorted dictionary in Font traing process.
                List<string> sentencIDs = indexFile.WaveCandidates.SelectMany(c => c.Value.Select(k => k.Value.SentenceId).Distinct()).Distinct().ToList();
                Dictionary<string, int> dic = sentencIDs.Select((v, i) => new { Value = v, Index = i }).ToDictionary(p => p.Value, p => p.Index);
                SortedDictionary<string, int> sortedSentenceDic = new SortedDictionary<string, int>(dic);
                List<string> orderedSentenceIDs = sortedSentenceDic.Select(e => e.Key).ToList();

                // Get the confing data.
                List<uint> sentencCountList = ReadConfigFile(configFile, (uint)orderedSentenceIDs.Count);

                using (FileStream readerStream = File.Open(wveFile, FileMode.Open))
                {
                    BinaryReader reader = new BinaryReader(readerStream);

                    // load header
                    VoiceFontHeader fontHeader = new VoiceFontHeader();
                    fontHeader.Load(reader);

                    PrintLog("[Totoal Frame in each new VWF file.]", true);

                    // the data offset from the header
                    long dataOffSet = reader.BaseStream.Position;
                    uint outputFileSuffix = 0;
                    uint readFrameNumber = 0;
                    int curSplitSegmentIndex = 0;
                    for (int index = 0; index <= orderedSentenceIDs.Count; index++)
                    {
                        if (index < sentencCountList[curSplitSegmentIndex])
                        {
                            untFrameUpdateList.Add(orderedSentenceIDs[index], curFillFrameCount);
                            continue;
                        }

                        curSplitSegmentIndex++;
                        string newWVEFileName = Path.Combine(outputFolder, Path.GetFileNameWithoutExtension(wveFile) + "_" + outputFileSuffix.ToString() + ".wve");
                        PrintLog(string.Format("{0} Frame Update Count: {1}", Path.GetFileName(newWVEFileName), curFillFrameCount), true);

                        using (FileStream wveFileStream = File.Open(newWVEFileName, FileMode.Create))
                        {
                            BinaryWriter wveWriter = new BinaryWriter(wveFileStream);
                            fontHeader.Save(wveWriter);
                            long writerOffSet = wveWriter.BaseStream.Position;

                            // calculate lenth
                            long length = 0;
                            uint frameCount = 0;
                            if (index == orderedSentenceIDs.Count)
                            {
                                length = reader.BaseStream.Length - reader.BaseStream.Position;
                                frameCount = (uint)(length / bytesPerFrame);
                            }
                            else
                            {
                                // Get all candidate which are got from the specfied sentenc and sorted by frame index.
                                string endSentenceID = orderedSentenceIDs[index];
                                List<WaveCandidateInfo> endSenteceWaveInfo = indexFile.WaveCandidates.SelectMany(c => c.Value.Where(p => p.Value.SentenceId == endSentenceID))
                                                                                                             .Select(i => i.Value).SortBy(k => k.FrameIndexInSentence).ToList();

                                // Get the end candiate in the specifid sentence.
                                WaveCandidateInfo firstWaveCandidate = endSenteceWaveInfo[0];

                                frameCount = firstWaveCandidate.FrameIndex - firstWaveCandidate.FrameIndexInSentence - readFrameNumber;
                                length = bytesPerFrame * frameCount;
                                readFrameNumber = firstWaveCandidate.FrameIndex - firstWaveCandidate.FrameIndexInSentence;
                            }

                            // we need calculate how many bit will be filled into the WVE when it will be commpressed.
                            // 640 bit will be used in the compress tool, so we will reference this.
                            uint byteGap = (uint)((CompressFrameSize - (length % CompressFrameSize)) % CompressFrameSize);
                            uint updateFrameCount = (byteGap / bytesPerFrame) % compressFrameCount;
                            curFillFrameCount += updateFrameCount;

                            reader.BaseStream.Seek(dataOffSet, SeekOrigin.Begin);
                            byte[] data = reader.ReadBytes((int)length);
                            wveWriter.Write(data);

                            // fill data if the length can't be exact division.
                            if (bFillData)
                            {
                                FillSilenceData(wveWriter, byteGap);
                            }

                            // save the header file
                            fontHeader.DataSize = (ulong)(wveWriter.BaseStream.Position - writerOffSet);
                            SaveFontHeader(fontHeader, wveWriter);

                            dataOffSet = reader.BaseStream.Position;
                            PrintLog(string.Format("{0} Total Frame Count: {1} + {2}", Path.GetFileName(newWVEFileName), frameCount, updateFrameCount.ToString()), true);
                            PrintLog(string.Empty, true);

                            // recode the new file path.
                            newWVEFileList.Add(newWVEFileName);

                            if (index != orderedSentenceIDs.Count)
                            {
                                acdFrameUpdateList.Add(orderedSentenceIDs[index], curFillFrameCount);
                            }
                        }

                        header.Save(Path.ChangeExtension(newWVEFileName, "wih"));
                        outputFileSuffix++;

                        if (index != orderedSentenceIDs.Count)
                        {
                            index--;
                        }
                    }
                }

                // update ACD file.
                PrintLog("Update ACD file!", true);
                UpdateACDFile(indexFile, acdFrameUpdateList, fontPath + ".acd", Path.ChangeExtension(outputUnit, "acd"));

                // update index file
                PrintLog("Update UNT file!", true);
                UpdateIndexingFile(indexFile, untFrameUpdateList);
                indexFile.Save(outputUnit);
            }

            PrintLog("Split successfully!", true);

            return newWVEFileList;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Compares two UNT files by ignoring builder number.
        /// </summary>
        /// <param name="left">The left file name of UNT file.</param>
        /// <param name="right">The right file name of UNT file.</param>
        /// <returns>True if the two UNT file is equal, otherwise false.</returns>
        public static bool Compare(string left, string right)
        {
            using (UnitIndexingFile leftFile = new UnitIndexingFile(null))
            {
                leftFile.Load(left);
                using (UnitIndexingFile rightFile = new UnitIndexingFile(null))
                {
                    rightFile.Load(right);

                    leftFile.BuildNumber = rightFile.BuildNumber;
                    string tempFile = left + Path.GetRandomFileName();
                    try
                    {
                        leftFile.Save(tempFile);
                        return Helper.CompareBinary(tempFile, right);
                    }
                    finally
                    {
                        Helper.SafeDelete(tempFile);
                    }
                }
            }
        }