private static IntPtr SapiCategory(SPVTEXTFRAG sapiFrag, string interpretAs, string format)
        {
            int    num   = Array.BinarySearch(_asSayAsFormat, interpretAs);
            string value = (num >= 0) ? _asContextFormat[num] : format;

            sapiFrag.gcSayAsCategory = GCHandle.Alloc(value, GCHandleType.Pinned);
            return(sapiFrag.gcSayAsCategory.AddrOfPinnedObject());
        }
        private static IntPtr SapiCategory(SPVTEXTFRAG sapiFrag, string interpretAs, string format)
        {
            int    posSayAsFormat = Array.BinarySearch <string>(s_asSayAsFormat, interpretAs);
            string sFormat        = posSayAsFormat >= 0 ? s_asContextFormat[posSayAsFormat] : format;

            sapiFrag.gcSayAsCategory = GCHandle.Alloc(sFormat, GCHandleType.Pinned);
            return(sapiFrag.gcSayAsCategory.AddrOfPinnedObject());
        }
        internal static void FreeTextSegment(ref GCHandle fragment)
        {
            SPVTEXTFRAG sPVTEXTFRAG = (SPVTEXTFRAG)fragment.Target;

            if (sPVTEXTFRAG.gcNext.IsAllocated)
            {
                FreeTextSegment(ref sPVTEXTFRAG.gcNext);
            }
            if (sPVTEXTFRAG.gcPhoneme.IsAllocated)
            {
                sPVTEXTFRAG.gcPhoneme.Free();
            }
            if (sPVTEXTFRAG.gcSayAsCategory.IsAllocated)
            {
                sPVTEXTFRAG.gcSayAsCategory.Free();
            }
            sPVTEXTFRAG.gcText.Free();
            fragment.Free();
        }
        internal static void FreeTextSegment(ref GCHandle fragment)
        {
            SPVTEXTFRAG sapiFrag = (SPVTEXTFRAG)fragment.Target;

            if (sapiFrag.gcNext.IsAllocated)
            {
                FreeTextSegment(ref sapiFrag.gcNext);
            }

            // free the references to the optional elements
            if (sapiFrag.gcPhoneme.IsAllocated)
            {
                sapiFrag.gcPhoneme.Free();
            }

            if (sapiFrag.gcSayAsCategory.IsAllocated)
            {
                sapiFrag.gcSayAsCategory.Free();
            }

            // Free the text associated with this fragment
            sapiFrag.gcText.Free();
            fragment.Free();
        }
        internal static bool ToSapi(List <TextFragment> ssmlFrags, ref GCHandle sapiFragLast)
        {
            bool flag = true;

            for (int num = ssmlFrags.Count - 1; num >= 0; num--)
            {
                TextFragment textFragment = ssmlFrags[num];
                if (textFragment.State.Action != TtsEngineAction.StartParagraph && textFragment.State.Action != TtsEngineAction.StartSentence)
                {
                    SPVTEXTFRAG sPVTEXTFRAG = new SPVTEXTFRAG();
                    sPVTEXTFRAG.gcNext          = (flag ? default(GCHandle) : sapiFragLast);
                    sPVTEXTFRAG.pNext           = (flag ? IntPtr.Zero : sapiFragLast.AddrOfPinnedObject());
                    sPVTEXTFRAG.gcText          = GCHandle.Alloc(textFragment.TextToSpeak, GCHandleType.Pinned);
                    sPVTEXTFRAG.pTextStart      = sPVTEXTFRAG.gcText.AddrOfPinnedObject();
                    sPVTEXTFRAG.ulTextSrcOffset = textFragment.TextOffset;
                    sPVTEXTFRAG.ulTextLen       = textFragment.TextLength;
                    SPVSTATE      state  = default(SPVSTATE);
                    FragmentState state2 = textFragment.State;
                    state.eAction = (SPVACTIONS)state2.Action;
                    state.LangID  = (short)state2.LangId;
                    state.EmphAdj = ((state2.Emphasis == 1) ? 1 : 0);
                    if (state2.Prosody != null)
                    {
                        state.RateAdj            = SapiRate(state2.Prosody.Rate);
                        state.Volume             = SapiVolume(state2.Prosody.Volume);
                        state.PitchAdj.MiddleAdj = SapiPitch(state2.Prosody.Pitch);
                    }
                    else
                    {
                        state.Volume = 100;
                    }
                    state.ePartOfSpeech = SPPARTOFSPEECH.SPPS_Unknown;
                    if (state.eAction == SPVACTIONS.SPVA_Silence)
                    {
                        state.SilenceMSecs = SapiSilence(state2.Duration, (EmphasisBreak)state2.Emphasis);
                    }
                    if (state2.Phoneme != null)
                    {
                        state.eAction         = SPVACTIONS.SPVA_Pronounce;
                        sPVTEXTFRAG.gcPhoneme = GCHandle.Alloc(state2.Phoneme, GCHandleType.Pinned);
                        state.pPhoneIds       = sPVTEXTFRAG.gcPhoneme.AddrOfPinnedObject();
                    }
                    else
                    {
                        sPVTEXTFRAG.gcPhoneme = default(GCHandle);
                        state.pPhoneIds       = IntPtr.Zero;
                    }
                    if (state2.SayAs != null)
                    {
                        string format = state2.SayAs.Format;
                        string text;
                        switch (text = state2.SayAs.InterpretAs)
                        {
                        case "spellout":
                        case "spell-out":
                        case "characters":
                        case "letters":
                            state.eAction = SPVACTIONS.SPVA_SpellOut;
                            break;

                        case "time":
                        case "date":
                            if (!string.IsNullOrEmpty(format))
                            {
                                text = text + ":" + format;
                            }
                            state.Context.pCategory = SapiCategory(sPVTEXTFRAG, text, null);
                            break;

                        default:
                            state.Context.pCategory = SapiCategory(sPVTEXTFRAG, text, format);
                            break;
                        }
                    }
                    sPVTEXTFRAG.State = state;
                    sapiFragLast      = GCHandle.Alloc(sPVTEXTFRAG, GCHandleType.Pinned);
                    flag = false;
                }
            }
            return(!flag);
        }