Snapdragon® Telematics Application Framework (TelAF) Interface Specification
Audio Service

API Reference


The Audio service APIs provide an interface to playback and record audio. TelAf audio is connector based and audio connectors have one input and output interface, which is responsible for routing audio data.

The audio stream reference represents the audio interfaces for the given connectors.

For any stream types the maximum number of supported devices is one. A single stream for multiple devices is not supported.

For example, for a voice call audio path, MIC and SPEAKER connectors are required, but in lower layers the audio stream is closely coupled, so once the stream type is set to to VOICE both the MIC and SPEAKER are configured.

IPC interfaces binding

All functions of this API are provided by the tafAudioSvc application service.

The following example shows how to bind to the audio service.

In application.adef add the taf_audio API in bindings.

bindings:
{
   clientExe.clientComponent.taf_audio -> tafAudioService.taf_audio
}

In Component.cdef add the taf_audio interface.

requires:
{
 api:
 {
   taf_audio.api
 }
}

Audio playback

To do playback of audio with a supported format (such as .wav / .amr), the following APIs should be called in sequence.

 OutRef = taf_audio_OpenSpeaker();
 LE_ERROR_IF((NULL == OutRef), "taf_audio_OpenSpeaker returns NULL!");

 OutputConnectorRef  = taf_audio_CreateConnector();
 LE_ERROR_IF((NULL == OutputConnectorRef), "OutputConnectorRef  is NULL!");

 FileRef = taf_audio_OpenPlayer();
 LE_ERROR_IF((NULL == FileRef), "OpenFilePlayback returns NULL!");

MediaHandler and Media Events

Handler for media events, such as error and media end.

 MediaHandlerRef = taf_audio_AddMediaHandler(FileRef, MediaEventHandler, NULL);

Connector and open file from location

     res = taf_audio_Connect(OutputConnectorRef, OutRef);
     LE_ERROR_IF((LE_OK != res), "Failed on Output connector (res %s)!", LE_RESULT_TXT(res));

     res = taf_audio_Connect(OutputConnectorRef , FileRef);
     LE_ERROR_IF((LE_OK != res), "Playback failed on input connector!");

     if ((FileFd = open(FilePath, O_RDONLY)) == -1)
     {
         LE_ERROR("Open file %s failure: errno.%d (%s)", FilePath, errno, LE_ERRNO_TXT(errno));
         taf_audio_Disconnect(OutputConnectorRef, OutRef);
         taf_audio_Disconnect(OutputConnectorRef, FileRef);
         taf_audio_DeleteConnector(OutputConnectorRef);
         taf_audio_Close(OutRef);
         taf_audio_Close(FileRef);

         return LE_FAULT;
     }

Play file from location

     res = taf_audio_PlayFile(FileRef, FileFd);

     LE_ERROR_IF((LE_OK != res), "Playback failed...!");

Mute and Unmute

     // Mute and UnMute can be called only on active stream
     res = taf_audio_Mute(FileRef);
     res = taf_audio_Unmute(FileRef);

Close and Delete connectors

Delete and close the connectors when finished.

taf_audio_Disconnect(OutputConnectorRef, OutRef);
taf_audio_Disconnect(OutputConnectorRef, FileRef);
taf_audio_DeleteConnector(OutputConnectorRef);
taf_audio_Close(OutRef);
taf_audio_Close(FileRef);

Audio voice call

Echo Cancellation and Noise Reduction

This needs to be called before starting a voice call.

EnableNoiseSuppressor and EnableEchoCanceller API's are handled in a single configuration.

