Re: Creating a speaking tapi application



Hi Matthias

I am able to record incoming calls using filerecordingterminal and
mediacontrol in tapi3.
Now I want to play that audio with speaker instead of recording.
I tried this in the same way i did recording but the application
crashes once i run the application. Can u please suggest how to play
audio in real time in tapi3.

Below is the relevant code i am using.

if (stream.MediaType == TapiConstants.TAPIMEDIATYPE_AUDIO &&
stream.Direction ==
TERMINAL_DIRECTION.TD_CAPTURE )
{
ITTerminalSupport termsupport =
(ITTerminalSupport)ia[line]; //ia[line] is the address
firstplaybackterminal =
termsupport.CreateTerminal(TapiConstants.CLSID_String_MediaStreamTerminal,

TapiConstants.TAPIMEDIATYPE_AUDIO, TERMINAL_DIRECTION.TD_CAPTURE);

stream.SelectTerminal(firstplaybackterminal);
break;
}
//bc2 is itbasiccallcontrol2
bc2.SelectTerminalOnCall(firstplaybackterminal);

bc2.Answer();
stream.StartStream();




Amit Bharadwaj

Matthias Moetje [MVP] wrote:

Atlas,

the "default static terminal" is (well, not by definition but this
is the way this is implemented by all known MSPs) equivalent
to the default audio playback and recording device (usually,
soundcard's wave playback and record).
The purpose of selecting the default static terminal (or other
static terminals in case you have more than one audio device,
like multi-channel soundcard or a bluetoth audio implementation
for using a headset) is to be able to make an audio converation
through these sound devices.
It is called terminals because when we talk about video streams
(or even other types of data streams like application sharing,
whiteboard, etc) the capture terminal corresponds to a video
capture device and the default render terminal corresponds
to a window that displays the video.

There are other types of terminals like the media streaming
terminal which provides DirectShow interfaces to get at the
data or the file terminals (TAPI3.1) which allow you to record
and playback from/to media files.
You can even implement your own custom "pluggable" terminals..

Regarding the other topic: it is much easier to buy some better
hardware than trying to do audio analysis in order to check if
the call was picked up by the remote party. If you want to go
this route, I'd suggest to use the media streaming terminal which
lets' you directly get at the samples for analysis.

Most TSPs alway have audio devices associated with it so that
you could also use the wave API to get at the samples, but some
TSPs (like the H.323 TSP, the IPConf TSP, the Unimodem TSP
in full-duplex mode and our SIP TSP) don't have audio devices and
you can only use TAPI3 terminals.

Best regards,

Matthias Moetje
-------------------------------------
TERASENS GmbH
Augustenstraße 24
80333 Munich, GERMANY
-------------------------------------
Fon: +49 89 143370-0
Fax: +49 89 143370-22
e-mail: moetje at terasens dot com
www: www.terasens.com
-------------------------------------

"atlasgp" <atlasgp@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:07451C26-5B3C-44B4-BE05-6A4088845581@xxxxxxxxxxxxxxxx
Thank you Matthias, you were correct. I took your first approach as this
was
the most straightfoward for testing purposes and it worked, however, I
will
investigate the second approach as well as my goal is to hopefully
implement./learn the best solution.

If you could endulge me for a moment, while I haven't had a difficult time
understanding the tapi interfaces thus far, I'm unclear as far as the
'default terminal' selection, or it's meaning in the context of the sample
code. I infered from your comments that by doing this action ( selecting
a
terminal for the stream ) I created a state in which the wave device is in
a
blocked state since it is in use, however my knowdege on these mechanisms
is
limited at this time. Can you recommend for me some high level
documentation
so that I can get a 'big picture' of how the tapi and wave device are
working
in conjunction and then I can start digging into the lower level workings
from that point?

Also, and perhaps this just requires a better TSP, I realize that my tapi
events are very limited at this time since a normal voice modem doesn't
have
full tapi event implementation. However, it was suggested to me at an
earlier date that perhaps I could monitor the incoming stream and attempt
to
determine when the call has been picked up at the other end. To the
point, I
need to investigate in what ways it can be determined that a call is
picked
up at the other end.

Thank you very much for your assistance.



"Matthias Moetje [MVP]" wrote:

Atlas,

your code does not work because you select the default
static terminals on the audio streams. This has two effects:

- it will make the wave devices used/occupied by the Wave MSP
- this will make the behaviour indefinite if the capture or the
render stream is started (the other stream will fail because 99%
of all modems are only half-duplex)

To make this work you need to do one of the following:

- Don't even select any terminal on any stream and playback
audio through the wave API (using the wave device returned
by lineGetID)

- Don't use the wave API but instead use TAPI3 media streaming
only. This will require a bit of work. You will need to select a
media streaming terminal on the capture stream and stop the render
stream before the call is connected. Don't select anythin on the
render stream. Then you'll need the STCustomStream library from
the SAPI SDK samples which will provide an interface between the
media streaming terminal and SAPI's custom audio stream object.


Best regards,

Matthias Moetje
-------------------------------------
TERASENS GmbH
Augustenstraße 24
80333 Munich, GERMANY
-------------------------------------
Fon: +49 89 143370-0
Fax: +49 89 143370-22
e-mail: moetje at terasens dot com
www: www.terasens.com
-------------------------------------

"atlasgp" <atlasgp@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote in message
news:F5C7AD00-6AE6-451B-98BA-62420DEEC818@xxxxxxxxxxxxxxxx
Hi, I'm new to the tapi enviroment and I'm attempting to create an
application which can place a call and speak something over the call
via a
stream. Based on the core sdk samples and the Microsoft Speech SDK
samples I
wrote a test application which freezes when I attempt to send a spoken
response over a calls stream. This code is based of the
simpletelephony
sample in the speech sdk, howevr their example is done in the context
of
answering a call which retrieves the call interface from a tapi event
call
back. My example creates a call and uses the call interface
immediately,
get's an interface to the calls stream, and attemps to use a voice to
stream
sound over the phone connection. The application freezes when calling
the
voice's speak method. My MSP/TSP is a simple 56k voice modem which I
have
used to build and test the sdk samples, however I'm willing to upgrade
to
a
better 'test' modem if need be.

1 ) can anyone recommend documentation/source code that I can go over
to
help create a simple application which can stream a voice over a call?

