TTS - Sapi 5 (XP et plus) and Speech SDK 11 (Vista et plus)

Just starting out? Need help? Post your questions and find answers here.
User avatar
gurj
Enthusiast
Enthusiast
Posts: 664
Joined: Thu Jan 22, 2009 3:48 am
Location: china
Contact:

TTS - Sapi 5 (XP et plus) and Speech SDK 11 (Vista et plus)

Post by gurj »

uptated

Code: Select all

;TTS - Sapi 5 (XP et plus) et Speech SDK 11 (Vista et plus)
;from https://www.purebasic.fr/french/viewtopic.php?f=6&t=15716
;[old code by nico at 12/23/15-13:00]添加了 SkipStream (...) 功能, 允许您绕过当前回放, 向前或向后。
;by gurj add Pitch and getSpeakPosition() and speakFromCursor, but has question,has better way? thanks.

#CLSCTX_INPROC_SERVER=1

;// Valeur pour SpeechVoiceSpeakFlags
#SVSFDefault = 0
#SVSFlagsAsync = 1
#SVSFPurgeBeforeSpeak = 2
#SVSFIsFilename = 4
#SVSFIsXML = 8
#SVSFIsNotXML = 16
#SVSFPersistXML = 32
#SVSFNLPSpeakPunc = 64
#SVSFNLPMask = 64
#SVSFVoiceMask = 127
#SVSFUnusedFlags = -128

Enumeration ; SPSTREAMFORMAT
 #SPSF_Default
 #SPSF_NoAssignedFormat
 #SPSF_Text
 #SPSF_NonStandardFormat
 #SPSF_ExtendedAudioFormat
 ;// Standard PCM wave formats
 #SPSF_8kHz8BitMono
 #SPSF_8kHz8BitStereo
 #SPSF_8kHz16BitMono
 #SPSF_8kHz16BitStereo
 #SPSF_11kHz8BitMono
 #SPSF_11kHz8BitStereo
 #SPSF_11kHz16BitMono
 #SPSF_11kHz16BitStereo
 #SPSF_12kHz8BitMono
 #SPSF_12kHz8BitStereo
 #SPSF_12kHz16BitMono
 #SPSF_12kHz16BitStereo
 #SPSF_16kHz8BitMono
 #SPSF_16kHz8BitStereo
 #SPSF_16kHz16BitMono
 #SPSF_16kHz16BitStereo
 #SPSF_22kHz8BitMono
 #SPSF_22kHz8BitStereo
 #SPSF_22kHz16BitMono
 #SPSF_22kHz16BitStereo
 #SPSF_24kHz8BitMono
 #SPSF_24kHz8BitStereo
 #SPSF_24kHz16BitMono
 #SPSF_24kHz16BitStereo
 #SPSF_32kHz8BitMono
 #SPSF_32kHz8BitStereo
 #SPSF_32kHz16BitMono
 #SPSF_32kHz16BitStereo
 #SPSF_44kHz8BitMono
 #SPSF_44kHz8BitStereo
 #SPSF_44kHz16BitMono
 #SPSF_44kHz16BitStereo
 #SPSF_48kHz8BitMono
 #SPSF_48kHz8BitStereo
 #SPSF_48kHz16BitMono
 #SPSF_48kHz16BitStereo
 ;// TrueSpeech format
 #SPSF_TrueSpeech_8kHz1BitMono
 ;// A-Law formats
 #SPSF_CCITT_ALaw_8kHzMono
 #SPSF_CCITT_ALaw_8kHzStereo
 #SPSF_CCITT_ALaw_11kHzMono
 #SPSF_CCITT_ALaw_11kHzStereo
 #SPSF_CCITT_ALaw_22kHzMono
 #SPSF_CCITT_ALaw_22kHzStereo
 #SPSF_CCITT_ALaw_44kHzMono
 #SPSF_CCITT_ALaw_44kHzStereo
 ;// u-Law formats
 #SPSF_CCITT_uLaw_8kHzMono
 #SPSF_CCITT_uLaw_8kHzStereo
 #SPSF_CCITT_uLaw_11kHzMono
 #SPSF_CCITT_uLaw_11kHzStereo
 #SPSF_CCITT_uLaw_22kHzMono
 #SPSF_CCITT_uLaw_22kHzStereo
 #SPSF_CCITT_uLaw_44kHzMono
 #SPSF_CCITT_uLaw_44kHzStereo
 ;// ADPCM formats
 #SPSF_ADPCM_8kHzMono
 #SPSF_ADPCM_8kHzStereo
 #SPSF_ADPCM_11kHzMono
 #SPSF_ADPCM_11kHzStereo
 #SPSF_ADPCM_22kHzMono
 #SPSF_ADPCM_22kHzStereo
 #SPSF_ADPCM_44kHzMono
 #SPSF_ADPCM_44kHzStereo
 ;// GSM 6.10 formats
 #SPSF_GSM610_8kHzMono
 #SPSF_GSM610_11kHzMono
 #SPSF_GSM610_22kHzMono
 #SPSF_GSM610_44kHzMono
 #SPSF_NUM_FORMATS
EndEnumeration

Interface ISpeechObjectTokenCategory Extends IDispatch
 get_Id(Id.i)
 set_Default(TokenId.i)
 get_Default(TokenId.i)
 SetId(Id.p-bstr, CreateIfNotExist.i)
 GetDataKey(SpeechDataKeyLocation.i, ISpeechDataKey.i)
 EnumerateTokens(RequiredAttributes.i, OptionalAttributes.i, ISpeechObjectTokens.i)
EndInterface

Interface ISpeechObjectToken Extends IDispatch
 get_Id(ObjectId.i)
 get_DataKey(ISpeechDataKey.i)
 get_Category(ISpeechObjectTokenCategory.i)
 GetDescription(Locale.i, Description.i);区域设置.
 SetId(Id.i, CategoryID.i, CreateIfNotExist.l)
 GetAttribute(AttributeName.p-bstr, AttributeValue.i)
 CreateInstance(pUnkOuter.i, SpeechTokenContext.l, Object.i)
 Remove(ObjectStorageCLSID.i)
 GetStorageFileName(ObjectStorageCLSID.i, KeyName,FileName.i, SpeechTokenShellFolder.l, FilePath.i)
 RemoveStorageFileName(ObjectStorageCLSID.i, KeyName.i, DeleteFile.l)
 IsUISupported(TypeOfUI.i, ExtraData.variant, Object.i, Supported.i)
 DisplayUI(hWnd.i, Title.i, TypeOfUI.i, ExtraData.variant, Object.i)
 MatchesAttributes(Attributes.i, Matches.i)
