All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Audio Service

Click here for the API reference documentation.


Open/Close an Audio Interface
Control an Audio Stream
Create Audio connectors
Specifying audio formats
Play and record audio
Code samples

The Audio API handles audio interfaces including play or listen supported formats.

A Legato device can use several audio interfaces. You choose the input and output interfaces to tie together. The Audio stream related to a particular interface is represented with an 'Audio Stream Reference'.

You can create your own audio path by connecting several audio streams together using audio connectors.

An audio path can support more than two audio interfaces. You can have a basic output audio path of a voice call to connect the Modem Voice Received interface with the Speaker interface, and at the same time, the Modem Voice Received interface can be also connected to a Recorder Device interface.

Open/Close an Audio Interface

The following functions let you select the desired interface:

  • le_audio_OpenMic(): returns an Audio Stream Reference of the analog audio signal coming from the microphone input.
  • le_audio_OpenSpeaker(): returns an Audio Stream Reference of the analog audio signal routed to the Speaker output.
  • le_audio_OpenUsbRx(): returns an Audio Stream Reference of the digitized audio signal coming from an external device connected via USB Audio Class.
  • le_audio_OpenUsbTx(): returns an Audio Stream Reference of the digitized audio signal routed to an external device connected via USB Audio Class.
  • le_audio_OpenPcmRx(): it returns an Audio Stream Reference of the digitized audio signal coming from an external device connected via the PCM interface.
  • le_audio_OpenPcmTx(): it returns an Audio Stream Reference of the digitized audio signal routed to an external device connected via the PCM interface.
  • le_audio_OpenI2sRx(): it returns an Audio Stream Reference of the digitized audio signal coming from an external device connected via the I2S interface.
  • le_audio_OpenI2sTx(): it returns an Audio Stream Reference of the digitized audio signal routed to an external device connected via the I2S interface.
  • le_audio_OpenModemVoiceRx(): returns an Audio Stream Reference of the digitized audio signal coming from a voice call. The audio format is negotiated with the network when the call is established.
  • le_audio_OpenModemVoiceTx(): returns an Audio Stream Reference of the digitized audio signal routed to a voice call. The audio format is negotiated with the network when the call is established.

Multiple users can own the same stream at the same time.

le_audio_GetFormat() can be called to get the audio format of an input or output stream.

Call le_audio_Close() to release it. If several users own the same, corresponding stream reference, the interface will close only after the last user releases the audio stream.

Control an Audio Stream

Once the users get an Audio Stream reference, they can control it with the following functions:

  • le_audio_SetGain(): allows the user to adjust the gain of an audio stream (0 means 'muted', 100 is the maximum gain value).
  • le_audio_GetGain(): allows the User to retrieve the gain of an audio stream (0 means 'muted', 100 is the maximum gain value).
  • le_audio_Mute(): allows the user to mute an audio stream.
  • le_audio_Unmute(): allows the user to unmute an audio stream.
Note
The hardware may or may not support the full 0-100 resolution, and if you want to see what was actually set call le_audio_GetGain() after le_audio_SetGain() to get the real value.

Create Audio connectors

You can create your own audio path by connecting several audio streams together.

le_audio_CreateConnector() function creates a reference to an audio connector.

You can tie an audio stream to a connector by calling the le_audio_Connect() function.

You can remove an audio stream from a connector by calling the le_audio_Disconnect() function.

When finished with it, delete it using the le_audio_DeleteConnector() function.

Specifying audio formats

The encoding audio format can be specified to (or retrieved from) the audio interfaces that support this option. The format parameter is a string containing the IANA specified encoding format name for Real-Time protocol (RTP).

