TAPI Dial/Send .WAV or SAPI speak command

Alright, I've read lots of questions on here, and lots of white papers over the Web but I cannot find one good example of integrating the two of these things together.  All answers are spoken in theory which I'm having a hard time tieing together.  I can play a .WAV file, I can use the SAPI to speak, I can dial a phone number multiple ways (using MSCOMM, TAPI and actually opening a directory connection to the COM port and sending the ATDT command) but I can't marry the two together.

The only code snippet that I found promising used SPVOICE and SpObjectToken but alas failed on the voice output... This was that snippet:

    Dim v As SpVoice
    Dim t As SpObjectToken
    'create voice object
    Set v = New SpVoice
    'enumerate available audio output devices and set the voice object to the Voice modem
    For Each t In v.GetAudioOutputs
        'I just look for the phrase "odem" to locate the voice modem, but you could use other means
        If InStr(1, t.GetDescription, "odem") Then
            'prevent changing modem's format to default SpVoice format
            v.AllowAudioOutputFormatChangesOnNextSet = False
            Set v.AudioOutput = t
            Exit For
        End If
    'set format of voice object to that compatible with voice modem
    v.AllowAudioOutputFormatChangesOnNextSet = False
    v.AudioOutputStream.Format.Type = SAFT8kHz16BitMono
    'this extra step is needed to force the voice object to recognize the new Format
    Set v.AudioOutputStream = v.AudioOutputStream
    'Now, you use TAPI to answer or place the call using the voice modem, and
    'once connected, the simple Speak method of the voice object will talk to
    'the other party, e.g.:

    ' fails on this line
    v.Speak "Hello, this is a test to see if this is working."    ', SVSFlagsAsync

I also tried this but my noob status with getting device ID's halted my progress here... I felt this one was promising:

    Dim MMSysAudioOut As ISpeechMMSysAudio
    Dim voiceobj As SpVoice
    Set voiceobj = New SpVoice

           'Create SpMMAudioOut object
    Set MMSysAudioOut = New SpMMAudioOut
    'Get the device identifier and set it to audio out
    '  the lineGetID doesn't work here, can't get the call correct
    MMSysAudioOut.DeviceId = lineGetID(0, 0, 0, 0, "", "wave/out")
    'Find the supported wav format and set it to audio out object
    MMSysAudioOut.Format.Type = SAFT8kHz16BitMono
    'Prevent format changes
    voiceobj.AllowAudioOutputFormatChangesOnNextSet = False
    'Set the object as the audio output
    Set voiceobj.AudioOutputStream = MMSysAudioOut
    voiceobj.Speak "test"

I would greatly appreciate any specific coding snippets or help (aside from links to white papers) on how to dial, then send either a .WAV or the SAPI voice (preferably the SAPI voice).

Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Here's how I do it in my project:

I have a form called frmLine, on it I have 2 objects declared:

Public WithEvents Voice As SpeechLib.SpVoice
Public VoiceStream As SpeechLib.SpMMAudioOut

Then I use it here:
Set frmLine.VoiceStream = New SpeechLib.SpMMAudioOut
If lLineWaveOut >= 0 Then
    frmLine.VoiceStream.DeviceId = lLineWaveOut
    frmLine.VoiceStream.DeviceId = frmLine.amtpLine.LineWaveOutID
End If
frmLine.Voice.AllowAudioOutputFormatChangesOnNextSet = False
frmLine.VoiceStream.Format.Type = lapLineAudioProperties.OutputQuality
Set frmLine.Voice.AudioOutputStream = frmLine.VoiceStream
If LenB(sTTSVoice) > 0 Then
    Set frmLine.Voice.Voice = frmLine.Voice.GetVoices.Item(GetVoiceIndex(sTTSVoice))
    Set frmLine.Voice.Voice = frmLine.Voice.GetVoices.Item(0)
End If
frmLine.Voice.Rate = lSpeechRate
frmLine.Voice.Volume = lVolume
frmLine.Voice.AlertBoundary = SVEPhoneme
frmLine.Voice.Speak sTextToSpeak, SVSFIsXML + SVSFPurgeBeforeSpeak + SVSFlagsAsync
This is done after the call has been established.  For me, the client calls into the system so I just react when I answer the call.  In your case, just use this code after you have dialed and established that someone has answered.
By default:

lapLineAudioProperties.OutputQuality = SAFT8kHz16BitMono
Your Guide to Achieving IT Business Success

The IT Service Excellence Tool Kit has best practices to keep your clients happy and business booming. Inside, you’ll find everything you need to increase client satisfaction and retention, become more competitive, and increase your overall success.

IUFITSAuthor Commented:
Where are you getting the lLineWaveOut here?  Currently, after I dial-up and connect whenever I get it to say something with the voice, it comes through the speakers and not the modem.  I'm assume that's a fluke since lLineWaveOut's undefined value of 0 must be the speaker setting.