EndInterface

Interface ISpeechObjectTokens Extends IDispatch
 get_Count(a.l)
 Item(Index.l, Token.ISpeechObjectToken)
 get__NewEnum(ppEnumVARIANT.IUnknown)
EndInterface

Interface ISpeechAudioFormat Extends IDispatch
 get_Type(SpeechAudioFormatType.i)
 set_Type(SpeechAudioFormatType.i)
 get_Guid(Guid.i)
 set_Guid(Guid.i)
 GetWaveFormatEx(ISpeechWaveFormatEx.i)
 SetWaveFormatEx(ISpeechWaveFormatEx.i)
EndInterface

Interface ISpeechFileStream Extends IDispatch
 get_Format(ISpeechAudioFormat.i)
 set_putref_Format(ISpeechAudioFormat.i)
 Read(Buffer.i, NumberOfBytes.i, BytesRead.i, BytesWritten.i)
 Write(Buffer.i, BytesWritten.i)
 Seek(Position.i, SpeechStreamSeekPositionType.i, NewPosition.i)
 Open(FileName.p-bstr, SpeechStreamFileMode.i, DoEvents.i)
 Close()
EndInterface

Interface ISpeechVoiceStatus Extends IDispatch
 get_CurrentStreamNumber(StreamNumber.i)
 get_LastStreamNumberQueued(StreamNumber.i)
 get_LastHResult(Hresult.i)
 get_RunningState(State.i)
 get_InputWordPosition(Position.i)
 get_InputWordLength(Length.i)
 get_InputSentencePosition(Position.i)
 get_InputSentenceLength(Length.i)
 get_LastBookmark(Bookmark.i)
 get_LastBookmarkId(BookmarkId.i)
 get_PhonemeId(PhoneId.i)
 get_VisemeId(VisemeId.i)
EndInterface

Interface ISpeechVoice Extends IDispatch
 get_Status(ISpeechVoiceStatus.i)
 get_Voice(ISpeechObjectToken.i)
 put_Voice(ISpeechObjectToken.i)
 get_AudioOutput(ISpeechObjectToken.i)
 put_AudioOutput(ISpeechObjectToken.i)
 get_AudioOutputStream(ISpeechBaseStream.i)
 put_AudioOutputStream(ISpeechBaseStream.i)
 get_Rate(long.i)
 put_Rate(long.i)
 get_Volume(long.i)
 put_Volume(long.i)
 put_AllowAudioOutputFormatChangesOnNextSet(VARIANT_BOOL.i)
 get_AllowAudioOutputFormatChangesOnNextSet(VARIANT_BOOL.i)
 get_EventInterests(SpeechVoiceEvents.i)
 put_EventInterests(SpeechVoiceEvents.i)
 put_Priority(SpeechVoicePriority.i)
 get_Priority(SpeechVoicePriority.i)
 put_AlertBoundary(SpeechVoiceEvents.i)
 get_AlertBoundary(SpeechVoiceEvents.i)
 put_SynchronousSpeakTimeout(long.i)
 get_SynchronousSpeakTimeout(long.i)
 Speak(Text.p-bstr, SpeechVoiceSpeakFlags.l, IDVoice.i)
 SpeakStream(ISpeechBaseStream.i, SpeechVoiceSpeakFlags.l, StreamNumber.i)
 Pause()
 Resume()
 Skip(Type.i, NumItems.l, NumSkipped.i);跳过
 GetVoices(RequiredAttributes.i, OptionalAttributes.i, ISpeechObjectTokens.i)
 GetAudioOutputs(RequiredAttributes.i, OptionalAttributes.i, ISpeechObjectTokens.i)
 WaitUntilDone(msTimeout.l, VARIANT_BOOL.i)
 SpeakCompleteEvent(Handle.i)
 IsUISupported(TypeOfUI.i, ExtraData.VARIANT, VARIANT_BOOL.i)
 DisplayUI(hWndParent.i, Title.i, TypeOfUI.i, ExtraData.VARIANT)
EndInterface

Structure AttributeVoice
 Description.s
 LangID.s
 Item.l
 Rate.l
 Volume.l
 SpeechVoice.i
EndStructure

Structure AttributeAudio
 Description.s
 Item.l
 DeviceId.s
EndStructure