2 ) Any suggestions where I can start trouble shooting this problem?

Thxs.


void CQuickTestDlg::OnOK()
{
// TODO: Add extra validation here
CComPtr<ISpRecognizer> cpRecognizer;
CComPtr<ISpRecoContext> cpRecoCtxt;
CComPtr<ISpRecoGrammar> cpDictGrammar;
CComPtr<ISpVoice> cpOutgoingVoice;
CComPtr<ISpMMSysAudio> cpMMSysAudioOut;
CComPtr<ITAddress> cpAddress;
ITTAPI* pTapi;
ITBasicCallControl* pCall;

IConnectionPointContainer* pCPC;
IConnectionPoint* pCP;

HRESULT hr ( S_OK );

// Create a voice for us to use to speak on our tapi stream...
hr = cpRecognizer.CoCreateInstance( CLSID_SpInprocRecognizer );
hr = cpRecognizer->CreateRecoContext( &cpRecoCtxt );
const ULONGLONG ullInterest = SPFEI(SPEI_PHRASE_START) |
SPFEI(SPEI_RECOGNITION) |
SPFEI(SPEI_FALSE_RECOGNITION);
hr = cpRecoCtxt->SetInterest( ullInterest, ullInterest );
hr = cpRecoCtxt->SetAudioOptions( SPAO_RETAIN_AUDIO, NULL, NULL );
hr = cpRecoCtxt->CreateGrammar( 0, &cpDictGrammar );
hr = cpDictGrammar->LoadDictation( NULL, SPLO_STATIC );
hr = cpRecoCtxt->GetVoice( &cpOutgoingVoice );


hr = CoCreateInstance(
CLSID_TAPI,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITTAPI,
(LPVOID *)&pTapi
);

// Intialize Tapi
hr = pTapi->Initialize();
hr = pTapi->QueryInterface ( IID_IConnectionPointContainer, (void
**)&pCPC );

// Get connection point for tapi events
hr = pCPC->FindConnectionPoint( IID_ITTAPIEventNotification,
&pCP );
pCPC->Release();
DWORD dwCookie;

// For this example, the dialog inherits from ITTAPIEventNotification
interface and
// implements Event method for tapi callback, thus we advis passing
this
ptr
hr = pCP->Advise ( this, &dwCookie );
pCP->Release();

// Set our event filters, per example
hr = pTapi->put_EventFilter(TE_CALLNOTIFICATION | TE_CALLSTATE);

CComPtr < IEnumAddress > pEnumAddress;
CComPtr < ITAddress > pAddress;
CComPtr < ITAddressCapabilities > pAddressCaps;
CComBSTR AddressName;
CComBSTR bstrAddressToCall ( SOME_PHONE_NUMBER );
long lType ( 0 );
DWORD dwAddressType ( 1 );

// Enumerate current machines address and find one that supports audio
hr = pTapi->EnumerateAddresses( &pEnumAddress );

if ( FAILED(hr) )
{
return;
}

while ( SUCCEEDED(hr) )
{
// reset address
pAddress = NULL;

// get the next address
hr = pEnumAddress->Next( 1, &pAddress, NULL );

if (S_OK != hr)
{
break;
}


// Get ITAddressCapabilities interface
hr = pAddress->QueryInterface(IID_ITAddressCapabilities,
(void**)&pAddressCaps);

if ( SUCCEEDED(hr) )
{

// Get address capabilities
hr = pAddressCaps->get_AddressCapability( AC_ADDRESSTYPES,
&lType );

if ( SUCCEEDED(hr) )
{
// is the type we are looking for?
if ( dwAddressType & lType )
{
// does it support audio?
VARIANT_BOOL bSupport = VARIANT_FALSE;
CComPtr < ITMediaSupport > pMediaSupport;

if ( SUCCEEDED( pAddress->QueryInterface( IID_ITMediaSupport,
(void **)&pMediaSupport ) ) )
{
// does it support this media type?
pMediaSupport->QueryMediaType( TAPIMEDIATYPE_AUDIO, &bSupport );
}


if ( bSupport == VARIANT_TRUE )
{
// does it have a name?
hr = pAddress->get_AddressName(&AddressName);
if ( SUCCEEDED( hr ) )
{
// found it
break;
}
}
}
}
}
} // end while loop

long lMediaTypes = TAPIMEDIATYPE_AUDIO;
// create a call
pAddress->CreateCall( bstrAddressToCall,
dwAddressType,
lMediaTypes,
&pCall);

//
// get the ITStreamControl interface for this call
//
CComPtr< ITStreamControl> pStreamControl;
hr = pCall ->QueryInterface(IID_ITStreamControl,
(void **) &pStreamControl);

if ( SUCCEEDED(hr) )
{
//
// enumerate the streams
//

CComPtr < IEnumStream > pEnumStreams;

hr = pStreamControl->EnumerateStreams(&pEnumStreams);

if ( SUCCEEDED(hr) )
{
//
// for each stream
//

CComPtr < ITStream > pStream;

while ( S_OK == pEnumStreams->Next(1, &pStream, NULL) )
{
CComPtr < ITTerminal > pTerminal;

//
// Find out the media type and direction of this
stream,
// and create the default terminal for this media type
and
// direction.
//
long lMediaType;
TERMINAL_DIRECTION dir;
hr = pStream->get_MediaType( &lMediaType );
if ( FAILED(hr) ) return;

hr = pStream->get_Direction( &dir );
if ( FAILED(hr) ) return;

CComPtr < ITTerminalSupport > pTerminalSupport;

hr = pAddress->QueryInterface( IID_ITTerminalSupport,
(void **)&pTerminalSupport);

if ( SUCCEEDED(hr) )
{
//
// get the default terminal for this MediaType and direction
//
hr = pTerminalSupport->GetDefaultStaticTerminal(lMediaType,
dir,
&pTerminal);
}

if ( SUCCEEDED(hr) )
{
//
// Select the terminal on the stream.
//
hr = pStream->SelectTerminal(pTerminal);

}
pStream = NULL;
}
}
}

// make the call
hr = pCall->Connect( VARIANT_TRUE );

Sleep ( 2000 );

// speak something
ITLegacyCallMediaControl *pLegacyCallMediaControl;
hr = pCall->QueryInterface( IID_ITLegacyCallMediaControl,


(void**)&pLegacyCallMediaControl );
// Set the audio for the SAPI objects so that the call
// can be handled
// Get the device ID from ITLegacyCallMediaControl::GetID()
UINT *puDeviceID;
BSTR bstrWavOut = ::SysAllocString( L"wave/out" );

DWORD dwSize = sizeof( puDeviceID );
hr = pLegacyCallMediaControl->GetID( bstrWavOut, &dwSize, (BYTE**)
&puDeviceID );

::SysFreeString ( bstrWavOut );

// Find out what, if any, formats are supported
GUID guidWave = SPDFID_WaveFormatEx;
WAVEFORMATEX *pWaveFormatEx = NULL;

.



Relevant Pages

  • Re: Creating a speaking tapi application
    ... Please suggest how to use terminals and streams to make real time ... Now I want to play that audio with speaker instead of recording. ... Matthias Moetje wrote: ... render stream is started (the other stream will fail because 99% ...
    (microsoft.public.win32.programmer.tapi)
  • Re: Creating a speaking tapi application
    ... Please suggest how to use terminals and streams to make real time ... Now I want to play that audio with speaker instead of recording. ... earlier date that perhaps I could monitor the incoming stream and attempt ... CComPtr pEnumAddress; ...
    (microsoft.public.win32.programmer.tapi)
  • Re: Creating a speaking tapi application
    ... "841712 - Telephony Application Programming Interface ... you need to stop one stream and start the other stream ... Please suggest how to use terminals and streams to make real time ... Now I want to play that audio with speaker instead of recording. ...
    (microsoft.public.win32.programmer.tapi)
  • Re: Creating a speaking tapi application
    ... static terminals in case you have more than one audio device, ... It is called terminals because when we talk about video streams ... earlier date that perhaps I could monitor the incoming stream and attempt ... CComPtr pEnumAddress; ...
    (microsoft.public.win32.programmer.tapi)
  • Re: Creating a speaking tapi application
    ... so that I can get a 'big picture' of how the tapi and wave device are working ... earlier date that perhaps I could monitor the incoming stream and attempt to ... static terminals on the audio streams. ... CComPtr pEnumAddress; ...
    (microsoft.public.win32.programmer.tapi)

Loading