Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Speech / Src / Internal / Synthesis / ConvertTextFrag.cs / 1 / ConvertTextFrag.cs
//------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // // // Converts text fragments from Sapi to SSML and from SSML to SAPI // // History: // 2/1/2005 [....] Created from the Sapi Managed code //----------------------------------------------------------------- using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Speech.Synthesis.TtsEngine; namespace System.Speech.Internal.Synthesis { internal static class ConvertTextFrag { //******************************************************************* // // Internal Methods // //******************************************************************* #region internal Methods internal static bool ToSapi (ListssmlFrags, ref GCHandle sapiFragLast) { bool fFirst = true; for (int iFrag = ssmlFrags.Count - 1; iFrag >= 0; iFrag--) { TextFragment textFragment = ssmlFrags [iFrag]; // Remove the start and end paragraph fragments if (textFragment.State.Action == TtsEngineAction.StartParagraph || textFragment.State.Action == TtsEngineAction.StartSentence) { continue; } SPVTEXTFRAG sapiFrag = new SPVTEXTFRAG (); // start with the text fragment sapiFrag.gcNext = fFirst ? new GCHandle () : sapiFragLast; sapiFrag.pNext = fFirst ? IntPtr.Zero : sapiFragLast.AddrOfPinnedObject (); sapiFrag.gcText = GCHandle.Alloc (textFragment.TextToSpeak, GCHandleType.Pinned); sapiFrag.pTextStart = sapiFrag.gcText.AddrOfPinnedObject (); sapiFrag.ulTextSrcOffset = textFragment.TextOffset; sapiFrag.ulTextLen = textFragment.TextLength; // State SPVSTATE sapiState = new SPVSTATE (); FragmentState ssmlState = textFragment.State; sapiState.eAction = (SPVACTIONS) ssmlState.Action; sapiState.LangID = (Int16) ssmlState.LangId; sapiState.EmphAdj = ssmlState.Emphasis != 1 ? 0 : 1; if (ssmlState.Prosody != null) { sapiState.RateAdj = SapiRate (ssmlState.Prosody.Rate); sapiState.Volume = SapiVolume (ssmlState.Prosody.Volume); sapiState.PitchAdj.MiddleAdj = SapiPitch (ssmlState.Prosody.Pitch); } else { sapiState.Volume = 100; } sapiState.ePartOfSpeech = SPPARTOFSPEECH.SPPS_Unknown; // Set the silence if any if (sapiState.eAction == SPVACTIONS.SPVA_Silence) { sapiState.SilenceMSecs = SapiSilence (ssmlState.Duration, (EmphasisBreak) ssmlState.Emphasis); } // Set the phonemes if any if (ssmlState.Phoneme != null) { sapiState.eAction = SPVACTIONS.SPVA_Pronounce; sapiFrag.gcPhoneme = GCHandle.Alloc (ssmlState.Phoneme, GCHandleType.Pinned); sapiState.pPhoneIds = sapiFrag.gcPhoneme.AddrOfPinnedObject (); // Get rid of the text if phonemes are defined. This is to be compatible with existing // TTS engines. } else { sapiFrag.gcPhoneme = new GCHandle (); sapiState.pPhoneIds = IntPtr.Zero; } // Set the say-as if any if (ssmlState.SayAs != null) { string format = ssmlState.SayAs.Format; string interpretAs; switch (interpretAs = ssmlState.SayAs.InterpretAs) { case "spellout": case "spell-out": case "characters": case "letters": sapiState.eAction = SPVACTIONS.SPVA_SpellOut; break; case "time": case "date": if (!string.IsNullOrEmpty (format)) { interpretAs = interpretAs + ':' + format; } sapiState.Context.pCategory = SapiCategory (sapiFrag, interpretAs, null); break; default: sapiState.Context.pCategory = SapiCategory (sapiFrag, interpretAs, format); break; } } sapiFrag.State = sapiState; sapiFragLast = GCHandle.Alloc (sapiFrag, GCHandleType.Pinned); fFirst = false; } return !fFirst; } private static IntPtr SapiCategory (SPVTEXTFRAG sapiFrag, string interpretAs, string format) { int posSayAsFormat = Array.BinarySearch (_asSayAsFormat, interpretAs); string sFormat = posSayAsFormat >= 0 ? _asContextFormat [posSayAsFormat] : format; sapiFrag.gcSayAsCategory = GCHandle.Alloc (sFormat, GCHandleType.Pinned); return sapiFrag.gcSayAsCategory.AddrOfPinnedObject (); } internal static void FreeTextSegment (ref GCHandle fragment) { SPVTEXTFRAG sapiFrag = (SPVTEXTFRAG) fragment.Target; if (sapiFrag.gcNext.IsAllocated) { FreeTextSegment (ref sapiFrag.gcNext); sapiFrag.gcNext.Free (); } // 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 (); } #endregion //******************************************************************** // // Private Methods // //******************************************************************* #region Private Methods private static int SapiVolume (ProsodyNumber volume) { int sapiVolume = 100; if (volume.SsmlAttributeId != ProsodyNumber.AbsoluteNumber) { switch ((ProsodyVolume) (int) volume.SsmlAttributeId) { case ProsodyVolume.ExtraLoud: sapiVolume = 100; break; case ProsodyVolume.Loud: sapiVolume = 80; break; case ProsodyVolume.Medium: sapiVolume = 60; break; case ProsodyVolume.Soft: sapiVolume = 40; break; case ProsodyVolume.ExtraSoft: sapiVolume = 20; break; case ProsodyVolume.Silent: sapiVolume = 0; break; } // add the relative information sapiVolume = (int) ((volume.IsNumberPercent ? sapiVolume * volume.Number : volume.Number) + 0.5); } else { sapiVolume = (int) (volume.Number + 0.5); } // Check the range. if (sapiVolume > 100) { sapiVolume = 100; } if (sapiVolume < 0) { sapiVolume = 0; } return sapiVolume; } private static int SapiSilence (int duration, EmphasisBreak emphasis) { int sapiSilence = 1000; if (duration > 0) { sapiSilence = duration; } else { switch (emphasis) { // No break, arbitrarily defined as 10 milliseconds case EmphasisBreak.None: sapiSilence = 10; break; // Extra small break, arbitrarily defined as 125 milliseconds case EmphasisBreak.ExtraWeak: sapiSilence = 125; break; // Small break, arbitrarily defined as 250 milliseconds case EmphasisBreak.Weak: sapiSilence = 250; break; // Medium break, arbitrarily defined as 1000 milliseconds case EmphasisBreak.Medium: sapiSilence = 1000; break; // Large break, arbitrarily defined as 1750 milliseconds case EmphasisBreak.Strong: sapiSilence = 1750; break; // Extra large break, arbitrarily defined as 3000 milliseconds case EmphasisBreak.ExtraStrong: sapiSilence = 3000; break; } } if (sapiSilence < 0 || sapiSilence > 0xffff) { sapiSilence = 1000; } return sapiSilence; } /// /// Produces the SAPI "RATE" tag /// /// ///private static int SapiRate (ProsodyNumber rate) { // Okay, we have a RATE element, but what do we set the rate to? // Rate varies on a scale from -10 to 10 for us. // There isn't a defined mapping between Words per Minute and rate. // For percentage changes, we will require that -10 maps to one third the default rate, // and +10 to three times the default, on a log scale. // But for absolute or relative (not percent) we can't support this without a defined base-line rate // We could get away with 180 for this in english, but very variable across languages. int sapiRate = 0; if (rate.SsmlAttributeId != ProsodyNumber.AbsoluteNumber) { switch ((ProsodyRate) (int) rate.SsmlAttributeId) { case ProsodyRate.ExtraSlow: sapiRate = -9; break; case ProsodyRate.Slow: sapiRate = -4; break; case ProsodyRate.Fast: sapiRate = 4; break; case ProsodyRate.ExtraFast: sapiRate = 9; break; } // add the relative information sapiRate = (int) ((rate.IsNumberPercent ? ScaleNumber (rate.Number, sapiRate, 10) : sapiRate) + 0.5); } else { sapiRate = ScaleNumber (rate.Number, 0, 10); } // Check the range. if (sapiRate > 10) { sapiRate = 10; } if (sapiRate < -10) { sapiRate = -10; } return sapiRate; } private static int SapiPitch (ProsodyNumber pitch) { int sapiPitch = 0; if (pitch.SsmlAttributeId != ProsodyNumber.AbsoluteNumber) { switch ((ProsodyPitch) (int) pitch.SsmlAttributeId) { case ProsodyPitch.ExtraHigh: sapiPitch = 9; break; case ProsodyPitch.High: sapiPitch = 4; break; case ProsodyPitch.Low: sapiPitch = -4; break; case ProsodyPitch.ExtraLow: sapiPitch = -9; break; } // add the relative information sapiPitch = (int) ((pitch.IsNumberPercent ? sapiPitch * pitch.Number : pitch.Number) + 0.5); } // Check the range. if (sapiPitch > 10) { sapiPitch = 10; } if (sapiPitch < -10) { sapiPitch = -10; } return sapiPitch; } private static int ScaleNumber (float value, int currentValue, int max) { int rate = 0; // Because we are on a logarithmic scale, can handle percentage changes // 300% --> multiply by 3.0 --> sapi rate change of +max.0 // 100% --> multiply by 1.0 --> sapi rate change of 0.0 // 33% --> multiply by 0.33 --> sapi rate change of -max.0 if (value >= 0.01) { rate = (int) (((Math.Log (value) / Math.Log (3.0)) * max) + 0.5); rate += currentValue; if (rate > max) { rate = max; } else if (rate < -max) { rate = -max; } } else { rate = -max; } return rate; } #endregion //******************************************************************** // // Private Field // //******************************************************************** #region Private Methods static readonly string [] _asSayAsFormat = new string [] { "acronym", "address", "cardinal", "currency", "date", "date:d", "date:dm", "date:dmy", "date:m", "date:md", "date:mdy", "date:my", "date:ym", "date:ymd", "date:y", "digits", "name", "net", "net:email", "net:uri", "ordinal", "spellout", "telephone", "time", "time:hms12", "time:hms24" }; static readonly string [] _asContextFormat = new string [] { "name", "address", "number_cardinal", "currency", "date_md", "date_dm", "date_dm", "date_dmy", "date_md", "date_md", "date_mdy", "date_my", "date_ym", "date_ymd", "date_year", "number_digit", "name", "web_url", "E-mail_address", "web_url", "number_ordinal", "", "phone_number", "time", "time", "time" }; #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DocumentXmlWriter.cs
- DetailsViewRowCollection.cs
- SecUtil.cs
- XamlWriter.cs
- ResourceExpression.cs
- HMACSHA512.cs
- xsdvalidator.cs
- ProfilePropertySettings.cs
- Deserializer.cs
- SqlCommandBuilder.cs
- ACE.cs
- WindowsEditBox.cs
- HttpResponseInternalBase.cs
- HttpModule.cs
- Point3DCollection.cs
- WebPartHeaderCloseVerb.cs
- Page.cs
- UIElementHelper.cs
- PageTheme.cs
- NavigationExpr.cs
- AnnotationElement.cs
- StateBag.cs
- XmlSchemaParticle.cs
- GlobalProxySelection.cs
- InternalPermissions.cs
- ApplicationBuildProvider.cs
- OptimizedTemplateContent.cs
- IChannel.cs
- WebBrowserContainer.cs
- TextClipboardData.cs
- ConfigurationManager.cs
- TextServicesLoader.cs
- Row.cs
- PartManifestEntry.cs
- SiteMapHierarchicalDataSourceView.cs
- InvalidProgramException.cs
- ServiceThrottle.cs
- CfgParser.cs
- ToolStripContentPanelRenderEventArgs.cs
- RegexTree.cs
- ThreadAbortException.cs
- WebConfigurationManager.cs
- DataSourceBooleanViewSchemaConverter.cs
- DBCSCodePageEncoding.cs
- DbConnectionStringBuilder.cs
- SqlUtil.cs
- BasicViewGenerator.cs
- DockPanel.cs
- FixedPosition.cs
- IntegerValidator.cs
- RemotingServices.cs
- DependencyObjectPropertyDescriptor.cs
- DataGridViewComboBoxEditingControl.cs
- SimpleTextLine.cs
- CompilerResults.cs
- ComponentResourceKey.cs
- Config.cs
- SymmetricKeyWrap.cs
- ToolStripOverflowButton.cs
- WebConfigurationHost.cs
- DecoratedNameAttribute.cs
- RuntimeArgumentHandle.cs
- TabControl.cs
- DateTimePicker.cs
- MaxSessionCountExceededException.cs
- BamlRecords.cs
- InputLanguageProfileNotifySink.cs
- CommonDialog.cs
- LookupBindingPropertiesAttribute.cs
- DataGridTextBox.cs
- ToolStripHighContrastRenderer.cs
- XmlUrlResolver.cs
- TemplatedAdorner.cs
- RunClient.cs
- WmlCommandAdapter.cs
- DataContractSerializerSection.cs
- DetailsViewPageEventArgs.cs
- WindowsSecurityToken.cs
- SetUserPreferenceRequest.cs
- InternalsVisibleToAttribute.cs
- DataServiceContext.cs
- ValueChangedEventManager.cs
- WebPartEditorCancelVerb.cs
- XmlnsDefinitionAttribute.cs
- DataGridItem.cs
- HealthMonitoringSection.cs
- TiffBitmapEncoder.cs
- IOException.cs
- UpdateTracker.cs
- MethodCallTranslator.cs
- AccessDataSource.cs
- GridViewCancelEditEventArgs.cs
- SpnegoTokenAuthenticator.cs
- URL.cs
- ViewGenResults.cs
- HttpRawResponse.cs
- AggregationMinMaxHelpers.cs
- AuthorizationRule.cs
- Random.cs
- TdsValueSetter.cs