If lLineWaveOut >= 0 Then
    frmLine.VoiceStream.DeviceId = lLineWaveOut
    frmLine.VoiceStream.DeviceId = frmLine.amtpLine.LineWaveOutID
End If
It's the index of the enumerated speech devices.  In my program I let the user select which device to use as output.  Here's an example of how you enumerate them:

Dim T As SpeechLib.SpObjectToken
Dim sAudio As String
Set T = Voice.AudioOutput
sCurrentAudio = T.GetDescription
For Each T In Voice.GetAudioOutputs
    sAudio = T.GetDescription
    If sAudio = sCurrentAudio Then
        sAudio = sAudio & "  (Current)  "
    End If
    cmbAudioDevices.AddItem sAudio
I use the amTapiPro and amWavePro from Allen Martin for all the TAPI, I didn't feel like writing my own TAPI library, theirs is really complete, really easy, and not too badly priced (www.allen-martin-inc.com).  That's the type of object that amtpLine is.  It makes writing a TAPI based app really easy.
If you download and install the trial version of amTAPI and amWave, you can use my slapped together sample testing application so you can see how a lot of it is done.


Let me know when you've downloaded the file so I can remove it from our server.  :)

The code is a just slapped together, it's just a tester application so don't expect to see the prettiest, most professional code in there, it's a little sloppy.  ;)
It's a self-extracting, virus scanned file so don't be scared.  ;)
IUFITSAuthor Commented:
Done.  ;)
IUFITSAuthor Commented:
I'm going to run this when I get home also, I noticed that when I remoted desktop the number of devices I have changed and the only output device available was "Microsoft RDP" which I can only assume is a special remote desktop audio setting.
Correct.  You need to run this via the local machine, not RDP'd.  MS does some hardware mapping stuff that will screw with it.  Let me know how it goes.  :)
IUFITSAuthor Commented:
Alright, I used your project but replaced the dial section with my dialing code since I didn't have the controls installed on this machine that you used.  I still receive this error once I change to the modem input instead of the sound blaster card:

Method 'Type' obj object 'ISpeechAudioFormat' failed  Error Number -2147201021

I used a seperate VB answering machine project to send a .WAV file over the phone line so I know the modem is at least capable (which I was beginning to doubt).  Any ideas on the above?  The above was setting the format type...  in another project I was working on I could set the type but got a failed error on the actual speak section.

Going through the sound card, the speaking works fine.

On what line does this error occur?  Can you post the code snippet causing the error?  Also, make sure that your modem supports voice.  If it's just a regular data/fax modem, it won't work.  The best 2 I've found are the Zoom 2949 and the USR 5610B, but NOT 5610A.  They work really well in TAPI/SAPI applications unless you're willing to spend 500 or more for a Dialogic D/4 PCI or Brooktrout board.
IUFITSAuthor Commented:
The modem is a Conexant D850 56K V.9x DFVc Modem.  I was under the assumption it had telephony capabilities but I could be wrong.  It is capable of sending the sound from a .WAV file over the phone (I've got an answering machine VB application that does it).

1.)  Am I wrong in assuming that if it can send the sound of a .WAV file that it should be able to do this also?

2.)  Here is the line it failed on in the "Hear It" button with the "Modem #0 Line Playback" selected:

VoiceStream.Format.Type = SAFT11kHz8BitMono
IUFITSAuthor Commented:
If I can't get the SAPI to actually speak over the modem, I guess I could use it to write out a .WAV file and then send that .WAV file over the phone line... would prefer not to do it that way but I guess it's not that bad of a work around.
For a regular voice modem the format can't be anything but: SAFT8kHz16BitMono.  Nothing else will work.  Also, with Microsoft voices, I had a problem getting them to actually speak over the phone at SAFT8kHz16BitMono.  I had to have it speak and record the speech as a SAFT16kHz16BitMono wave file and then open the file, extract the header information and average out every two bits to create the SAFT8kHz16BitMono file and then play it.  There should be some rem'd out code in that project that shows you how (I believe it's called FixAudio or FixWaveFile, or something like that).  Also, sometimes the system puts the index of the audio devices in the wrong order, so beware of that.  Sometimes, depending on the modem and computer, I had to select the sound card as the audio output device in order for it to play over the modem.  That's why in my program I added the ability to select the audio output device in the program's modem configuration area, so no matter what it was for that system it could be configured properly.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
IUFITSAuthor Commented:
I found the following answering machine code also which uses TAPI and has a ton of stuff in it.  Thought I'd share the link since it was a huge help along with the advice here:

IUFITSAuthor Commented:
Thanks for the help codeconqueror!
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic Classic

From novice to tech pro — start learning today.