The complete list of the audio encoding format names can be found on the IANA organization web site (http://www.iana.org).

Function that gets the current audio format for an open interface is:

Warning
Ensure to check the list of supported audio formats for your specific platform.

Some examples of audio formats:

  • "L16-8K": Linear PCM 16-bit audio @ 8KHz
  • "L16-16K": Linear PCM 16-bit audio @ 16KHz
  • "GSM": European GSM Full Rate @ 8KHz (GSM 06.10)
  • "GSM-EFR": ITU-T GSM Enhanced Full Rate @ 8KHz (GSM 06.60)
  • "GSM-HR-08": ITU-T GSM Half Rate @ 8KHz (GSM 06.20)
  • "AMR": Adaptive Multi-Rate - Full Rate @ 8KHz
  • "AMR-HR": Adaptive Multi-Rate - Half Rate @ 8KHz
  • "AMR-WB": Adaptive Multi-Rate Wideband @ 16KHz
Note
The string is not case sensitive.

Play and record audio

An audio file can be played to any active output interfaces.

You must open a "File Playback" interface by calling:

  • le_audio_OpenFilePlayback(): returns an Audio Stream Reference for file playback. The audio file is played on the local audio interface like Speaker, USB Tx, PCM Tx, I2S Tx or on the remote audio interface Modem Voice Tx depending the kind of connector (input or output) is tied to.

A "File Playback" interface can be opened only on an active output audio path. For instance, the "I2S Tx" and "Modem Voice Rx" must be previously connected before opening and connecting the "File Playback" interface on the same connector.

Audio file recording can be done from any active input interfaces.

You must open a "File Recording" interface by calling:

  • le_audio_OpenFileRecording(): returns an Audio Stream Reference for file recording. The local audio interface like Microphone, USB Rx, PCM Rx, I2S Rx is recorded into an audio file; or the Modem Voice Rx remote audio interface is recorded into an audio file, depending the kind of connector (input or output) is tied to.

A "File Recording" interface can be opened only on an active input audio path. For instance, the "I2S Rx" and "Modem Voice Tx" must be previously connected before opening and connecting the "File Recording" interface on the same connector.

Note
Only .wav file format is currently supported.

The function below is an example of how a file can be played to the Modem Voice Tx output interface. The audio of the voice call is redirected to the I2S interfaces. This function simply plays a voice prompt to the remote party when the voice call is established.

static void ConnectAudioAndPlayVoicePromptToRemoteParty
(
void
)
{
// I get the audio from the voice call.
// I get the I2S interface references.
// I create the audio connectors.
// The voice call's audio is redirected to I2S interfaces.
if (mdmRxAudioRef && mdmTxAudioRef && i2sTxRef && i2sRxRef &&
audioInputConnectorRef && audioOutputConnectorRef)
{
le_audio_Connect(audioInputConnectorRef, i2sRxRef);
le_audio_Connect(audioInputConnectorRef, mdmTxAudioRef);
le_audio_Connect(audioOutputConnectorRef, i2sTxRef);
le_audio_Connect(audioOutputConnectorRef, mdmRxAudioRef);
}
// I get the interface reference for file playback.
int fd = open("/myvoiceprompt.wav", O_RDONLY));
// The audio file is played on the input connector, the remote party can now here the voice
// prompt.
if (fileAudioRef && audioInputConnectorRef)
{
le_audio_Connect(audioInputConnectorRef, fileAudioRef);
}
}

Code samples

The following two code samples show how to create different audio paths for an incoming voice call.

The first example has the audio path depending on an USB Audio handset. The ConnectVoiceCallAudio() function creates this audio path. A USB Audio handset plugged in and fully operationnal, will redirect the call audio to the handset; otherwise, it will redirect the call to the default microphone and speaker.

Use DisconnectVoiceCallAudio() to delete the audio path.