if (LE_OK != (res = taf_audio_EnableNoiseSuppressor(AudioRef)))
 {
     LE_ERROR("Set EnableNoiseSuppressor failed (res.%d)", res);
 }

 if (LE_OK != ((res = taf_audio_EnableEchoCanceller(AudioRef)))
 {
     LE_ERROR("Set EnableEchoCanceller failed! (res.%d)", res);
 }

DisableEchoCanceller and DisableNoiseSuppressor APIs are handled in a single configuration. This needs to be called before starting a voice call.

 if (LE_OK != ((res = taf_audio_DisableEchoCanceller(AudioRef)))
 {
     LE_ERROR(" DisableEchoCanceller failed! (res.%d)", res);
 }

 if (LE_OK != ((res = taf_audio_DisableNoiseSuppressor(AudioRef)))
 {
     LE_ERROR(" DisableNoiseSuppressor failed! (res.%d)", res);
 }

For a voice call, the OpenModemVoiceRx API with the slot ID should be called in sequence as shown in the following example.

 RxMdmRef = taf_audio_OpenModemVoiceRx(1);
 LE_ERROR_IF(( NULL == RxMdmRef), "taf_audio_OpenModemVoiceRx returns NULL!");

 OutRef = taf_audio_OpenSpeaker();
 LE_ERROR_IF((NULL == OutRef), "taf_audio_OpenSpeaker returns NULL!");
Note
This also needs to be called for a voice call on SA525M device.
 TxMdmRef = taf_audio_OpenModemVoiceTx(1);
 LE_ERROR_IF(( NULL == TxMdmRef), "taf_audio_OpenModemVoiceTx returns NULL!");

 InRef = taf_audio_OpenMic();
 LE_ERROR_IF((NULL == InRef), "taf_audio_OpenMic returns NULL!");

Connector and open file from location when call is on hold

When a voice call is on hold there will be local file playback of audio.

 OutputConnectorRef = taf_audio_CreateConnector();
 LE_ERROR_IF((NULL == OutputConnectorRef), "OutputConnectorRef is NULL!");

 taf_audio_Connect(OutputConnectorRef, OutRef);
Note
This needs to be called when a voice call is on hold.
 if ((FileFd = open(FilePath, O_RDONLY)) == -1)
    {
        LE_ERROR_IF((LE_OK != res), "Playback failed...!");
        return LE_FAULT;
    }
     res = taf_audio_PlayFile(FileRef, FileFd);

     LE_ERROR_IF((LE_OK != res), "Playback failed...!");

Close and Delete connectors

Delete and close the connectors when finished.

 taf_audio_Disconnect(OutputConnectorRef, OutRef);
 taf_audio_Disconnect(OutputConnectorRef, FileRef);
 taf_audio_DeleteConnector(OutputConnectorRef);
 taf_audio_Close(OutRef);
 taf_audio_Close(FileRef);

Audio capture

To capture audio in PCM format with 16 bits per sample resolution, the following APIs should be called in sequence.

 InRef = taf_audio_OpenMic();
 LE_ERROR_IF((NULL == InRef), "taf_audio_OpenMic returns NULL!");

 InputConnectorRef  = taf_audio_CreateConnector();
 LE_ERROR_IF((NULL == InputConnectorRef), "InputConnectorRef  is NULL!");

 FileRef = taf_audio_OpenRecorder();
 LE_ERROR_IF((NULL == FileRef), "OpenRecorder returns NULL!");

 res = taf_audio_Connect(InputConnectorRef, InRef);
 LE_ERROR_IF(res != LE_OK, "Failed to connect Mic on Input connector!");

 res = taf_audio_Connect(InputConnectorRef , FileRef);
 LE_ERROR_IF(res != LE_OK, "Failed to connect FileRecorder on input connector!");

 // Default channel number is 1, and records on LEFT channel.
 //Set to 2 for both LEFT & RIGHT channels
 res = taf_audio_SetSamplePcmChannelNumber(FileAudioRef, 2);
 LE_ERROR_IF(res != LE_OK, "Failed to set the channel number!");

 int AudioFileFd=open(AudioFilePath, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);

 if(AudioFileFd != -1) {
     res = taf_audio_RecordFile(FileRef, AudioFileFd);
     LE_ERROR_IF(res != LE_OK, "Failed to record the file!");
 }