Native record with inband silence and DTMF detection

Use the following procedure to implement native record with inband silence detection (or DTMF detection without silence detection) for the CG boards.

To implement native record functionality with inband silence detection or DTMF detection, the application performs the following tasks:

The following illustration shows an overview of the native record mechanism with voice decoding enabled:

Sample procedure

Applications use functions from the following NaturalAccess resources to implement native record functionality with inband silence detection or DTMF detection:

The following procedure shows the function sequence used to implement a typical native record operation with decoding on CG boards:

Step

Action

1

ctaCreateQueue creates a NaturalAccess event queue.

ctaCreateQueue (&queuehd)

2

ctaCreateContext creates a NaturalAccess context for the audio channel.

ctaCreateContext (queuehd, &ctahd)

3

ctaOpenServices opens the ADI service on the context.

When using ctaOpenServices, the application must specify the following:

  • Set the svclist.mvipaddr.mode parameter to ADI_VOICE_DUPLEX to allocate DSP resources for the channel on the CG board.

  • Set the svclist.mvipaddr.stream parameter to 0 and the svclist.mvipaddr.timeslot parameter to a unique and valid entry. For more information, refer to the Dialogic® NaturalAccess™ Software Developer’s Manual.

 

ctaOpenServices (ctahd, svclist, nsvcs)

4

adiStartProtocol starts the NOCC protocol on the audio channel and enables silence detection on the audio channel.

adiStartProtocol (ctahd, "nocc")

5

swiOpenSwitch opens a switching device for the context and returns a switch handle (swihd).

swiOpenSwitch (ctahd, "cg6ksw", board, 0x0, &swihd)

6

ctaCreateContext creates a NaturalAccess context for the MSPP channel.

ctaCreateContext (queuehd, &msphd)

7

ctaOpenServices opens the MSPP API on the context.

ctaOpenServices (ctahd, svclist, nsvcs)

8

mspCreateEndpoint creates an audio DS0 endpoint and returns an endpoint handle (ephd).

mspCreateEndpoint (ctahd, mspaddrstruct, mspparmstruct, &ds0ephd)

9

mspCreateChannel creates a full duplex or voice decoding channel.

mspCreateChannel (ctahd, chnladdr, chnlparms, &chanhd)

10

mspCreateEndpoint creates an audio RTP endpoint and returns an endpoint handle.

mspCreateEndpoint (ctahd, mspaddrstruct, mspparmstruct, &rtpephd)

11

mspConnect connects the RTP and DS0 endpoints with the voice channel.

mspConnect (rtpephd, chanhd, ds0ephd)

12

swiMakeConnection, with the swihd returned by swiOpenSwitch, connects the MSPP DS0 output to the ADI audio channel input and vice versa. When using swiMakeConnection, the application specifies the stream and timeslot used to create the ADI port and the stream and timeslot used to create the DS0 endpoint.

swiMakeConnection (swihd, fusion_ds0, adi_ds0, 1)

13

mspGetFilterHandle retrieves the filter identifier (fltID) associated with the MSPP record channel.

mspGetFilterHandle (chanhd, MSP_FILTER_JITTER, &fltID)

14

adiSetNativeInfo, with both the context handle of the ADI port and the fltID returned by mspGetFilterHandle, sets NMS native record parameters.

adiSetNativeInfo (ctahd, fltID, NULL, natpr_parms)

15

adiRecordToMemory starts recording a message.

adiRecordToMemory (ctahd, buf, bufsize, rec_param)

16

adiStopRecording stops recording the audio portion of the message.

adiStopRecording (ctahd)

Example

The following example shows how to perform a native record operation that supports ADI silence and DTMF detection on CG boards:

ret = ctaCreateQueue( NULL, 0, &hCtaQueueHd );
ret = ctaCreateContext( hCtaQueueHd, 0, "Record", &ctahd );

ServiceCount = 2;
ServDesc[0].name.svcname       = "ADI";
ServDesc[0].name.svcmgrname    = "ADIMGR";
ServDesc[0].mvipaddr.mode      = ADI_VOICE_DUPLEX;
ServDesc[0].mvipaddr.stream    = 0;
ServDesc[0].mvipaddr.timeslot  = record_timeslot;
ServDesc[1].name.svcname       = "MSP";
ServDesc[1].name.svcmgrname    = "MSPMGR";

ret = ctaOpenServices( ctahd, ServDesc, ServiceCount );
ret = WaitForSpecificEvent( CTAEVN_OPEN_SERVICES_DONE, &Event );

// IP Channel Initialization
MSPHD     ds0_ephd;
MSPHD     rtp_ephd;

