Snapdragon® Telematics Application Framework (TelAF) Interface Specification
|
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.
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 } }
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!");
Handler for media events, such as error and media end.
MediaHandlerRef = taf_audio_AddMediaHandler(FileRef, MediaEventHandler, NULL);
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; }
res = taf_audio_PlayFile(FileRef, FileFd); LE_ERROR_IF((LE_OK != res), "Playback failed...!");
// Mute and UnMute can be called only on active stream res = taf_audio_Mute(FileRef); res = taf_audio_Unmute(FileRef);
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);
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!");
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!");
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);
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...!");
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);
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!"); }