wie kann ich Sapi.voice disposen?

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von -Franky-.

    wie kann ich Sapi.voice disposen?

    Hallo ,

    ich benutze SAPI.spVoice und frage mich, wie ich das Object wieder sauber aus dem Speicher bekomme kann?
    Gibt es dazu ein Dispose? Oder kann ich das irgendwie mit using machen?

    VB.NET-Quellcode

    1. Dim ObjTextToSpeech
    2. ObjTextToSpeech = CreateObject("SAPI.spVoice")
    3. ObjTextToSpeech.Speak(cNachricht, speechFlags)


    Als Ergänzung möchte ich mein Problem beschreiben.

    Wenn ich Sprachausgabe ca. 160 hintereinander aufrufe, dann erhalte ich eine Execption mit dem Hinweis
    "Zur Verarbeitung dieses Befehls sind nicht genügend Speicherressourcen verfügbar(Ausnahme von HRESLT: 0X80070008)
    Error Code -2147024888


    Der Fehler tritt auf mehreren PC auf. Alle mit 16 GB RAM . Win 10
    @Der flotte Johann Gibt es da ein DestroyObject()?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hi
    Füge einen Verweis unter COM auf die "Microsoft Speech Object Library 5.4" zu Deinem Projekt hinzu. Eventuell werden Dir da zwei Einträge angezeigt. Nur einer davon funktioniert. Bei mir die Dateiversion "5.3.29317.00".

    VB.NET-Quellcode

    1. Imports SpeechLib
    2. Imports System.ComponentModel
    3. Imports System.Runtime.InteropServices
    4. Public Class Form1
    5. Private TextToSpeech As New SpVoice
    6. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    7. TextToSpeech.Speak("Das ist ein Text.", SpeechVoiceSpeakFlags.SVSFlagsAsync)
    8. End Sub
    9. Private Sub Form1_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
    10. Marshal.ReleaseComObject(TextToSpeech)
    11. End Sub
    12. End Class

    Falls Du lieber mit "CreateObject" arbeiten möchtest, sollte es ausreichen ObjTextToSpeech = Nothing zu setzen.
    Mfg -Franky-

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „-Franky-“ ()

    Nun, ich habe es jetzt so gelöst, dass ich das Sapi.SPVoice als Globala Variable verwalte und dann nur ein einziges mal beim ersten Speak Befehl erstelle.
    Bei allen 10.000 folgenden Texten greife ich dann auf diese Globale Variable zurück, damit funktioniert es.

    Global

    VB.NET-Quellcode

    1. Public ObjTextToSpeech as Object


    VB.NET-Quellcode

    1. if isnothing(ObjTexttoSpeed) then
    2. ObjTextToSpeech = CreateObject("SAPI.spVoice")
    3. endif
    4. ObjTextToSpeech.Speak(cNachricht, speechFlags)


    Problem gelöst- Vielen Dank!
    Hi. CreateObject ist Bestanteil vom Namespace Microsoft.VisualBasic den man nach Möglichket in .NET nicht verwenden sollte. Spätes Binden ist auch nicht das gelbe vom Ei da Du dafür Option Strict Off arbeiten musst. Was spricht den gegen eine Referenz, und den damit verbundenen Vorteilen, auf die "Microsoft Speech Object Library"?
    Mfg -Franky-

    Der flotte Johann schrieb:

    Außerdem möchte ich so wenige wie möglich Abhängigkeiten im Einsatz.
    Das kann ich gut nachvollziehen. In dem Fall kannst Du auch direkt die Speech-Interfaces nutzen. Kein Verweis, kein Nuget-Paket und wenn man das ganze schön in eine Klasse packt, Kannst auch "Implements IDisposable" in die Klasse schreiben und hast Dein Dispose. ;)

    Unvollständig und alles in einer Form
    Spoiler anzeigen

    VB.NET-Quellcode

    1. ' https://learn.microsoft.com/en-us/previous-versions/office/developer/speech-technologies/jj127823(v=msdn.10)
    2. Imports System.ComponentModel
    3. Imports System.Runtime.InteropServices
    4. Public Class Form1
    5. Private Const CLSID_SpVoice As String = "9bc773b8-9b6c-400f-8af0-0dfdd1c43229"
    6. Private Const IID_ISpVoice As String = "6c44df74-72b9-4992-a1ec-ef996e0422d4"
    7. Private Enum SPEAKFLAGS As UInteger
    8. SPF_DEFAULT = &H0
    9. SPF_ASYNC = &H1
    10. SPF_PURGEBEFORESPEAK = &H2
    11. SPF_IS_FILENAME = &H4
    12. SPF_IS_XML = &H8
    13. SPF_IS_NOT_XML = &H10
    14. SPF_PERSIST_XML = &H20
    15. SPF_NLP_SPEAK_PUNC = &H40
    16. SPF_PARSE_SAPI = &H80
    17. SPF_PARSE_SSML = &H100
    18. End Enum
    19. Private m_ISpVoice As ISpVoice
    20. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    21. m_ISpVoice = CType(Activator.CreateInstance(Type.GetTypeFromCLSID(
    22. New Guid(CLSID_SpVoice))),
    23. ISpVoice)
    24. End Sub
    25. Private Sub Form1_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
    26. If m_ISpVoice IsNot Nothing Then Marshal.ReleaseComObject(m_ISpVoice)
    27. End Sub
    28. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    29. If m_ISpVoice IsNot Nothing Then
    30. m_ISpVoice.SetRate(-1)
    31. m_ISpVoice.Speak("Das ist ein Test.", SPEAKFLAGS.SPF_ASYNC, Nothing)
    32. End If
    33. End Sub
    34. #Region "Interface ISpVoice"
    35. <ComImport>
    36. <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
    37. <Guid(IID_ISpVoice)>
    38. Private Interface ISpVoice
    39. '/*** ISpNotifySource methods ***/
    40. 'HRESULT (STDMETHODCALLTYPE *SetNotifySink)(
    41. ' ISpNotifySink *pNotifySink);
    42. <PreserveSig> Function SetNotifySink() As Integer
    43. 'HRESULT (STDMETHODCALLTYPE *SetNotifyWindowMessage)(
    44. ' HWND hWnd,
    45. ' UINT Msg,
    46. ' WPARAM wParam,
    47. ' LPARAM lParam);
    48. <PreserveSig> Function SetNotifyWindowMessage() As Integer
    49. 'HRESULT (STDMETHODCALLTYPE *SetNotifyCallbackFunction)(
    50. ' SPNOTIFYCALLBACK *pfnCallback,
    51. ' WPARAM wParam,
    52. ' LPARAM lParam);
    53. <PreserveSig> Function SetNotifyCallbackFunction() As Integer
    54. 'HRESULT (STDMETHODCALLTYPE *SetNotifyCallbackInterface)(
    55. ' ISpNotifyCallback *pSpCallback,
    56. ' WPARAM wParam,
    57. ' LPARAM lParam);
    58. <PreserveSig> Function SetNotifyCallbackInterface() As Integer
    59. 'HRESULT (STDMETHODCALLTYPE *SetNotifyWin32Event)
    60. <PreserveSig> Function SetNotifyWin32Event() As Integer
    61. 'HRESULT (STDMETHODCALLTYPE *WaitForNotifyEvent)(
    62. ' DWORD dwMilliseconds);
    63. <PreserveSig> Function WaitForNotifyEvent() As Integer
    64. 'HANDLE (STDMETHODCALLTYPE *GetNotifyEventHandle)
    65. <PreserveSig> Function GetNotifyEventHandle() As Integer
    66. '/*** ISpEventSource methods ***/
    67. 'HRESULT (STDMETHODCALLTYPE *SetInterest)(
    68. ' ULONGLONG ullEventInterest,
    69. ' ULONGLONG ullQueuedInterest);
    70. <PreserveSig> Function SetInterest() As Integer
    71. 'HRESULT (STDMETHODCALLTYPE *GetEvents)(
    72. ' ULong ulCount,
    73. ' SPEVENT * pEventArray,
    74. ' ULong * pulFetched);
    75. <PreserveSig> Function GetEvents() As Integer
    76. 'HRESULT (STDMETHODCALLTYPE *GetInfo)(
    77. ' SPEVENTSOURCEINFO *pInfo);
    78. <PreserveSig> Function GetInfo() As Integer
    79. '/*** ISpVoice methods ***/
    80. 'HRESULT (STDMETHODCALLTYPE *SetOutput)(
    81. ' IUnknown *pUnkOutput,
    82. ' WINBOOL fAllowFormatChanges);
    83. <PreserveSig> Function SetOutput() As Integer
    84. 'HRESULT (STDMETHODCALLTYPE *GetOutputObjectToken)(
    85. ' ISpObjectToken **ppObjectToken);
    86. <PreserveSig> Function GetOutputObjectToken() As Integer
    87. 'HRESULT (STDMETHODCALLTYPE *GetOutputStream)(
    88. ' ISpStreamFormat **ppStream);
    89. <PreserveSig> Function GetOutputStream() As Integer
    90. 'HRESULT (STDMETHODCALLTYPE *Pause)
    91. <PreserveSig> Function Pause() As Integer
    92. 'HRESULT (STDMETHODCALLTYPE *Resume)
    93. <PreserveSig> Function [Resume]() As Integer
    94. 'HRESULT (STDMETHODCALLTYPE *SetVoice)(
    95. ' ISpObjectToken *pToken);
    96. <PreserveSig> Function SetVoice() As Integer
    97. 'HRESULT (STDMETHODCALLTYPE *GetVoice)(
    98. ' ISpObjectToken **ppToken);
    99. <PreserveSig> Function GetVoice() As Integer
    100. 'HRESULT (STDMETHODCALLTYPE *Speak)(
    101. ' LPCWSTR pwcs,
    102. ' DWORD dwFlags,
    103. ' ULong * pulStreamNumber);
    104. <PreserveSig> Function Speak(<[In], MarshalAs(UnmanagedType.LPWStr)> pwcs As String,
    105. <[In]> dwFlags As SPEAKFLAGS,
    106. <Out> ByRef pulStreamNumber As ULong) As Integer
    107. 'HRESULT (STDMETHODCALLTYPE *SpeakStream)(
    108. ' IStream *pStream,
    109. ' DWORD dwFlags,
    110. ' ULONG *pulStreamNumber);
    111. <PreserveSig> Function SpeakStream() As Integer
    112. 'HRESULT (STDMETHODCALLTYPE *GetStatus)(
    113. ' SPVOICESTATUS *pStatus,
    114. ' LPWSTR *ppszLastBookmark);
    115. <PreserveSig> Function GetStatus() As Integer
    116. 'HRESULT (STDMETHODCALLTYPE *Skip)(
    117. ' LPCWSTR pItemType,
    118. ' LONG lNumItems,
    119. ' ULONG *pulNumSkipped);
    120. <PreserveSig> Function Skip() As Integer
    121. 'HRESULT (STDMETHODCALLTYPE *SetPriority)(
    122. ' SPVPRIORITY ePriority);
    123. <PreserveSig> Function SetPriority() As Integer
    124. 'HRESULT (STDMETHODCALLTYPE *GetPriority)(
    125. ' SPVPRIORITY *pePriority);
    126. <PreserveSig> Function GetPriority() As Integer
    127. 'HRESULT (STDMETHODCALLTYPE *SetAlertBoundary)(
    128. ' SPEVENTENUM eBoundary);
    129. <PreserveSig> Function SetAlertBoundary() As Integer
    130. 'HRESULT (STDMETHODCALLTYPE *GetAlertBoundary)(
    131. ' SPEVENTENUM *peBoundary);
    132. <PreserveSig> Function GetAlertBoundary() As Integer
    133. 'HRESULT (STDMETHODCALLTYPE *SetRate)(
    134. ' Long RateAdjust);
    135. <PreserveSig> Function SetRate(<[In]> RateAdjust As Integer) As Integer
    136. 'HRESULT (STDMETHODCALLTYPE *GetRate)(
    137. ' Long * pRateAdjust);
    138. <PreserveSig> Function GetRate(<Out> ByRef pRateAdjust As Integer) As Integer
    139. 'HRESULT (STDMETHODCALLTYPE *SetVolume)(
    140. ' UShort usVolume);
    141. <PreserveSig> Function SetVolume() As Integer
    142. 'HRESULT (STDMETHODCALLTYPE *GetVolume)(
    143. ' UShort * pusVolume);
    144. <PreserveSig> Function GetVolume() As Integer
    145. 'HRESULT (STDMETHODCALLTYPE *WaitUntilDone)(
    146. ' ULong msTimeout);
    147. <PreserveSig> Function WaitUntilDone() As Integer
    148. 'HRESULT (STDMETHODCALLTYPE *SetSyncSpeakTimeout)(
    149. ' ULong msTimeout);
    150. <PreserveSig> Function SetSyncSpeakTimeout() As Integer
    151. 'HRESULT (STDMETHODCALLTYPE *GetSyncSpeakTimeout)(
    152. ' ULong * pmsTimeout);
    153. <PreserveSig> Function GetSyncSpeakTimeout() As Integer
    154. 'HANDLE (STDMETHODCALLTYPE *SpeakCompleteEvent)
    155. <PreserveSig> Function SpeakCompleteEvent() As Integer
    156. 'HRESULT (STDMETHODCALLTYPE *IsUISupported)(
    157. ' LPCWSTR pszTypeOfUI,
    158. ' void *pvExtraData,
    159. ' ULong cbExtraData,
    160. ' WINBOOL * pfSupported);
    161. <PreserveSig> Function IsUISupported() As Integer
    162. 'HRESULT (STDMETHODCALLTYPE *DisplayUI)(
    163. ' HWND hwndParent,
    164. ' LPCWSTR pszTitle,
    165. ' LPCWSTR pszTypeOfUI,
    166. ' void *pvExtraData,
    167. ' ULong cbExtraData);
    168. <PreserveSig> Function DisplayUI() As Integer
    169. End Interface
    170. #End Region
    171. End Class

    Mfg -Franky-

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „-Franky-“ ()

    Der flotte Johann schrieb:

    Es gibt keine Änderung der Geschwindigkeit. Ich habe Parameter -3 , 3 , 10, 1000, und 30000 getestet.

    Wenn Du dem Link in meinem Code folgst -> SetRate: learn.microsoft.com/en-us/prev…logies/jj149379(v=msdn.10) -> Parameters und Remarks lesen.

    ISPVoice.SetVoice -> learn.microsoft.com/en-us/prev…logies/jj149381(v=msdn.10) -> Da gibt es ein kleines C++ Beispiel wie man die installieren Voices auflistet und an die entsprechenden Token eines bestimmten Voice kommt.
    Mfg -Franky-
    Hi. Auch wenn das Thema eventuell erledigt ist, habe ich dennoch ein bischen was an meinem Code geschraubt und ein bissel erweitert. Ist halt nur Testcode und darf gern verbessert und erweitert werden. Was kann das Ding: Natürlich einen String wiedergeben, Volume und Rate kann angepasst werden, die installierten Voices können ermittelt werden und entsprechend kann für die Ausgabe ein Voice eingestellt werden. Keine Referenzen und keine Nuget-Pakete. Dafür Unvollständig (ich brauch das ja nicht). Da geht also noch viel mehr. Ab Win10 würde ich die TTS über die WinRT bevorzugen da diese einfacher zu programmieren ist als die TTS über die SAPI-Interfaces.
    Dateien
    Mfg -Franky-