Can't pass a whole file for the speech

Just starting out? Need help? Post your questions and find answers here.
Fiwip
User
User
Posts: 27
Joined: Tue Feb 24, 2004 2:42 pm

Can't pass a whole file for the speech

Post by Fiwip »

Hello,

Still trying to make my computer speaking.

The example below mixing Danilo and FlowHimself work should be able to speech a file.txt choosen in my directory.

The answer is this is reading the adress of the file "C: ......... file.txt" !

Code: Select all

CurrentDirectory.s

Interface ISpNotifySource Extends IUnknown 
  SetNotifySink(a) 
  SetNotifyWindowMessage(a,b,c,d) 
  SetNotifyCallbackFunction(a,b,c) 
  SetNotifyCallbackInterface(a,b,c) 
  SetNotifyWin32Event() 
  WaitForNotifyEvent(a)
  GetNotifyEventHandle() 
EndInterface 

Interface ISpEventSource Extends ISpNotifySource 
  SetInterest(a,b) 
  GetEvents(a,b,c) 
  GetInfo(a) 
EndInterface 

Interface iSPVoice Extends ISpEventSource 
  SetOutput(a,b) 
  GetOutputObjectToken(a) 
  GetOutputStream(a) 
  Pause() 
  Resume() 
  SetVoice(a) 
  GetVoice(a) 
  Speak(a,b,c) 
  SpeakStream(a,b,c) 
  GetStatus(a,b) 
  Skip(a,b,c) 
  SetPriority(a) 
  GetPriority(a) 
  SetAlertBoundary(a) 
  GetAlertBoundary(a) 
  SetRate(a) 
  GetRate(a) 
  SetVolume(a) 
  GetVolume(a) 
  WaitUntilDone(a) 
  SetSyncSpeakTimeout(a) 
  GetSyncSpeakTimeout(a) 
  SpeakCompleteEvent() 
  IsUISupported(a,b,c,d) 
  DisplayUI(a,b,c,d,e) 
EndInterface 

#CLSCTX_INPROC_SERVER  = $1 
#CLSCTX_INPROC_HANDLER = $2 
#CLSCTX_LOCAL_SERVER   = $4 
#CLSCTX_REMOTE_SERVER  = $10 
#CLSCTX_ALL = (#CLSCTX_INPROC_SERVER|#CLSCTX_INPROC_HANDLER|#CLSCTX_LOCAL_SERVER|#CLSCTX_REMOTE_SERVER) 

Global VoiceObject.iSPVoice 

Procedure Speak(Filename.s)
  CallDebugger
  If ReadFile(0, Filename) 
    BufferLength = Lof()
    Debug BufferLength
    *Buffer = AllocateMemory(BufferLength)
    Debug *Buffer
    ReadData(*Buffer, BufferLength) 
    CloseFile(0) 
  EndIf ;will normally load all the file's content in a buffer which address is *Buffer
  MultiByteToWideChar_(#CP_ACP ,0,Filename,-1,*Buffer, BufferLength) 
  VoiceObject\Speak(*Buffer,0,0)
  DisableDebugger
EndProcedure

hWnd.l = OpenWindow(0, 200, 200, WindowXSize, WindowYSize, #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_TitleBar, "MyWindow")
If hWnd
  AddKeyboardShortcut(0, #PB_Shortcut_Escape, 99)
  LoadFont(0, "Verdana", 10)
  FontID.l = FontID()
  If CreateMenu(0, WindowID())
    OpenSubMenu("General")
    MenuItem(11, "Open file")
    MenuItem(99, "Quit")
    CloseSubMenu()
  EndIf
  If CreateStatusBar(0, WindowID())
    StatusBarText(0, 0, "Idle ...", 0)
  EndIf
  If CreateGadgetList(WindowID())
    SetGadgetFont(#PB_Default,FontID)
    TextGadget(100, 10, 10, WindowXSize - 20, WindowYSize - 40, "")
    SetGadgetText(100, "Select a file to process ...")
  EndIf

  Repeat
    Select WaitWindowEvent()
      Case #PB_EventCloseWindow
        Quit = #True
      Case #PB_EventMenu
        Select EventMenuID()
          Case 11
            Filename.s = OpenFileRequester("Select a file", CurrentDirectory + "\" + "*.txt", "Text files|*.txt|All files|*.*", 0, #PB_Requester_MultiSelection)
            
            CoInitialize_(0) 
            If CoCreateInstance_(?CLSID_SpVoice, 0, #CLSCTX_ALL, ?IID_ISpVoice, @VoiceObject.iSPVoice) = 0 
              VoiceObject\SetVolume(100) 
              VoiceObject\SetRate(0)
              Speak(Filename)
            Else 
              MessageRequester("ERROR","MS SPEECH API not installed",0) 
            EndIf 
            
          Case 99
            Quit = #True
        EndSelect
    EndSelect
  Until Quit
EndIf
End

DataSection 
CLSID_SpVoice: 
    ;96749377-3391-11D2-9EE3-00C04F797396 
Data.l $96749377 
Data.w $3391,$11D2 
Data.b $9E,$E3,$00,$C0,$4F,$79,$73,$96 
IID_ISpVoice: 
    ;6C44DF74-72B9-4992-A1EC-EF996E0422D4 
Data.l $6C44DF74 
Data.w $72B9,$4992 
Data.b $A1,$EC,$EF,$99,$6E,$04,$22,$D4 
EndDataSection 
Can somebody tell me where I am wrong ? ie how to get correctly the whole file choosen for a working speech ?

Thanks in advance,

Fiwip
El_Choni
TailBite Expert
TailBite Expert
Posts: 1007
Joined: Fri Apr 25, 2003 6:09 pm
Location: Spain

Post by El_Choni »

Hi, try changing this:

Code: Select all

MultiByteToWideChar_(#CP_ACP ,0,Filename,-1,*Buffer, BufferLength) 
To this:

Code: Select all

  *BufferW = AllocateMemory(BufferLength*2)
  MultiByteToWideChar_(#CP_ACP, 0, *Buffer, BufferLength, *BufferW, BufferLength)
  FreeMemory(*Buffer)
  VoiceObject\Speak(*BufferW, 0, 0)
  FreeMemory(*BufferW)
Regards,
El_Choni
Fiwip
User
User
Posts: 27
Joined: Tue Feb 24, 2004 2:42 pm

Post by Fiwip »

El_Choni,

Thanks, it works fine now.

The error was not where I thought it was (using badly var Filename) , I should have created a new buffer for byte to wide conversion.

But, even after reading the "MultiByteToWideChar " in the Win32 Programmer's Reference Help, I am not sure to understand clearly why we need to have:

*Buffer = AllocateMemory(BufferLength) then
*BufferW = AllocateMemory(BufferLength*2) where BufferLengh is * 2

Is it correct to say that to convert from Byte to Wide (Unicode) we need twice the size of the buffer used for the one in bytes ?

Anyhow, thanks again

Fiwip
El_Choni
TailBite Expert
TailBite Expert
Posts: 1007
Joined: Fri Apr 25, 2003 6:09 pm
Location: Spain

Post by El_Choni »

Yes, each Unicode character takes two bytes instead of one (ASCII), including the tertminating zero, which takes two zeroed bytes.

Regards,
El_Choni
Post Reply