Procedure.i ConvertToUnicode(AsciiOrUnicode.s)
 Static *MemoryUnicode
 Protected LenMemoryUnicode.l
 
 If *MemoryUnicode <> 0
  FreeMemory(*MemoryUnicode)
 EndIf
 
 LenMemoryUnicode = StringByteLength(AsciiOrUnicode , #PB_Unicode)
 *MemoryUnicode = AllocateMemory(LenMemoryUnicode + 2)
 If *MemoryUnicode <> 0
  PokeS(*MemoryUnicode, AsciiOrUnicode, Len(AsciiOrUnicode), #PB_Unicode)
  ProcedureReturn *MemoryUnicode
 EndIf
 
 ProcedureReturn 0
EndProcedure

Procedure.i InterfaceData(Option.l, Donnees.i)
 Static NameInterface.l
 
 If Option = 1
  NameInterface = Donnees
  ProcedureReturn 1
 ElseIf Option = -1
  ProcedureReturn NameInterface
 EndIf
 
 ProcedureReturn 0
EndProcedure

Procedure SetInterfaceData(Option.l, Donnees.i)
 ProcedureReturn InterfaceData(Option.l, Donnees.i)
EndProcedure

Procedure.i GetInterfaceData(Option.l)
 ProcedureReturn InterfaceData(-1, 0)
EndProcedure


Procedure.l SaveTextToWav(Array VoicesSapi.AttributeVoice(1), VoixID.l, Texte.s, File.s, Format.l)
 Protected SpeechFileStream.ISpeechFileStream, SpeechAudioFormat.ISpeechAudioFormat
 Protected SpeechFileStreamDefault.i, IDVoice.l, NameInterface$, NameInterface.l, Ret.l=-10
 Protected  SSFMCreateForWrite = 3
 
 If VoixID > -1 And VoixID <= ArraySize(VoicesSapi())
  NameInterface = GetInterfaceData(-1)
  
  If NameInterface = 2 ; Speech 11
   NameInterface$ = "SAPI.SpFileStream"
  ElseIf NameInterface = 1 ; Sapi 5
   NameInterface$ = "Speech.SpFileStream"
  Else
   Ret = -9
   Goto Error2
  EndIf
  
  If CLSIDFromProgID_(ConvertToUnicode(NameInterface$), @CLSID.CLSID) < #S_OK
   Ret = -8
   Goto Error2
  EndIf
  
  If CLSIDFromString_(ConvertToUnicode("{AF67F125-AB39-4E93-B4A2-CC2E66E182A7}"), @Refiid.CLSID) < #S_OK
   Ret = -7
   Goto Error2
  EndIf
  
  If  CoCreateInstance_(Clsid, #Null, #CLSCTX_INPROC_SERVER, Refiid, @SpeechFileStream.ISpeechFileStream) < #S_OK
   Ret = -6
   Goto Error2
  EndIf
  
  If SpeechFileStream\get_Format(@SpeechAudioFormat.ISpeechAudioFormat) < #S_OK
   Ret = -5
   Goto Error2
  EndIf
  
  If SpeechAudioFormat\set_Type(Format) < #S_OK
   Ret = -4
   Goto Error2
  EndIf
  
  If SpeechFileStream\Open(File, SSFMCreateForWrite, 0) < #S_OK
   Ret = -3
   Goto Error2
  EndIf
  
  SpeechVoice.ISpeechVoice = VoicesSapi(VoixID)\SpeechVoice
  If SpeechVoice = 0
   Ret = -2
   Goto Error2
  EndIf
  
  If SpeechVoice\get_AudioOutputStream(@SpeechFileStreamDefault) < #S_OK
   Ret = -1
   Goto Error2
  EndIf
  
  If SpeechVoice\put_AudioOutputStream(SpeechFileStream) < #S_OK
   Ret = 0
   Goto Error2
  EndIf
  
  If SpeechVoice\Speak(Texte, 0, @IDVoice) < #S_OK
   Ret = 1
   Goto Error2
  EndIf
  
  
  error2:
  If SpeechFileStream <> 0
   SpeechFileStream\Close()
   SpeechFileStream\Release()
  EndIf
  
  If SpeechAudioFormat <> 0
   SpeechAudioFormat\Release()
  EndIf
  
  If SpeechFileStreamDefault <> 0
   SpeechVoice\put_AudioOutputStream(SpeechFileStreamDefault)
  EndIf
  
 EndIf
 ;如果成功的函数返回1
 ProcedureReturn Ret
EndProcedure

Procedure GetAudioOutput(Array VoicesAudio.AttributeAudio(1), *DefaultAudio.long)
 Protected SpeechObjectTokenCategory.ISpeechObjectTokenCategory
 Protected SpeechObjectTokens.ISpeechObjectTokens
 Protected SpeechObjectToken.ISpeechObjectToken
 Protected Clsid.CLSID, Refiid.CLSID, NameInterface$
 Protected Description.i, DescriptionAudio.s, ID.s, DefaultID.s
 Protected a.l, Ret.l=0
 
 #SpeechCategoryAudioOut = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\AudioOutput"
 
 
 NameInterface = GetInterfaceData(-1)
 
 If NameInterface = 2 ; Speech 11
  NameInterface$ = "Speech.SpObjectTokenCategory"
 ElseIf NameInterface = 1 ; Sapi 5
  NameInterface$ = "Sapi.SpObjectTokenCategory"
 Else
  Goto Error3
 EndIf
 
 If CLSIDFromProgID_(ConvertToUnicode(NameInterface$), @Clsid.CLSID) < #S_OK
  Goto Error3
 EndIf
 
 If CLSIDFromString_(ConvertToUnicode("{CA7EAC50-2D01-4145-86D4-5AE7D70F4469}"), @Refiid.CLSID) < #S_OK
  Goto Error3
 EndIf
 
 If CoCreateInstance_(Clsid, #Null, #CLSCTX_INPROC_SERVER, Refiid, @SpeechObjectTokenCategory.ISpeechObjectTokenCategory) >= #S_OK
  If SpeechObjectTokenCategory\SetId(#SpeechCategoryAudioOut, 0) >= #S_OK
   
   If SpeechObjectTokenCategory\get_Default(@Description) >= #S_OK
    If Description <> 0
     DefaultID.s = PeekS(Description, -1, #PB_Unicode)
     ;Debug DefaultID
     SysFreeString_(Description)
    EndIf
   EndIf
   
   If SpeechObjectTokenCategory\EnumerateTokens(0, 0, @SpeechObjectTokens.ISpeechObjectTokens) >= #S_OK
    If SpeechObjectTokens\get_Count(@Count.l) >= #S_OK
     
     For a = 0 To count -1
      If SpeechObjectTokens\Item(a, @SpeechObjectToken.ISpeechObjectToken) >= #S_OK
       If SpeechObjectToken\GetDescription(0, @Description) >= #S_OK
        If Description <> 0
         DescriptionAudio.s = PeekS(Description, -1, #PB_Unicode)
         ;Debug DescriptionAudio
         SysFreeString_(Description)
         VoicesAudio(a)\Description = DescriptionAudio
         Ret = Ret + 1
        EndIf
        
        If SpeechObjectToken\get_Id(@Description) >= #S_OK
         If Description <> 0
          ID.s = PeekS(Description, -1, #PB_Unicode)
          ;Debug ID
          VoicesAudio(a)\DeviceId = ID
          If DefaultID = ID
           *DefaultAudio\l = a
          EndIf
         EndIf
         SysFreeString_(Description)
        EndIf
        
        VoicesAudio(a)\Item = a
       EndIf
       SpeechObjectToken\Release()
      EndIf
     Next a
     
    EndIf
    SpeechObjectTokens\Release()
   EndIf
   
  EndIf
  SpeechObjectTokenCategory\Release()
 EndIf
 
 Error3:
 ProcedureReturn Ret
EndProcedure

Procedure SetAudioOutput(Array VoicesSapi.AttributeVoice(1), Item.l)
 Protected SpeechObjectTokenCategory.ISpeechObjectTokenCategory
 Protected SpeechObjectTokens.ISpeechObjectTokens
 Protected SpeechObjectToken.ISpeechObjectToken
 Protected Clsid.CLSID, Refiid.CLSID, NameInterface$, NameInterface.l
 Protected Description.i, DescriptionAudio.s, a.l, Ret.l=0
 Protected SpeechVoice.ISpeechVoice
 
 #SpeechCategoryAudioOut = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\AudioOutput"
 
 If Item > -1 And Item  <= ArraySize(VoicesSapi())
  SpeechVoice = VoicesSapi(0)\SpeechVoice
  
  If SpeechVoice <> 0
   
   NameInterface = GetInterfaceData(-1)
   
   If NameInterface = 1 ; Sapi 5
    NameInterface$ = "Speech.SpObjectTokenCategory"
   ElseIf NameInterface = 2 ; Speech 11
    NameInterface$ = "Sapi.SpObjectTokenCategory"
   Else
    Goto Error5
   EndIf
   
   If CLSIDFromProgID_(ConvertToUnicode(NameInterface$), @Clsid.CLSID) < #S_OK
    Goto Error5
   EndIf
   
   If CLSIDFromString_(ConvertToUnicode("{CA7EAC50-2D01-4145-86D4-5AE7D70F4469}"), @Refiid.CLSID) < #S_OK
    Goto Error5
   EndIf
   
   If  CoCreateInstance_(Clsid, #Null, #CLSCTX_INPROC_SERVER, Refiid, @SpeechObjectTokenCategory.ISpeechObjectTokenCategory) >= #S_OK
    If SpeechObjectTokenCategory\SetId(#SpeechCategoryAudioOut, 0) >= #S_OK
     If SpeechObjectTokenCategory\EnumerateTokens(0, 0, @SpeechObjectTokens.ISpeechObjectTokens) >= #S_OK
      If SpeechObjectTokens\Item(Item, @SpeechObjectToken.ISpeechObjectToken)>= #S_OK
       If SpeechObjectToken <> 0
        If SpeechVoice\put_AudioOutput(SpeechObjectToken)>= #S_OK
         Ret = 1
        EndIf
        SpeechObjectToken\Release()
       EndIf
      EndIf
      SpeechObjectTokens\Release()
     EndIf
    EndIf
    SpeechObjectTokenCategory\Release()
   EndIf
   
  EndIf
 EndIf
 
 Error5:
 ProcedureReturn Ret
EndProcedure

Procedure.l FreeSpeakVoice(Array VoicesSapi.AttributeVoice(1))
 Protected SpeechVoice.ISpeechVoice, a.l
 
 SpeechVoice = VoicesSapi(0)\SpeechVoice
 If SpeechVoice <> 0
  SpeechVoice\Pause()
  SpeechVoice\Release()
  For a = 0 To ArraySize(VoicesSapi())
   VoicesSapi(a)\SpeechVoice = 0
  Next a
  ;Debug "Free InterfaceVoice -> OK"
  ProcedureReturn #True
 EndIf
 
 ProcedureReturn #False
 ;返回 true 或 false
EndProcedure

Procedure.l InitSpeakVoice(Array VoicesSapi.AttributeVoice(1), NameInterface.l)
 Protected ClsidSpVoice.i, RefiidISpeechVoice.i, Clsid.CLSID, Refiid.CLSID, Language.i
 Protected SpeechVoice.ISpeechVoice, SpeechObjectTokens.ISpeechObjectTokens
 Protected SpeechObjectToken.ISpeechObjectToken, SpeechObjectTokenCategory.ISpeechObjectTokenCategory
 Protected LangIDVoice.s, DescriptionVoice.s, Ret.l = -2, Longueur.l, a.l
 Protected NameInterface$, Count.l, Lang.i, Description.i
 ;安全, 为了释放接口 Sapi.SpVoice 如果已经创建
 FreeSpeakVoice(VoicesSapi())
 
 Longueur =  ArraySize(VoicesSapi())
 
 ;
 ; HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices
 
 If NameInterface = 2 ; Speech 11
  NameInterface$ = "Speech.SpVoice" ; HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech Server\v11.0\Voices
  SetInterfaceData(1, 2)
 ElseIf NameInterface = 1 ; Sapi 5
  NameInterface$ = "SAPI.SpVoice" ; HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices
  SetInterfaceData(1, 1)
 Else
  SetInterfaceData(1, 0)
  Ret = -1
  Goto Error
 EndIf
 
 If CLSIDFromProgID_(ConvertToUnicode(NameInterface$), @Clsid.CLSID) < #S_OK
  Goto Error
 EndIf
 
 If CLSIDFromString_(ConvertToUnicode("{269316D8-57BD-11D2-9EEE-00C04F797396}"), @Refiid.CLSID) < #S_OK
  Goto Error
 EndIf
 
 If  CoCreateInstance_(Clsid, #Null, #CLSCTX_INPROC_SERVER, Refiid, @SpeechVoice) >= #S_OK
  Ret = 0
  
  If SpeechVoice\GetVoices(0, 0, @SpeechObjectTokens) >= #S_OK
   If SpeechObjectTokens\get_Count(@Count) >= #S_OK
    ;已安装声音的列表
    For a= 0 To Count-1
     If SpeechObjectTokens\Item(a, @SpeechObjectToken) >= #S_OK
      
      If SpeechObjectToken\GetDescription(0, @Description) >= #S_OK
       If Description <> 0
        DescriptionVoice = PeekS(Description, -1, #PB_Unicode)
        SysFreeString_(Description)
       EndIf
      EndIf
      
      If SpeechObjectToken\GetAttribute("Language", @Lang) >= #S_OK
       If Lang <> 0
        LangIDVoice = PeekS(Lang, -1, #PB_Unicode)
        SysFreeString_(Lang)
       EndIf
      EndIf
      
      If a < (Longueur + 1)
       VoicesSapi(a)\Description = DescriptionVoice
       VoicesSapi(a)\LangID = LangIDVoice
       VoicesSapi(a)\Item = a
       VoicesSapi(a)\Rate = 0
       VoicesSapi(a)\Volume = 100
       VoicesSapi(a)\SpeechVoice = SpeechVoice
       Ret = a + 1
      EndIf
      
      SpeechObjectToken\Release()
     EndIf
    Next
   EndIf
   SpeechObjectTokens\Release()
  EndIf
 EndIf
 
 Error:
 If ClsidSpVoice <> 0
  FreeMemory(ClsidSpVoice)
 EndIf
 If RefiidSpVoice <> 0
  FreeMemory(RefiidSpVoice)
 EndIf
 
 ProcedureReturn Ret
 ;引用值 > 0 表示选票数
 ;如果没有安装声音, 则返回 0 (如果安装运行时没有声音, 则可能)
 ;返回-1 如果 Sapi 5 或没有安装的语音平台11
 ;返回-2 如果 InterfaceName 没有所需的值
EndProcedure

Procedure.l putRate(Rate.l,Array VoicesSapi.AttributeVoice(1))
 Protected SpeechVoice.ISpeechVoice
 
 SpeechVoice = VoicesSapi(0)\SpeechVoice
 If SpeechVoice <> 0
  If SpeechVoice\put_Rate(Rate) >= #S_OK
   ProcedureReturn #True
  EndIf
 EndIf
 ProcedureReturn #False
EndProcedure
Procedure.l putVolume(Volume.l,Array VoicesSapi.AttributeVoice(1))
 Protected SpeechVoice.ISpeechVoice
 
 SpeechVoice = VoicesSapi(0)\SpeechVoice
 If SpeechVoice <> 0
  If SpeechVoice\put_Volume(Volume) >= #S_OK
   ProcedureReturn #True
  EndIf
 EndIf
 ProcedureReturn #False
EndProcedure
Procedure.l PauseSpeak(Array VoicesSapi.AttributeVoice(1))
 Protected SpeechVoice.ISpeechVoice
 
 SpeechVoice = VoicesSapi(0)\SpeechVoice
 If SpeechVoice <> 0
  If SpeechVoice\Pause() >= #S_OK
   ProcedureReturn #True
  EndIf
 EndIf
 
 ProcedureReturn #False
EndProcedure

Procedure.l ResumeSpeak(Array VoicesSapi.AttributeVoice(1))
 Protected SpeechVoice.ISpeechVoice
 
 SpeechVoice = VoicesSapi(0)\SpeechVoice
 If SpeechVoice <> 0
  If SpeechVoice\Resume() >= #S_OK
   ProcedureReturn #True
  EndIf
 EndIf
 
 ProcedureReturn #False
EndProcedure

Procedure.l StatusSpeak(Array VoicesSapi.AttributeVoice(1))
 Protected SpeechVoice.ISpeechVoice, State.l=-1
 Protected SpeechVoiceStatus.ISpeechVoiceStatus
 
 SpeechVoice = VoicesSapi(0)\SpeechVoice
 If SpeechVoice <> 0
  If SpeechVoice\get_Status(@SpeechVoiceStatus) >= #S_OK
   SpeechVoiceStatus\get_RunningState(@State)
   ;Debug "RunningState = " + Str(State)
   SpeechVoiceStatus\Release()
  EndIf
 EndIf
 
 ProcedureReturn State;状态
                      ;如果使用 Sapi 返回2
                      ;返回1如果 Sapi ok
                      ;返回0如果说没有启动第一次
                      ;返回-1 如果函数失败
EndProcedure

Procedure.l getSpeakPosition(Array VoicesSapi.AttributeVoice(1))
 Protected SpeechVoice.ISpeechVoice, Position.i;=-1
 Protected SpeechVoiceStatus.ISpeechVoiceStatus
 
 SpeechVoice = VoicesSapi(0)\SpeechVoice
 If SpeechVoice <> 0
  If SpeechVoice\get_Status(@SpeechVoiceStatus) >= #S_OK
   ;    SpeechVoiceStatus\get_InputWordPosition(@Position)
   ;    Debug position
   SpeechVoiceStatus\get_InputSentencePosition(@Position)
   ;  Debug position
   SpeechVoiceStatus\Release()
  EndIf
 EndIf
 
 ProcedureReturn Position
EndProcedure

Procedure.l CurrentStream(Array VoicesSapi.AttributeVoice(1))
 Protected SpeechVoice.ISpeechVoice, Number.l = -1
 Protected SpeechVoiceStatus.ISpeechVoiceStatus
 
 SpeechVoice = VoicesSapi(0)\SpeechVoice
 If SpeechVoice <> 0
  If SpeechVoice\get_Status(@SpeechVoiceStatus) >= #S_OK
   SpeechVoiceStatus\get_CurrentStreamNumber(@Number)
   SpeechVoiceStatus\Release()
  EndIf
 EndIf
 
 ProcedureReturn Number;编号
                       ;如果0不是当前流, 则返回当前流的 ID
                       ;返回-1 如果函数失败
EndProcedure

Procedure.l SkipStream(Array VoicesSapi.AttributeVoice(1), Item.l)
 Protected SpeechVoice.ISpeechVoice, Sentence.i, ItemSkipped.l
 
 SpeechVoice = VoicesSapi(0)\SpeechVoice
 If SpeechVoice <> 0
  If SpeechVoice\Skip(ConvertToUnicode("SENTENCE"), Item, @ItemSkipped) >= #S_OK
   ProcedureReturn ItemSkipped
  EndIf
 EndIf
 
 ProcedureReturn #False
 ;返回跳过的句子数, 可以是正数还是负数
 ;如果函数失败, 则返回0
EndProcedure

Procedure.l InputSentenceLength(Array VoicesSapi.AttributeVoice(1))
 Protected SpeechVoice.ISpeechVoice, Lenght.l = -1
 Protected SpeechVoiceStatus.ISpeechVoiceStatus
 
 SpeechVoice = VoicesSapi(0)\SpeechVoice
 If SpeechVoice <> 0
  If SpeechVoice\get_Status(@SpeechVoiceStatus) >= #S_OK
   SpeechVoiceStatus\get_InputSentenceLength(@Lenght)
   SpeechVoiceStatus\Release()
  EndIf
 EndIf
 
 ProcedureReturn Lenght;长度
                       ;返回当前句子的文本长度
                       ;返回-1 如果函数失败
EndProcedure

Procedure.l PlaySpeakAsync(Array VoicesSapi.AttributeVoice(1), VoixID.l, Texte.s, *Stream.long = 0, Rate.l = -20, Volume.l = -1)
 Protected SpeechVoice.ISpeechVoice, StreamNumber.l, Ret.l = 0, Ret2.l
 Protected SpeechObjectTokens.ISpeechObjectTokens, SpeechObjectToken.ISpeechObjectToken
 
 
 SpeechVoice = VoicesSapi(0)\SpeechVoice
 If SpeechVoice <> 0
  
  If VoixID > -1 And VoixID <= ArraySize(VoicesSapi())
   If SpeechVoice\GetVoices(0, 0, @SpeechObjectTokens) >= #S_OK
    If SpeechObjectTokens\Item(VoixID, @SpeechObjectToken) >= #S_OK
     If SpeechVoice\put_Voice(SpeechObjectToken) >= #S_OK
      Ret2 = 1
     EndIf
     SpeechObjectToken\Release()
    EndIf
    SpeechObjectTokens\Release()
   EndIf
   
   
   If Volume = -1
    SpeechVoice\put_Volume(VoicesSapi(VoixID)\Volume)
   Else
    If SpeechVoice\put_Volume(Volume) >= #S_OK
     VoicesSapi(VoixID)\Volume = Volume
    EndIf
   EndIf
   
   If Rate = -20
    SpeechVoice\put_Rate(VoicesSapi(VoixID)\Rate)
   Else
    If SpeechVoice\put_Rate(Rate) >= #S_OK
     VoicesSapi(VoixID)\Rate = Rate
    EndIf
   EndIf
   
  EndIf
  
  If SpeechVoice\Speak(Texte, #SVSFlagsAsync, @StreamNumber) >= #S_OK
   If *Stream <> 0
    *Stream\l = StreamNumber
   EndIf
   Ret = Ret2 + 1
  EndIf
  
 EndIf
 
 ProcedureReturn Ret
 ;如果函数成功地使用语音指定索引返回2
 ;如果在未指定语音索引的情况下, 如果指定了声音索引或未找到, 则返回 1 (如果已成功运行)。
 ;如果函数 SpeechVoice\Speak, 则返回0
EndProcedure

Procedure.l StopSpeak(Array VoicesSapi.AttributeVoice(1))
 Protected SpeechVoice.ISpeechVoice, IDVoice.l
 
 SpeechVoice = VoicesSapi(0)\SpeechVoice
 If SpeechVoice <> 0
  
  ;ResumeSpeak 是必要的, 以防前一个状态被暂停
  ;因为否则他将不得不做一个 ResumeSpeak 后, 一个新的发言
  ResumeSpeak(VoicesSapi())
  If SpeechVoice\Speak("", #SVSFPurgeBeforeSpeak, 0) >= #S_OK
   ;Debug "Stop -> OK"
   ProcedureReturn #True
  EndIf
 EndIf
 
 ProcedureReturn #False
EndProcedure
Procedure EditorGadgetCursorPos(Gadget) 
 ; returns relative Position of Cursor 
 
 SendMessage_(GadgetID(Gadget),#EM_EXGETSEL,0,Range.CHARRANGE) 
 ProcedureReturn Range\cpMax 
EndProcedure 
;程序创建的开始

Enumeration
 #Menu
EndEnumeration

Enumeration
 #Window
EndEnumeration

Enumeration
 #TimerDetectSpeakfinish
EndEnumeration

Enumeration
 #TextPitch
 #Pitch
 #Voix
 #LangID
 #Edit
 #TextRate
 #Rate
 #RateArea
 #TextVolume
 #Volume
 #Speak
 #Pause
 #Resume
 #Stop
 #SaveToWav
 #Sentence
 #Sentence1
EndEnumeration

CoInitialize_(0);仅在程序中调用 Coinitialize_ () 一次

#SAPI_5 = 1
#SPEECH_11 = 2

;数组的初始化
;它将在以后调整大小
#LmiteNbVoices = 30
Dim VoicesSapi1.AttributeVoice(#LmiteNbVoices)
; ----------------------------------------------

;用于显示语音的菜单的第一个索引的声明
#DebutIndiceVoix = 10
#DebutIndiceAudio = 100
; ----------------------------------------------
Menu0=#DebutIndiceVoix
Menu1=#DebutIndiceAudio

If OpenWindow(#Window, 200, 200, 400, 520, "SAPI 5 / SPEECH 11 - TTS:text to speech",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
 If CreateMenu(#Menu, WindowID(#Window))
  MenuTitle("select voice")
  TextGadget(#Voix, 10, 5, 280, 20, "voice:")
  TextGadget(#LangID, 290, 5, 100, 20, "LangID:")
  SetGadgetColor(#Voix, #PB_Gadget_FrontColor, RGB(255,0,0))
  SetGadgetColor(#LangID, #PB_Gadget_FrontColor, RGB(255,0,0))
  
  ;InitSpeakVoice 初始化接口 Sapi.SpVoice 并更新参数数组中已安装的声音列表
  ;函数的返回值允许知道我们是否可以得到一个 Sapi.SpVoice 指针和安装声音的数量
  
  
  ;选择, 选择 #SPEECH_11 或 #SAPI_5, 可以测试一个或另一个
  ;如本例所示
  NbVoice = InitSpeakVoice(VoicesSapi1(), #SPEECH_11)
  If NbVoice < 0
   NbVoice =  InitSpeakVoice(VoicesSapi1(), #SAPI_5)
  EndIf
  
  If NbVoice > 0
   ;它调整表的大小与确切的 votes-1 数, 因为从0开始
   ReDim VoicesSapi1(NbVoice-1)
   
   ;Debug "------------------------------"
   ;Debug "Nombre de Voix = " + Str(NbVoice)
   
   For a = 0 To NbVoice -1
    MenuItem( #DebutIndiceVoix + a, VoicesSapi1(a)\Description)
    ;Debug "------------------------------"
    ;Debug "Description = " + VoicesSapi1(a)\Description
    ;Debug "LangID = " + VoicesSapi1(a)\LangID
    ;Debug "------------------------------"
    If VoicesSapi1(a)\Description="Microsoft Simplified Chinese"
    VoiceSapi1 = a:Menu0=#DebutIndiceVoix+a:EndIf
   Next
   ;根据我的测试, 默认的声音是0。
   SetMenuItemState(#Menu, Menu0, #True)
   
   SetGadgetText(#LangID, "LangID:"+ VoicesSapi1(VoiceSapi1)\LangID)
   SetGadgetText(#Voix,"voice:" + VoicesSapi1(VoiceSapi1)\Description)
   
   
  ElseIf NbVoice = 0
   SetGadgetText(#Voix, "voice : 没有声音安装")
   MenuItem( #DebutIndiceVoix, "没有声音安装")
   
  Else
   SetGadgetText(#Voix, "voice : 请安装 SAPI 5")
   MenuItem( #DebutIndiceVoix, "请安装 SAPI 5")
  EndIf
  
  MenuTitle("select device")
  Dim SortieAudio.AttributeAudio(10)
  CountAudioOutput.l = GetAudioOutput(SortieAudio(), @DefautAudio)
  If CountAudioOutput > 0
   For a = 0 To CountAudioOutput - 1
    MenuItem(#DebutIndiceAudio + a, SortieAudio(a)\Description)
   Next a:menu1=#DebutIndiceAudio
   SetMenuItemState(#Menu,menu1 , #True)
  Else
   MenuItem(#DebutIndiceAudio, "错误音频输出")
  EndIf
  
 EndIf
 Volume = 100
 Rate = 0
 Pitch=0
 TextGadget(#TextRate, 10, 25, 90, 20, "-/+ rate = " + Str(Rate))
 ;TextGadget(#RateArea, 100, 25, 290, 20, "( -10 To +10 ), 正常速度 = 0")
 TrackBarGadget(#Rate, 100,  25, 290, 20, 0, 20)
 SetGadgetState(#Rate, Rate + 10)
 
 TextGadget(#TextPitch, 10,45, 90, 20, "-/+ pitch = " + Str(Pitch) )
 TrackBarGadget(#Pitch, 100,45, 290, 20, 0, 20)
 SetGadgetState(#Pitch, Pitch+10)
 TextGadget(#TextVolume, 10, 65, 90, 20, " + volume = " + Str(Volume))
 TrackBarGadget(#Volume, 100,  65, 290, 20, 0, 100)
 SetGadgetState(#Volume, Volume)
 a=520-GetSystemMetrics_(#SM_CYMENU)-30
 EditorGadget(#Edit, 10, 90, 380, a-90-5,#PB_Editor_WordWrap)
 SetGadgetFont(#Edit, LoadFont(0,"宋体",11,#PB_Font_Bold))
 SetGadgetText(#Edit, ~"1 Purebasic 是非常好的! is very nice!\n"+
 ~"2 通过指定一个文本行应占据的额外空间,可用这个函数对文本进行两端对齐处理\n"+
 ~"3 额外空间由行内各个分隔字符分摊。这里的“分隔字符”是由特定的字体定义的,\n"+
 ~"4 函数了解一种字体采用的分隔字符是什么。对文本进行两端对齐排列的时候,通常需要采取的操作步骤如下:\n"+
 ~"5 用于分散额外空间的分隔字符的数量\n")
 
 ButtonGadget(#Speak, 10, a, 50, 20, "Speak")
 ButtonGadget(#Pause, 60, a, 50, 20, "Pause")
 ButtonGadget(#Resume, 110, a, 50, 20, "Resume")
 ButtonGadget(#Stop, 160, a, 50, 20, "Stop")
 ButtonGadget(#Sentence, 215, a, 45, 20,"<<Sent");to prevSentence
 ButtonGadget(#Sentence1, 260, a, 45, 20,"ence>>");To nextSentence

 ButtonGadget(#SaveToWav, 310, a, 80, 20, "Save to Wav")
 
 DisableGadget(#Resume, 1)
 DisableGadget(#Pause, 1)
 DisableGadget(#Stop, 1)
 
 If NbVoice < 1
  DisableGadget(#Speak, 1)
  ;DisableGadget(#Pitch, 1)
 EndIf
 CreatePopupMenu(10)
 MenuItem(0, "cut")
 MenuItem(1, "copy")
 MenuItem(2, "paste")
 MenuItem(3, "select all")
 MenuBar()
 MenuItem(4, "undo")
 MenuBar()
 MenuItem(5, "speakFromCursor");从这里开始播放
 Texte.s = "<pitch middle="+Chr(34)+Str(Pitch)+Chr(34)+"/>" +GetGadgetText(#Edit)
 
 Repeat
  Select WaitWindowEvent()
    
   Case #PB_Event_Menu
    EventMenu = EventMenu()
    Select EventMenu
     Case 0:SendMessage_(GadgetID(#Edit), #WM_CUT, 0, 0)
     Case 1:SendMessage_(GadgetID(#Edit), #WM_COPY, 0, 0)
     Case 2:SendMessage_(GadgetID(#Edit), #WM_PASTE, 0, 0)
     Case 3:SendMessage_(GadgetID(#Edit),#EM_SETSEL, 0, -1)
     Case 4:SendMessage_(GadgetID(#Edit), #EM_UNDO, 0, 0);#WM_UNDO
     Case 5:SetCursorPos_(mouse.POINT\x,mouse\y)
      mouse_event_(#MOUSEEVENTF_LEFTDOWN,0,0,0,0)
      mouse_event_(#MOUSEEVENTF_LEFTUP,0,0,0,0)
      While WindowEvent():Wend
      pos=EditorGadgetCursorPos(#Edit):StopSpeak(VoicesSapi1())
      SendMessage_(GadgetID(#Edit), #EM_SETSEL, pos, pos+4)
      Texte = GetGadgetText(#Edit)
      Texte = "<pitch middle="+Chr(34)+Str(Pitch)+Chr(34)+"/>" +Mid(Texte,pos)
      Gosub Play
     Case #DebutIndiceVoix To (#DebutIndiceVoix + NbVoice-1)
      SetMenuItemState(#Menu, Menu0, #False)
      SetMenuItemState(#Menu, EventMenu, #True):Menu0=EventMenu
      VoiceSapi1 = EventMenu - #DebutIndiceVoix
      SetGadgetText(#Voix, "voice:" + VoicesSapi1(VoiceSapi1)\Description)
      SetGadgetText(#LangID, "LangID:" + VoicesSapi1(VoiceSapi1)\LangID)
      
      
     Case #DebutIndiceAudio To (#DebutIndiceAudio + CountAudioOutput-1)
      SetMenuItemState(#Menu, Menu1, #False)
      SetMenuItemState(#Menu, EventMenu, #True):Menu1=EventMenu
      
      ;Debug "/////////////////////////"
      ;Debug EventMenu - #DebutIndiceAudio
      SetAudioOutput(VoicesSapi1(), EventMenu - #DebutIndiceAudio)
    EndSelect
    
   Case  #PB_Event_Timer
    Select EventTimer()
     Case #TimerDetectSpeakfinish
      ;暂停, StatusSpeak 是 0, 实际上没有状态
      ;目前是2
      ;准备好了1
      ;Debug InputSentenceLength(VoicesSapi1())
      If StatusSpeak(VoicesSapi1()) = 1
       RemoveWindowTimer(#Window, #TimerDetectSpeakfinish)
       DisableGadget(#Speak, 0)
       DisableGadget(#Pitch, 0)
       DisableGadget(#TextPitch,0)
       DisableGadget(#Resume, 1)
       DisableGadget(#Pause, 1)
       DisableGadget(#Stop, 1)
      EndIf
      
    EndSelect
    
   Case #PB_Event_Gadget
    Select EventGadget()
     Case #Pause:RemoveWindowTimer(#Window, #TimerDetectSpeakfinish)
      DisableGadget(#Resume, 0)
      DisableGadget(#Pause, 1)
      ;DisableGadget(#Speak, 1)
      PauseSpeak(VoicesSapi1())
      
     Case #Resume
      DisableGadget(#Resume, 1)
      DisableGadget(#Pause, 0)
      ResumeSpeak(VoicesSapi1())
      AddWindowTimer(#Window, #TimerDetectSpeakfinish, 500)
     Case #Stop:RemoveWindowTimer(#Window, #TimerDetectSpeakfinish)
      DisableGadget(#Speak, 0)
      DisableGadget(#Pitch, 0)
      DisableGadget(#TextPitch,0)
      DisableGadget(#Resume, 1)
      DisableGadget(#Pause, 1)
      DisableGadget(#Stop, 1)
      StopSpeak(VoicesSapi1())
     Case #Volume
      Volume = GetGadgetState(#Volume)
      SetGadgetText(#TextVolume, " + volume = " + Str(Volume))
      putVolume(Volume,VoicesSapi1())
     Case #Rate
      Rate = GetGadgetState(#Rate) - 10
      SetGadgetText(#TextRate, "-/+ rate = " + Str(Rate))
      putRate(Rate,VoicesSapi1())
     Case #Pitch
      Pitch = GetGadgetState(#Pitch) - 10
      SetGadgetText(#TextPitch, "-/+ pitch = " + Str(Pitch)):editcg=0
      Texte.s = "<pitch middle="+Chr(34)+Str(Pitch)+Chr(34)+"/>" +GetGadgetText(#Edit)
     Case #Speak
      Gosub Play
      Case #edit:et=EventType():If et=#PB_EventType_Change:editcg=1
      ElseIf et=#PB_EventType_LostFocus And editcg=1:editcg=0
       Texte.s = "<pitch middle="+Chr(34)+Str(Pitch)+Chr(34)+"/>" +GetGadgetText(#Edit)
      EndIf
     Case #SaveToWav
      Texte.s = GetGadgetText(#Edit)
      File$ = SaveFileRequester("保存为...", "c:\", "*.wav", 0)
      If File$ <> ""
       If LCase(Right(File$, 3)) <> "wav"
        File$ = File$ + ".wav"
       EndIf
       ;Debug File$
       If SaveTextToWav(VoicesSapi1(), VoiceSapi1, Texte, File$, #SPSF_22kHz16BitMono)
        MessageRequester("Info", "文本到 Wav 成功!")
       EndIf
      EndIf
      Case #Sentence,#Sentence1
       If EventGadget()=#Sentence:SkipStream(VoicesSapi1(),-1) 
       Else:SkipStream(VoicesSapi1(),1):EndIf
      pos=getSpeakPosition(VoicesSapi1())
      SendMessage_(GadgetID(#Edit), #EM_SETSEL, pos, pos+4)
    EndSelect
   Case #WM_RBUTTONUP;DOWN
    w.q=WindowMouseX(0)+WindowMouseY(0)<<32:GetCursorPos_(mouse.POINT)
    If ChildWindowFromPoint_(WindowID(0),w)=GadgetID(#edit)
     DisplayPopupMenu(10,WindowID(0))
    EndIf
   Case #PB_Event_CloseWindow
    Quit = 1
    
  EndSelect
 Until Quit = 1
EndIf

;离开前释放资源
;没有效果, 如果已经发布
FreeSpeakVoice(VoicesSapi1())
CoUninitialize_();仅在程序中调用一次

End
play: :If PlaySpeakAsync(VoicesSapi1(), VoiceSapi1, Texte, @Stream, Rate, Volume) > 0
 AddWindowTimer(#Window, #TimerDetectSpeakfinish, 500)
 DisableGadget(#Speak, 1)
 DisableGadget(#Pitch, 1)
 DisableGadget(#TextPitch,1)
 DisableGadget(#Pause, 0)
 DisableGadget(#Stop, 0)
Else
 MessageRequester("信息", "说话功能失败的选择的声音!")
EndIf
Return
Last edited by gurj on Tue Oct 30, 2018 10:32 pm, edited 4 times in total.
my pb for chinese:
http://ataorj.ys168.com
User avatar
gurj
Enthusiast
Enthusiast
Posts: 664
Joined: Thu Jan 22, 2009 3:48 am
Location: china
Contact:

Re: TTS - Sapi 5 (XP et plus) and Speech SDK 11 (Vista et pl

Post by gurj »

update
fixed bugs ,
And For speakFromCursor at Case #WM_RBUTTONUP add :
mouse_event_(#MOUSEEVENTF_LEFTDOWN,0,0,0,0)
mouse_event_(#MOUSEEVENTF_LEFTUP,0,0,0,0)
While WindowEvent():Wend
my pb for chinese:
http://ataorj.ys168.com
User avatar
gurj
Enthusiast
Enthusiast
Posts: 664
Joined: Thu Jan 22, 2009 3:48 am
Location: china
Contact:

Re: TTS - Sapi 5 (XP et plus) and Speech SDK 11 (Vista et pl

Post by gurj »

updated
line988,add StopSpeak(VoicesSapi1())
my pb for chinese:
http://ataorj.ys168.com
User avatar
gurj
Enthusiast
Enthusiast
Posts: 664
Joined: Thu Jan 22, 2009 3:48 am
Location: china
Contact:

Re: TTS - Sapi 5 (XP et plus) and Speech SDK 11 (Vista et pl

Post by gurj »

uptaded for PopupMenu
my pb for chinese:
http://ataorj.ys168.com
zefiro_flashparty
User
User
Posts: 74
Joined: Fri Mar 04, 2005 7:46 pm
Location: argentina

Re: TTS - Sapi 5 (XP et plus) and Speech SDK 11 (Vista et pl

Post by zefiro_flashparty »

nice :D
Amd Vishera fx8350 ,16Gbram, Gtx650 ti, 2gb,Win 10pro. 13tbs. 8)
User avatar
gurj
Enthusiast
Enthusiast
Posts: 664
Joined: Thu Jan 22, 2009 3:48 am
Location: china
Contact:

Re: TTS - Sapi 5 (XP et plus) and Speech SDK 11 (Vista et pl

Post by gurj »

uptaded for SaveTextToWav() to can work,chang line265:

Code: Select all

  If NameInterface = 2
   NameInterface$ = "SAPI.SpFileStream"
  ElseIf NameInterface =  1
   NameInterface$ = "Speech.SpFileStream"
to:

Code: Select all

  If NameInterface = 1
   NameInterface$ = "SAPI.SpFileStream"
  ElseIf NameInterface =  2
   NameInterface$ = "Speech.SpFileStream"
but, VoixID work is not right...
my pb for chinese:
http://ataorj.ys168.com
User avatar
A.D.
User
User
Posts: 98
Joined: Tue Oct 06, 2009 9:11 pm

Re: TTS - Sapi 5 (XP et plus) and Speech SDK 11 (Vista et pl

Post by A.D. »

amazing work, many thanks for it!
Repeat
PureBasic
ForEver
Post Reply