// Create and init RTP endpoint
MSP_ENDPOINT_ADDR      rtpaddr    = {0};
MSP_ENDPOINT_PARAMETER rtp_params = {0};

rtpaddr.size    = sizeof(MSP_ENDPOINT_ADDR);
rtpaddr.eEpType = MSP_ENDPOINT_RTPFDX;
rtpaddr.nBoard  = g_Board;
...
mspCreateEndpoint
( ctaHd, &rtpaddr, &rtp_params, &rtp_ephd );
if (! WaitForSpecificEvent(MSPEVN_CREATE_ENDPOINT_DONE, &Event, 5000))
{
printf("Failed waiting for MSPEVN_CREATE_ENDPOINT_DONE (RTP)");
return FAILURE;
}

// create mspp DS0 endpoint
MSP_ENDPOINT_ADDR     ds0addr      = {0};
ds0addr.eEpType          = MSP_ENDPOINT_DS0;
ds0addr.nBoard           = board;
ds0addr.size             = sizeof(MSP_ENDPOINT_DS0);
ds0addr.EP.DS0.nTimeslot = record_timeslot;
MSP_ENDPOINT_PARAMETER ds0parms    = {0};
ds0parms.size            = sizeof(DS0_ENDPOINT_PARMS);
ds0parms.eParmType       = MSP_ENDPOINT_DS0;
ds0parms.EP.DS0.media    = MSP_VOICE;
mspCreateEndpoint
( ctaHd, &ds0addr, &ds0parms, &ds0_ephd );
if (! WaitForSpecificEvent(MSPEVN_CREATE_ENDPOINT_DONE, &Event, 5000))
{
printf("Failed waiting for MSPEVN_CREATE_ENDPOINT_DONE (DS0)");
return FAILURE;
}

// create mspp Channel
MSP_CHANNEL_ADDR      chanaddr    = {0};
MSP_CHANNEL_PARAMETER chan_params = {0};

chanaddr.nBoard         = Board;
chanaddr.channelType    = G711FullDuplex;
chanaddr.FilterAttribs  = MSP_FCN_ATTRIB_RFC2833;
chan_params.size        = sizeof( MSP_CHANNEL_PARAMETER );
chan_params.channelType = G711FullDuplex;
chan_params.ChannelParms.VoiceParms.size = sizeof( MSP_VOICE_CHANNEL_PARMS );
...
// Create channel
mspCreateChannel
( ctaHd, &chanaddr, &chan_params, &msphd );
CTA_EVENT CtaEvent;
if (! WaitForSpecificEvent(MSPEVN_CREATE_CHANNEL_DONE, &Event, 5000))
{
printf("Failed waiting for MSPEVN_CREATE_CHANNEL_DONE");
return FAILURE;
}

// connect mspp endpoints
ret =
mspConnect(rtp_ephd, msphd, ds0_ephd);
if (! WaitForSpecificEvent(MSPEVN_CONNECT_DONE, &Event, 5000))
{
printf("Failed waiting for MSPEVN_CONNECT_DONE");
return FAILURE;
}

// enable channel
mspEnableChannel
(mspHd);
if (! WaitForSpecificEvent(MSPEVN_ENABLE_CHANNEL_DONE, &Event, 5000))
{
printf("Failed waiting for MSPEVN_ENABLE_CHANNEL_DONE");
return FAILURE;
}

//adiStartProtocol
adiStartProtocol
( ctahd, "nocc", NULL, NULL );
if (! WaitForSpecificEvent (ADIEVN_STARTPROTOCOL_DONE, &Event, 5000))
{
printf("Failed to receive ADIEVN_STARTPROTOCOL_DONE event");
return FAILURE;
}

// get cg6xxx board handle
ret = mspGetFilterHandle( msphd, MSP_FILTER_JITTER, &cg6xxx_board_filter_handle );

ADI_NATIVE_CONTROL parms = {0};     /*   Native parameters                    */
parms.frameFormat   = 0;
parms.include2833   = 0;
parms.vadFlag       = 0;
parms.nsPayload     = 0;
parms.mode          = ADI_NATIVE;
parms.rec_encoding = ADI_ENCODE_EDTX_MU_LAW;
parms.payloadID     = 0;
ret = adiSetNativeInfo( ctahd, cg6xxx_board_filter_handle,
    NULL,       /* this is record only so no egress handle */
    &parms );

// get default adi record parms
ret = ctaGetParms( ctahd, ADI_RECORD_PARMID, &recparms, sizeof(ADI_RECORD_PARMS) );
ret = adiRecordToMemory( ctahd, ADI_ENCODE_EDTX_MU_LAW,           /* audio rec */
     MemoryBuffer, RecordedBytes, &recparms );