le_result_t ConnectVoiceCallAudio
(
le_audio_ConnectorRef_t* audioInputConnectorRefPtr, // [OUT] Input connector.
le_audio_ConnectorRef_t* audioOutputConnectorRefPtr, // [OUT] Output connector.
le_audio_StreamRef_t* mdmRxAudioRefPtr, // [OUT] Received voice call audio stream.
le_audio_StreamRef_t* mdmTxAudioRefPtr, // [OUT] Transmitted voice call audio stream.
le_audio_StreamRef_t* deviceRxAudioRefPtr, // [OUT] Received device audio stream.
le_audio_StreamRef_t* deviceTxAudioRefPtr // [OUT] Transmitted device audio stream.
)
{
// I get the audio from the voice call.
*mdmRxAudioRefPtr = le_audio_OpenModemVoiceRx();
*mdmTxAudioRefPtr = le_audio_OpenModemVoiceTx();
// If I cannot get the audio from the voice call, I return an error.
if ((*mdmRxAudioRefPtr == NULL) || (*mdmTxAudioRefPtr == NULL))
{
// I close the audio interfaces that have failed to open.
le_audio_Close(*mdmRxAudioRefPtr);
le_audio_Close(*mdmTxAudioRefPtr);
}
// I create the audio connectors.
*audioInputConnectorRefPtr = le_audio_CreateConnector();
*audioOutputConnectorRefPtr = le_audio_CreateConnector();
// I verify if my Audio USB handset is plugged and operational before trying to use it.
if(IsMyUSBHandsetPlugged() == TRUE)
{
// I can redirect the audio to my USB handset using linear PCM audio format (PCM 16bits @ 16KHz)
*deviceRxAudioRefPtr = le_audio_OpenUsbRx();
*deviceTxAudioRefPtr = le_audio_OpenUsbTx();
le_audio_Connect(*audioInputConnectorRefPtr, *deviceRxAudioRefPtr);
le_audio_Connect(*audioOutputConnectorRefPtr, *deviceTxAudioRefPtr);
}
else
{
// There is no USB Audio handset, I redirect the audio to the in-built Microphone and Speaker.
*deviceRxAudioRefPtr = le_audio_OpenMic();
*deviceTxAudioRefPtr = le_audio_OpenSpeaker();
le_audio_Connect(*audioInputConnectorRefPtr, *deviceRxAudioRefPtr);
le_audio_Connect(*audioOutputConnectorRefPtr, *deviceTxAudioRefPtr);
}
// I tie the audio from the voice call to the connectors.
le_audio_Connect (*audioInputConnectorRefPtr, *mdmTxAudioRefPtr);
le_audio_Connect (*audioOutputConnectorRefPtr, *mdmRxAudioRefPtr);
return LE_OK;
}
void DisconnectVoiceCallAudio
(
le_audio_ConnectorRef_t audioInputConnectorRef, // [IN] Input connector.
le_audio_ConnectorRef_t audioOutputConnectorRef, // [IN] Output connector.
le_audio_StreamRef_t mdmRxAudioRef, // [IN] Received voice call audio stream.
le_audio_StreamRef_t mdmTxAudioRef, // [IN] Transmitted voice call audio stream.
le_audio_StreamRef_t deviceRxAudioRef, // [IN] Received device audio stream.
le_audio_StreamRef_t deviceTxAudioRef // [IN] Transmitted device audio stream.
)
{
// The call is terminated, I can close its audio interfaces.
le_audio_Close(mdmRxAudioRef);
le_audio_Close(mdmTxAudioRef);
// I close all the device interfaces.
le_audio_Close(deviceRxAudioRef);
le_audio_Close(deviceTxAudioRef);
// I delete the Audio connector references.
le_audio_DeleteConnector(audioInputConnectorRef);
le_audio_DeleteConnector(audioOutputConnectorRef);
}

The next code sample uses specific functions to deal with a new 'Incoming call' event during a call already in progress.

If no call is in progress, use the ConnectVoiceCallAudio() function to redirect the call audio to the in-built Microphone and Speaker.

If a new call is incoming, and considered a high priority call, you must mute the audio of the first call, and then connect the new call to your current audio path. Use SwitchVoiceCallAudio() for these actions.

When the high priority call terminates, you can return back to your previous call and reactivate its audio with the SwitchBackVoiceCallAudio() function.

