Wednesday 7 April 2021

SAPI (Microsoft Speech API) problems with the IDE

Every few months or so someone sends me an email telling me they've speech-enabled their application with SAPI (the Microsoft Speech API) after having read my old coverage (specifically that for SAPI 5.1) from conferences in 2002 and before. It's always good to hear that stuff you've worked on is being found useful, even long after you did it, in this case frighteningly close to 2 decades ago (Ͼ˳Ͽ)..!!!

Sometimes the communications are asking how to do specific things with SAPI - unfortunately those are typically a dead end, as I haven't used SAPI in anger for a long while.

Sometimes, though, people are stuck on the basics and I was recently contacted by someone with a fairly current version of RAD Studio saying they couldn't get started at all. It turns out that the current version of SAPI, SAPI 5.4, cannot be imported into RAD Studio!

Uh-oh. Time to investigate...

The steps to import SAPI components into the IDE is as follows (and is documented here):

  • Choose Component, Import Component... (as mentioned in the documentation)
  • Select Import a Type Library and press Next
  • Choose the Microsoft Speech Object Library that is defined in sapi.dll:

  • Press Next and choose a target Palette Page:
  • Press Next, select Install to New Package and press Next again
  • Now choose a value for Package name (and optionally for Description) and press Finish:

At this point the package will be created and a type library import unit is added to it and the IDE will try to build the package. Immediately something is flagged up:


Click Yes and the package will start building proper. This is where it all falls apart:



Hmm, is there a massive FUBAR in the type library importer? Sure looks like that could be the case....

However, upon closer inspection the issue actually comes up thanks to the SAPI type library defining its own versions of the already-defined-in-Delphi interfaces IStream and ISequentialStream. In the SAPI versions they have extra methods, references to which then fail to compile thanks to those methods not being imported.

Why are those 'known' interfaces not imported? Well, the idea is to avoid ambiguity with having multiple definitions, but that's not important as... we can override this omission!

In your RAD Studio bin folder (e.g. C:\Program Files (x86)\Embarcadero\Studio\21.0\bin) you will find a file called tlibimp.sym. This is the configuration file for the type library importers (both the one in the IDE we just used and also the command-line utility TLibImp.exe). The content of this configuration file affect the way type libraries get imported to help cover various trouble areas. In this case we need to remove some settings to get the SAPI type library imported.

Here is a part of tlibimp.sym:

;;===================================================================;;
;; Names listed in this section are skipped by the importer         
;; Built-in Interfaces, such as IUnknown and IDispatch are listed
;; here
;;===================================================================;;
[BuiltInInterfaces]
{00020400-0000-0000-C000-000000000046}=IDispatch
{00000000-0000-0000-C000-000000000046}=IUnknown
{0000000C-0000-0000-C000-000000000046}=IStream
{0C733A30-2A1C-11CE-ADE5-00AA0044773D}=ISequentialStream

We need to comment out the IStream and ISequentialStream lines to get a successful import. Once those 2 lines have semicolons inserted at their start we can try again.

Remove the emitted import unit SpeechLib_TLB.pas from the package still open in the IDE, then delete that unit from disk and close the package project.

Now you can go through the steps above again, but this time instead of selecting Install to New Package you select Install to Existing Package. After pressing Next you press Browse and locate the original DCLSAPI54.dpk project file, which by default will have been saved in the default Delphi projects folder (Embarcadero\Studio\Projects within your Documents folder tree).

This time the package will build and you will be told of the component wrappers now installed in the IDE:


If you want to import the SAPI type library from a RAD Studio Command Prompt you can run this command:

tlibimp -P -Yh+ -Yr+ -HpsActiveX C:\WINDOWS\System32\Speech\Common\sapi.dll

Note that the SAPI 5.x sample applications from the 2002 conference paper have been updated and are available along with an updated import package at these URLs:

4 comments:

  1. Looks like its time to do a new tutorial then (for the next 20 years), how to leverage the neural speech api. I think the results are really impressive.

    https://azure.microsoft.com/services/cognitive-services/text-to-speech/

    ReplyDelete
  2. Thanks a lot for the nice article, as always.
    Unfortunately it seems the 10.2 links were broken (speechdemos10.4.2.7z)

    ReplyDelete