# 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:

- Opens the ADI
  API on a NaturalAccess context and starts the NOCC protocol on the context.

- Opens the MSPP API and the ADI APIon a second context, and creates an RTP endpoint, a DS0 endpoint, and a voice channel on the context.

- Connects the RTP endpoint, DS0 endpoint, and voice channel to create a voice connection.

- Creates a switch connection between the ADI port and the DS0 endpoint.

- Retrieves the filter ID of the jitter filter associated with the voice channel.

- Supplies the ADI service with information about the RTP audio streams and specifies the desired behavior for native record operations.

- Starts and stops recording audio data from a network audio stream.

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:

- NaturalAccess functions to set up event queues and contexts and to open services on the contexts.

- ADI API functions to start a protocol, to set native record settings, and to record incoming audio data.

- MSPP functions to create a voice connection consisting of a voice decoding channel, an RTP endpoint, and a DS0 endpoint, and to retrieve the unique filter ID of the RTP endpoint's jitter filter.

- SWI functions to switch together the ADI service port and the MSPP service connection (through the DS0 endpoint).

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, msp addrstruct, msp parmstruct, &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, msp addrstruct, msp parmstruct, &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 );