| File: Internal\Synthesis\TTSEngineProxy.cs | Web Access |
| Project: src\runtime\src\libraries\System.Speech\src\System.Speech.csproj (System.Speech) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Runtime.InteropServices; using System.Speech.Synthesis.TtsEngine; namespace System.Speech.Internal.Synthesis { internal abstract class ITtsEngineProxy { internal ITtsEngineProxy(int lcid) { _alphabetConverter = new AlphabetConverter(lcid); } internal abstract IntPtr GetOutputFormat(IntPtr targetFormat); internal abstract void AddLexicon(Uri lexicon, string? mediaType); internal abstract void RemoveLexicon(Uri lexicon); internal abstract void Speak(List<TextFragment> frags, byte[] wfx); internal abstract void ReleaseInterface(); internal abstract char[]? ConvertPhonemes(char[] phones, AlphabetType alphabet); internal abstract AlphabetType EngineAlphabet { get; } internal AlphabetConverter AlphabetConverter { get { return _alphabetConverter; } } protected AlphabetConverter _alphabetConverter; } internal class TtsProxySsml : ITtsEngineProxy { #region Constructors internal TtsProxySsml(TtsEngineSsml ssmlEngine, ITtsEngineSite site, int lcid) : base(lcid) { _ssmlEngine = ssmlEngine; _site = site; } #endregion #region Internal Methods internal override IntPtr GetOutputFormat(IntPtr targetFormat) { return _ssmlEngine.GetOutputFormat(SpeakOutputFormat.WaveFormat, targetFormat); } internal override void AddLexicon(Uri lexicon, string? mediaType) { _ssmlEngine.AddLexicon(lexicon, mediaType, _site); } internal override void RemoveLexicon(Uri lexicon) { _ssmlEngine.RemoveLexicon(lexicon, _site); } internal override void Speak(List<TextFragment> frags, byte[] wfx) { GCHandle gc = GCHandle.Alloc(wfx, GCHandleType.Pinned); try { IntPtr waveFormat = gc.AddrOfPinnedObject(); _ssmlEngine.Speak(frags.ToArray(), waveFormat, _site); } finally { gc.Free(); } } internal override char[]? ConvertPhonemes(char[] phones, AlphabetType alphabet) { if (alphabet == AlphabetType.Ipa) { return phones; } else { return _alphabetConverter.SapiToIpa(phones); } } internal override AlphabetType EngineAlphabet { get { return AlphabetType.Ipa; } } /// <summary> /// Release the COM interface for COM object /// </summary> internal override void ReleaseInterface() { } #endregion #region private Fields private TtsEngineSsml _ssmlEngine; private ITtsEngineSite _site; #endregion } internal class TtsProxySapi : ITtsEngineProxy { #region Constructors internal TtsProxySapi(ITtsEngine sapiEngine, IntPtr iSite, int lcid) : base(lcid) { _iSite = iSite; _sapiEngine = sapiEngine; } #endregion #region Internal Methods internal override IntPtr GetOutputFormat(IntPtr preferredFormat) { // Initialize TTS Engine Guid formatId = SAPIGuids.SPDFID_WaveFormatEx; Guid guidNull = new(); IntPtr coMem = IntPtr.Zero; _sapiEngine.GetOutputFormat(ref formatId, preferredFormat, out guidNull, out coMem); return coMem; } internal override void AddLexicon(Uri lexicon, string? mediaType) { // SAPI: Ignore } internal override void RemoveLexicon(Uri lexicon) { // SAPI: Ignore } internal override void Speak(List<TextFragment> frags, byte[] wfx) { GCHandle gc = GCHandle.Alloc(wfx, GCHandleType.Pinned); try { IntPtr waveFormat = gc.AddrOfPinnedObject(); GCHandle spvTextFragment = new(); if (ConvertTextFrag.ToSapi(frags, ref spvTextFragment)) { Guid formatId = SAPIGuids.SPDFID_WaveFormatEx; try { _sapiEngine.Speak(0, ref formatId, waveFormat, spvTextFragment.AddrOfPinnedObject(), _iSite); } finally { ConvertTextFrag.FreeTextSegment(ref spvTextFragment); } } } finally { gc.Free(); } } internal override AlphabetType EngineAlphabet { get { return AlphabetType.Sapi; } } internal override char[]? ConvertPhonemes(char[] phones, AlphabetType alphabet) { if (alphabet == AlphabetType.Ipa) { return _alphabetConverter.IpaToSapi(phones); } else { return phones; } } /// <summary> /// Release the COM interface for COM object /// </summary> internal override void ReleaseInterface() { Marshal.ReleaseComObject(_sapiEngine); } #endregion #region private Fields private ITtsEngine _sapiEngine; // This variable is stored here but never created or deleted private IntPtr _iSite; #endregion } }