458 lines
16 KiB
C++
458 lines
16 KiB
C++
/*----------------------------------------------------------------------------
|
|
* Copyright (c) TJD Technologies Co., Ltd. 2025. All rights reserved.
|
|
*
|
|
* Description: TjdPhoneAudio.cpp
|
|
*
|
|
* Author: luziquan@ss-tjd.com
|
|
*
|
|
* Create: 2025-08-16
|
|
*--------------------------------------------------------------------------*/
|
|
|
|
#include "TjdPhoneAudio.h"
|
|
#include "TjdPhoneService.h"
|
|
#include "audio_errors.h"
|
|
#include "sys_config.h"
|
|
|
|
#define ENABLE_PRINT_INFO 1
|
|
#if ENABLE_PRINT_INFO
|
|
#define static_print_warn(...) sys_phone_log_w(__VA_ARGS__) // 警告信息打印一般常开
|
|
#define static_print_error(...) sys_phone_log_e(__VA_ARGS__) // 错误信息打印一般常开
|
|
#define static_print_debug(...) sys_phone_log_d(__VA_ARGS__) // 调试信息打印一般常开
|
|
#else
|
|
#define static_print_warn(...)
|
|
#define static_print_error(...)
|
|
#define static_print_debug(...)
|
|
#endif
|
|
|
|
class PhoneAudioInterruptListener : public Audio::InterruptListener
|
|
{
|
|
public:
|
|
PhoneAudioInterruptListener() {};
|
|
~PhoneAudioInterruptListener() {};
|
|
void OnInterrupt(int32_t type, int32_t hint) override
|
|
{
|
|
UNUSED(type);
|
|
UNUSED(hint);
|
|
static_print_debug("[PhoneAudioInterruptListener] OnInterrupt: type = %d, hint = %d", type, hint);
|
|
}
|
|
};
|
|
|
|
static std::shared_ptr<PhoneAudioInterruptListener> g_audioIntListener = nullptr;
|
|
|
|
int32_t TjdPhoneAudio::AudioInit(void)
|
|
{
|
|
bool ret = amInstance_.Initialize();
|
|
if (!ret) {
|
|
static_print_error("[%s] line:%d, audio manager init failed", __FUNCTION__, __LINE__);
|
|
return AUDIO_ERROR;
|
|
}
|
|
static_print_error("[%s] line:%d, success", __FUNCTION__, __LINE__);
|
|
return AUDIO_SUCCESS;
|
|
}
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioGetMinVolume(void) { return amInstance_.GetMinVolume(AUDIO_STREAM_VOICE_CALL_BT_SCO); }
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioGetMaxVolume(void) { return amInstance_.GetMaxVolume(AUDIO_STREAM_VOICE_CALL_BT_SCO); }
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioGetVolume(void) { return amInstance_.GetVolume(AUDIO_STREAM_VOICE_CALL_BT_SCO); }
|
|
|
|
bool TjdPhoneAudio::PhoneAudioSetVolume(int32_t volume)
|
|
{
|
|
return amInstance_.SetVolume(AUDIO_STREAM_VOICE_CALL_BT_SCO, volume);
|
|
}
|
|
|
|
// 设置通话speaker静音/取消静音
|
|
bool TjdPhoneAudio::PhoneAudioSetSpeakerMute(bool isMute)
|
|
{
|
|
bool ret;
|
|
static_print_debug("[PhoneAudioSetSpeakerMute] start");
|
|
ret = amInstance_.IsMute(AUDIO_STREAM_VOICE_CALL_BT_SCO);
|
|
if (ret == isMute) {
|
|
return true;
|
|
}
|
|
|
|
if (isMute) {
|
|
ret = amInstance_.Mute(AUDIO_STREAM_VOICE_CALL_BT_SCO);
|
|
} else {
|
|
ret = amInstance_.UnMute(AUDIO_STREAM_VOICE_CALL_BT_SCO);
|
|
}
|
|
static_print_debug("[PhoneAudioSetSpeakerMute] end! ret = %d", ret);
|
|
return ret;
|
|
}
|
|
|
|
// 设置通话mic静音/取消静音
|
|
bool TjdPhoneAudio::PhoneAudioSetMicMute(bool isMute)
|
|
{
|
|
bool ret;
|
|
static_print_debug("[PhoneAudioSetMicMute] start");
|
|
ret = amInstance_.IsMicrophoneMute();
|
|
if (ret == isMute) {
|
|
return true;
|
|
}
|
|
ret = amInstance_.SetMicrophoneMute(isMute);
|
|
static_print_debug("[PhoneAudioSetMicMute] end! ret = %d", ret);
|
|
return ret;
|
|
}
|
|
|
|
static bool CheckParam(int32_t instanceNum)
|
|
{
|
|
if (instanceNum == 0 || instanceNum == 1) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioManagerActInterrupt(AudioStreamType streamType)
|
|
{
|
|
/* request audio focus */
|
|
static_print_debug("[%s] streamType:0x%x", __FUNCTION__, streamType);
|
|
|
|
sessionId_ = amInstance_.MakeSessionId();
|
|
if (sessionId_ == AUDIO_SESSION_ID_NONE) {
|
|
static_print_error("[%s] line:%d, make session id failed", __FUNCTION__, __LINE__);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
static_print_debug("[%s] line:%d, session id = %d", __FUNCTION__, __LINE__, sessionId_);
|
|
|
|
g_audioIntListener = std::make_shared<PhoneAudioInterruptListener>();
|
|
if (g_audioIntListener.get() == nullptr) {
|
|
static_print_error("[%s] line:%d, g_audioIntListener is null", __FUNCTION__, __LINE__);
|
|
return AUDIO_ERROR;
|
|
}
|
|
interrupt_ = {streamType, sessionId_, g_audioIntListener};
|
|
if (amInstance_.ActivateAudioInterrupt(interrupt_) == INTERRUPT_FAILED) {
|
|
static_print_error("[%s] line:%d, ActivateAudioInterrupt failed", __FUNCTION__, __LINE__);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
static_print_debug("[%s] line:%d, success", __FUNCTION__, __LINE__);
|
|
return AUDIO_SUCCESS;
|
|
}
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioManagerSetDeviceConnState(AudioDeviceType deviceType,
|
|
AudioDeviceConnectState connectState)
|
|
{
|
|
int32_t ret = amInstance_.SetDeviceConnectionState(deviceType, connectState);
|
|
if (ret != AUDIO_SUCCESS) {
|
|
static_print_error("[%s] line:%d failed, deviceType = 0x%x connectState = %d ret = %d", __FUNCTION__, __LINE__,
|
|
deviceType, connectState, ret);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
static_print_debug("[%s] line:%d success, deviceType = 0x%x connectState = %d", __FUNCTION__, __LINE__, deviceType,
|
|
connectState);
|
|
return AUDIO_SUCCESS;
|
|
}
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioStreamInInit(AudioLinkDirection linkDir)
|
|
{
|
|
int32_t instanceNum = INVALID_AUDIO_VALUE;
|
|
static_print_debug("[%s] linkDir:0x%x", __FUNCTION__, linkDir);
|
|
|
|
/* create ASI instance UP_LINK: index 0, DOWN_LINK: index 1 */
|
|
if (linkDir == AUDIO_UP_LINK) {
|
|
g_streamIn[0] = std::make_shared<AudioStreamIn>();
|
|
instanceNum = 0;
|
|
} else if (linkDir == AUDIO_DOWN_LINK) {
|
|
g_streamIn[1] = std::make_shared<AudioStreamIn>();
|
|
instanceNum = 1;
|
|
} else {
|
|
static_print_error("[%s] line:%d failed, invalid linkDir = %d", __FUNCTION__, __LINE__, linkDir);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
if (g_streamIn[instanceNum] == nullptr || g_streamIn[instanceNum].get() == nullptr) {
|
|
static_print_error("[%s] line:%d make_shared AudioStreamIn failed", __FUNCTION__, __LINE__);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
/* init ASI */
|
|
CapturerInputConfig captureConfig = {
|
|
.streamType = AUDIO_STREAM_VOICE_CALL_BT_SCO,
|
|
.sessionID = sessionId_,
|
|
.channelCount = AUDIO_CHANNEL_1,
|
|
.linkDir = linkDir,
|
|
};
|
|
|
|
captureConfig.audioFormat = (AudioCodecFormat)GetCallAudioCodec();
|
|
if (captureConfig.audioFormat == PCM) {
|
|
captureConfig.sampleRate = AUDIO_SAMPLE_RATE_8K;
|
|
} else if (captureConfig.audioFormat == mSBC) {
|
|
captureConfig.sampleRate = AUDIO_SAMPLE_RATE_16K;
|
|
}
|
|
|
|
int32_t ret = g_streamIn[instanceNum]->Init(captureConfig);
|
|
if (ret != AUDIO_SUCCESS) {
|
|
static_print_error("[%s] line:%d streamIn init failed, ret: 0x%x", __FUNCTION__, __LINE__, ret);
|
|
return AUDIO_ERROR;
|
|
}
|
|
static_print_debug("[%s] line:%d success, instanceNum = %d", __FUNCTION__, __LINE__, instanceNum);
|
|
return instanceNum;
|
|
}
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioStreamOutInit(AudioLinkDirection linkDir)
|
|
{
|
|
int32_t instanceNum = INVALID_AUDIO_VALUE;
|
|
|
|
static_print_debug("[%s] linkDir:0x%x", __FUNCTION__, linkDir);
|
|
|
|
/* create ASO instance UP_LINK: index 0, DOWN_LINK: index 1 */
|
|
if (linkDir == AUDIO_UP_LINK) {
|
|
g_streamOut[0] = std::make_shared<AudioStreamOut>();
|
|
instanceNum = 0;
|
|
} else if (linkDir == AUDIO_DOWN_LINK) {
|
|
g_streamOut[1] = std::make_shared<AudioStreamOut>();
|
|
instanceNum = 1;
|
|
} else {
|
|
static_print_error("[%s] line:%d failed, invalid linkDir = %d", __FUNCTION__, __LINE__, linkDir);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
if (g_streamOut[instanceNum] == nullptr || g_streamOut[instanceNum].get() == nullptr) {
|
|
static_print_error("[%s] line:%d make_shared AudioStreamOut failed", __FUNCTION__, __LINE__);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
/* init ASO */
|
|
AudioRendererConfig renderConfig = {
|
|
.streamType = AUDIO_STREAM_VOICE_CALL_BT_SCO,
|
|
.sessionID = sessionId_,
|
|
.channelCount = AUDIO_CHANNEL_1,
|
|
.linkDir = linkDir,
|
|
};
|
|
|
|
renderConfig.audioFormat = (AudioCodecFormat)GetCallAudioCodec();
|
|
if (renderConfig.audioFormat == PCM) {
|
|
renderConfig.sampleRate = AUDIO_SAMPLE_RATE_8K;
|
|
} else if (renderConfig.audioFormat == mSBC) {
|
|
renderConfig.sampleRate = AUDIO_SAMPLE_RATE_16K;
|
|
}
|
|
|
|
int32_t ret = g_streamOut[instanceNum]->Init(renderConfig);
|
|
if (ret != AUDIO_SUCCESS) {
|
|
static_print_error("[%s] line:%d streamOut init failed, ret: 0x%x", __FUNCTION__, __LINE__, ret);
|
|
return AUDIO_ERROR;
|
|
}
|
|
/* dump stream */
|
|
g_streamOut[instanceNum]->DumpInfo();
|
|
|
|
static_print_debug("[%s] line:%d success, instanceNum = %d", __FUNCTION__, __LINE__, instanceNum);
|
|
return instanceNum;
|
|
}
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioStreamInStart(int32_t instanceNum)
|
|
{
|
|
static_print_debug("[%s] instanceNum:0x%x", __FUNCTION__, instanceNum);
|
|
bool isValid = CheckParam(instanceNum);
|
|
if (!isValid) {
|
|
static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
/* start ASI */
|
|
int32_t ret = g_streamIn[instanceNum]->Start();
|
|
if (ret != AUDIO_SUCCESS) {
|
|
static_print_error("[%s] line:%d streamIn Start failed ret: 0x%x", __FUNCTION__, __LINE__, ret);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__);
|
|
return AUDIO_SUCCESS;
|
|
}
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioStreamOutStart(int32_t instanceNum)
|
|
{
|
|
static_print_debug("[%s] instanceNum:0x%x", __FUNCTION__, instanceNum);
|
|
bool isValid = CheckParam(instanceNum);
|
|
if (!isValid) {
|
|
static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
/* start ASO */
|
|
int32_t ret = g_streamOut[instanceNum]->Play();
|
|
if (ret != AUDIO_SUCCESS) {
|
|
static_print_error("[%s] line:%d streamOut Play failed ret: 0x%x", __FUNCTION__, __LINE__, ret);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__);
|
|
return AUDIO_SUCCESS;
|
|
}
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioStreamInGetChannelId(int32_t instanceNum, uint32_t *shmId)
|
|
{
|
|
bool isValid = CheckParam(instanceNum);
|
|
if (!isValid || shmId == nullptr) {
|
|
static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
/* obtain ASI channel id(adp handle) */
|
|
uint32_t channelId;
|
|
int32_t ret = g_streamIn[instanceNum]->GetCurrentChannelId(channelId);
|
|
if (ret != AUDIO_SUCCESS) {
|
|
static_print_error("[%s] line:%d streamIn get Id failed ret: 0x%x", __FUNCTION__, __LINE__, ret);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
static_print_debug("[%s] line:%d stream in channelId: 0x%x", __FUNCTION__, __LINE__, channelId);
|
|
|
|
*shmId = channelId;
|
|
static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__);
|
|
return AUDIO_SUCCESS;
|
|
}
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioStreamOutGetChannelId(int32_t instanceNum, uint32_t *shmId)
|
|
{
|
|
bool isValid = CheckParam(instanceNum);
|
|
if (!isValid || shmId == nullptr) {
|
|
static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
/* obtain ASO channel id(adp handle) */
|
|
uint32_t channelId;
|
|
int32_t ret = g_streamOut[instanceNum]->GetCurrentChannelId(channelId);
|
|
if (ret != AUDIO_SUCCESS) {
|
|
static_print_error("[%s] line:%d streamOut get Id failed ret: 0x%x", __FUNCTION__, __LINE__, ret);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
static_print_debug("[%s] line:%d stream out channelId: 0x%x", __FUNCTION__, __LINE__, channelId);
|
|
|
|
*shmId = channelId;
|
|
static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__);
|
|
return AUDIO_SUCCESS;
|
|
}
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioStreamInAttachBackend(int32_t instanceNum, uint32_t backendId)
|
|
{
|
|
bool isValid = CheckParam(instanceNum);
|
|
if (!isValid) {
|
|
static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
/* ASI set shm id */
|
|
int32_t ret = g_streamIn[instanceNum]->AttachBackend(backendId);
|
|
if (ret != AUDIO_SUCCESS) {
|
|
static_print_error("[%s] line:%d streamIn AttachBackend failed backendId: 0x%x, ret: 0x%x", __FUNCTION__,
|
|
__LINE__, backendId, ret);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
static_print_debug("[%s] line:%d, stream in instanceNum: %d, backendId: 0x%x", __FUNCTION__, __LINE__, instanceNum,
|
|
backendId);
|
|
static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__);
|
|
return AUDIO_SUCCESS;
|
|
}
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioStreamOutAttachFrontend(int32_t instanceNum, uint32_t frontendId)
|
|
{
|
|
bool isValid = CheckParam(instanceNum);
|
|
if (!isValid) {
|
|
static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
/* ASO set shm id */
|
|
int32_t ret = g_streamOut[instanceNum]->AttachFrontend(frontendId);
|
|
if (ret != AUDIO_SUCCESS) {
|
|
static_print_error("[%s] line:%d streamOut AttachFrontend failed frontendId: 0x%x, ret: 0x%x", __FUNCTION__,
|
|
__LINE__, frontendId, ret);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
static_print_debug("[%s] line:%d, stream out instanceNum: %d, frontendId: 0x%x", __FUNCTION__, __LINE__,
|
|
instanceNum, frontendId);
|
|
static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__);
|
|
return AUDIO_SUCCESS;
|
|
}
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioStreamInStop(int32_t instanceNum)
|
|
{
|
|
bool isValid = CheckParam(instanceNum);
|
|
if (!isValid) {
|
|
static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
/* stop ASI */
|
|
int32_t ret = g_streamIn[instanceNum]->Stop();
|
|
if (ret != AUDIO_SUCCESS) {
|
|
static_print_error("[%s] line:%d streamIn Stop failed ret: 0x%x", __FUNCTION__, __LINE__, ret);
|
|
}
|
|
|
|
static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__);
|
|
return AUDIO_SUCCESS;
|
|
}
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioStreamOutStop(int32_t instanceNum)
|
|
{
|
|
bool isValid = CheckParam(instanceNum);
|
|
if (!isValid) {
|
|
static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
/* stop ASO */
|
|
int32_t ret = g_streamOut[instanceNum]->Stop();
|
|
if (ret != AUDIO_SUCCESS) {
|
|
static_print_error("[%s] line:%d streamOut Stop failed ret: 0x%x", __FUNCTION__, __LINE__, ret);
|
|
}
|
|
|
|
static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__);
|
|
return AUDIO_SUCCESS;
|
|
}
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioStreamInDeinit(int32_t instanceNum)
|
|
{
|
|
bool isValid = CheckParam(instanceNum);
|
|
if (!isValid) {
|
|
static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
/* deinit ASI */
|
|
if (g_streamIn[instanceNum] != nullptr) {
|
|
g_streamIn[instanceNum]->Release();
|
|
g_streamIn[instanceNum] = nullptr;
|
|
}
|
|
|
|
static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__);
|
|
return AUDIO_SUCCESS;
|
|
}
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioStreamOutDeinit(int32_t instanceNum)
|
|
{
|
|
bool isValid = CheckParam(instanceNum);
|
|
if (!isValid) {
|
|
static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
/* deinit ASO */
|
|
if (g_streamOut[instanceNum] != nullptr) {
|
|
g_streamOut[instanceNum]->Release();
|
|
g_streamOut[instanceNum] = nullptr;
|
|
}
|
|
|
|
static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__);
|
|
return AUDIO_SUCCESS;
|
|
}
|
|
|
|
int32_t TjdPhoneAudio::PhoneAudioManagerDeactInterrupt(void)
|
|
{
|
|
/* release audio focus */
|
|
int32_t ret = amInstance_.DeactivateAudioInterrupt(interrupt_);
|
|
if (ret != AUDIO_SUCCESS) {
|
|
static_print_error("[%s] line:%d DeactivateAudioInterrupt failed ret = %d", __FUNCTION__, __LINE__, ret);
|
|
return AUDIO_ERROR;
|
|
}
|
|
|
|
static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__);
|
|
return AUDIO_SUCCESS;
|
|
}
|