le_result_t ConnectVoiceCallAudio
(
le_audio_ConnectorRef_t* audioInputConnectorRefPtr, // [OUT] Input connector.
le_audio_ConnectorRef_t* audioOutputConnectorRefPtr, // [OUT] Output connector.
le_audio_StreamRef_t* mdmRxAudioRefPtr, // [OUT] Received voice call audio stream.
le_audio_StreamRef_t* mdmTxAudioRefPtr, // [OUT] Transmitted voice call audio stream.
le_audio_StreamRef_t* micRefPtr, // [OUT] Microphone stream.
le_audio_StreamRef_t* speakerRefPtr // [OUT] Speaker stream.
)
{
*mdmRxAudioRefPtr = le_audio_OpenModemVoiceRx();
*mdmTxAudioRefPtr = le_audio_OpenModemVoiceTx();
// If I cannot get the audio from the voice call, I return an error.
if ((*mdmRxAudioRefPtr == NULL) || (*mdmTxAudioRefPtr == NULL))
{
// I close the audio interfaces that have failed to open.
le_audio_Close(*mdmRxAudioRefPtr);
le_audio_Close(*mdmTxAudioRefPtr);
}
*audioInputConnectorRefPtr = le_audio_CreateConnector();
*audioOutputConnectorRefPtr = le_audio_CreateConnector();
// Redirect audio to the in-built Microphone and Speaker.
*speakerRefPtr = le_audio_OpenSpeaker();
*micRefPtr = le_audio_OpenMic();
le_audio_Connect(*audioInputConnectorRefPtr, *micRefPtr);
le_audio_Connect (*audioInputConnectorRefPtr, *mdmTxAudioRefPtr);
le_audio_Connect(*audioOutputConnectorRefPtr, *speakerRefPtr);
le_audio_Connect (*audioOutputConnectorRefPtr, *mdmRxAudioRefPtr);
return LE_OK;
}
le_result_t SwitchVoiceCallAudio
(
le_audio_ConnectorRef_t audioInputConnectorRef, // [IN] Input connector.
le_audio_ConnectorRef_t audioOutputConnectorRef, // [IN] Output connector.
le_audio_StreamRef_t oldMdmRxAudioRef, // [IN] Received audio stream of the previous voice call.
le_audio_StreamRef_t oldMdmTxAudioRef, // [IN] Transmitted audio stream of the previous voice call.
le_audio_StreamRef_t* newMdmRxAudioRefPtr, // [OUT] Received audio stream of the new voice call.
le_audio_StreamRef_t* newMdmTxAudioRefPtr // [OUT] Transmitted audio stream of the new voice call.
)
{
if ((newMdmRxAudioRefPtr == NULL) ||
(newMdmTxAudioRefPtr == NULL))
{
}
*newMdmRxAudioRefPtr = le_audio_OpenModemVoiceRx();
*newMdmTxAudioRefPtr = le_audio_OpenModemVoiceTx();
// If I cannot get the audio from the voice call, I return an error.
if ((*newMdmRxAudioRefPtr == NULL) || (*newMdmTxAudioRefPtr == NULL))
{
// I close the audio interfaces that have failed to open.
le_audio_Close(*newMdmRxAudioRefPtr);
le_audio_Close(*newMdmTxAudioRefPtr);
}
// I mute the previous call.
le_audio_Mute(oldMdmRxAudioRef);
le_audio_Mute(oldMdmTxAudioRef);
// I connect the new incoming call.
le_audio_Connect (audioInputConnectorRef, *newMdmTxAudioRefPtr);
le_audio_Connect (audioOutputConnectorRef, *newMdmRxAudioRefPtr);
return LE_OK;
}
le_result_t SwitchBackVoiceCallAudio
(
le_audio_StreamRef_t oldMdmRxAudioRef, // [IN] Received audio stream of the previous voice call.
le_audio_StreamRef_t oldMdmTxAudioRef, // [IN] Transmitted audio stream of the previous voice call.
le_audio_StreamRef_t newMdmRxAudioRef, // [IN] Received audio stream of the new voice call.
le_audio_StreamRef_t newMdmTxAudioRef // [IN] Transmitted audio stream of the new voice call.
)
{
// I can delete the new call audio interfaces.
le_audio_Close(newMdmRxAudioRef);
le_audio_Close(newMdmTxAudioRef);
// I can re-open the previous call streaming.
if (le_audio_Unmute(oldMdmRxAudioRef) != LE_OK)
{
return LE_FAULT;
}
if (le_audio_Unmute(oldMdmTxAudioRef) != LE_OK)
{
return LE_FAULT;
}
return LE_OK;
}

Copyright (C) Sierra Wireless, Inc. 2014. Use of this work is subject to license.

If a LE_VOICECALL_EVENT_TERMINATED event is received, application can get the termination reason by using le_voicecall_GetTerminationReason().

Note
The voice call use the mobile network. VoIP is not yet supported.

Answering a Voice call

An Incoming voice call will be notified by an LE_VOICECALL_EVENT_INCOMING event on state handler with a Call reference le_voicecall_CallRef_t().

Application can answer the call by using le_voicecall_Answer() or reject the call by using le_voicecall_End() passing the call reference le_voicecall_CallRef_t. Application should use le_voicecall_Delete() to release le_voicecall_CallRef_t voice call reference object.

Voice call Options

Note
Following functionality described in this section is not currently implemented; this description is provided to outline future functionality.

Some applications may have voice call requirements that are not met by the default voice call (e.g., use a least cost voice call link or disable roaming on mobile networks). You can do this by:

  • creating a request object using le_voicecall_CreateCall(),
  • setting optional values on that request object using le_voicecall_SelectLeastCost() or le_voicecall_DisableRoaming(),
  • and then submitting that object to a voice call connection request using le_voicecall_SubmitCall()

le_voicecall_AddStateHandler() , le_voicecall_End() and le_voicecall_Delete() APIs can continue to be used, as described above.


Copyright (C) Sierra Wireless, Inc. 2014. Use of this work is subject to license.