diff --git a/distributedaudio.gni b/distributedaudio.gni index 06e5b9b9012992a75b7f092a70a2410bba5271c4..9d64dc1124893e39b17a1368c03677f3688d0555 100644 --- a/distributedaudio.gni +++ b/distributedaudio.gni @@ -44,3 +44,7 @@ innerkits_path = "${distributedaudio_path}/interfaces/inner_kits" distributedaudio_fuzz_path = "distributed_audio/distributed_audio" build_flags = [ "-Werror" ] + +declare_args() { + distributed_audio_extension_sa = false +} diff --git a/services/audiomanager/managersource/include/daudio_echo_cannel_manager.h b/services/audiomanager/managersource/include/daudio_echo_cannel_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..dd72e9f9a1403584a0e9e9d0378a701a28095477 --- /dev/null +++ b/services/audiomanager/managersource/include/daudio_echo_cannel_manager.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DAUDIO_ECHO_CANNEL_MANAGER_H +#define OHOS_DAUDIO_ECHO_CANNEL_MANAGER_H + +#include + +#include "single_instance.h" + +#include "audio_capturer.h" +#include "audio_info.h" +#include "aec_effect_processor.h" +#include "iaudio_datatrans_callback.h" + +#include "audio_data.h" +#include "audio_data_ext.h" +#include "audio_param.h" + +namespace OHOS { +namespace DistributedHardware { +class DAudioEchoCannelManager : public AudioStandard::AudioCaptureReadCallback, + public std::enable_shared_from_this { +public: + DAudioEchoCannelManager(); + ~DAudioEchoCannelManager(); + + int32_t SetUp(const AudioCommonParam param, + const std::shared_ptr &callback); + int32_t Start(); + int32_t Stop(); + int32_t Release(); + + int32_t OnMicDataReceived(const std::shared_ptr &pipeInData); + +private: + void OnReadData(size_t length) override; + void AecProcessData(); + int32_t ProcessMicData(const std::shared_ptr &pipeInData, + std::shared_ptr &micOutData); + + int32_t AudioCaptureSetUp(); + int32_t AudioCaptureStart(); + int32_t AudioCaptureStop(); + int32_t AudioCaptureRelease(); + + int32_t LoadAecProcessor(); + void UnLoadAecProcessor(); + int32_t InitAecProcessor(); + int32_t StartAecProcessor(); + int32_t StopAecProcessor(); + int32_t ReleaseAecProcessor(); + + std::unique_ptr audioCapturer = nullptr; + std::atomic isAecRunnig_ = false; + std::thread aecProcessThread_; + static constexpr const char* AECTHREADNAME = "AecProcessThread"; + + std::shared_ptr devCallback_; + void *aecHandler_ = nullptr; + AecEffectProcessor *aecProcessor_ = nullptr; + constexpr static size_t COND_WAIT_TIME_MS = 10; + constexpr static size_t COND_WAIT_TIME_MS = 10; + constexpr static size_t WAIT_MIC_DATA_TIME_US = 5000; + constexpr static size_t REF_QUEUE_MAX_SIZE = 10; + std::queue> refDataQueue_; + std::queue> outDataQueue_; + std::mutex refQueueMtx_; + std::mutex outQueueMtx_; + std::condition_variable refQueueCond_; + std::atomic isStarted = false; +} // OHOS +#endif // OHOS_DAUDIO_DMIC_DEV_H diff --git a/services/audiomanager/managersource/include/dmic_dev.h b/services/audiomanager/managersource/include/dmic_dev.h index e1257abe8dfd46caf4d0a7dc657fcc97320e95a5..1928c68f2f180b1dad76a687cecb7d121cb921d4 100644 --- a/services/audiomanager/managersource/include/dmic_dev.h +++ b/services/audiomanager/managersource/include/dmic_dev.h @@ -26,6 +26,9 @@ #include "av_receiver_engine_transport.h" #include "ashmem.h" #include "daudio_constants.h" +#ifdef ECHO_CANNEL_ENABLE +#include "daudio_echo_cannel_manager.h" +#endif #include "daudio_hdi_handler.h" #include "daudio_io_dev.h" #include "iaudio_data_transport.h" @@ -106,6 +109,9 @@ private: std::atomic isOpened_ = false; std::atomic dumpFlag_ = false; std::shared_ptr micTrans_ = nullptr; +#ifdef ECHO_CANNEL_ENABLE + std::shared_ptr echoManager_ = nullptr; +#endif std::queue> dataQueue_; AudioStatus curStatus_ = AudioStatus::STATUS_IDLE; // Mic capture parameters @@ -130,6 +136,7 @@ private: std::mutex writeAshmemMutex_; std::condition_variable dataQueueCond_; int32_t dhId_ = -1; + bool echoCannelOn_ = false; }; } // DistributedHardware } // OHOS diff --git a/services/audiomanager/managersource/src/daudio_echo_cannel_manager.cpp b/services/audiomanager/managersource/src/daudio_echo_cannel_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..330b627445fe3e6afd4331243940eac9320ae89c --- /dev/null +++ b/services/audiomanager/managersource/src/daudio_echo_cannel_manager.cpp @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "daudio_echo_cannel_manager.h" + +#include + +#include "daudio_constants.h" +#include "daudio_errorcode.h" +#include "daudio_log.h" +#include "daudio_util.h" + +#include + +#undef DH_LOG_TAG +#define DH_LOG_TAG "DAudioEchoCannelManager" + +using namespace OHOS::AudioStandard; +namespace OHOS { +namespace DistributedHardware { +using AecEffectProcessorProvider = AecEffectProcessor *(*)(); + +const std::string ECHOCANNEL_SO_NAME = "libdaudio_aec_effect_processor.z.so"; +const std::string GET_AEC_EFFECT_PROCESSOR_FUNC = "GetAecEffectProcessor"; +const int32_t FRAME_SIZE_NORMAL = 3840; +#ifdef __LP64__ +const std::string LIB_LOAD_PATH = "/system/lib64/"; +#else +const std::string LIB_LOAD_PATH = "/system/lib/"; +#endif + +DAudioEchoCannelManager::DAudioEchoCannelManager() +{ + DHLOGD("Distributed audio echo cannel manager constructed."); +} + +DAudioEchoCannelManager::~DAudioEchoCannelManager() +{ + DHLOGD("Distributed audio echo cannel manager destructed."); +} + +int32_t DAudioEchoCannelManager::SetUp(const AudioCommonParam param, + const std::shared_ptr &callback) +{ + (void) param; + devCallback_ = callback; + DHLOGI("SetUp EchoCannel."); + int32_t ret = LoadAecProcessor(); + if (ret != DH_SUCCESS) { + DHLOGE("LoadAECProcessor error."); + return ERR_DH_AUDIO_FAILED; + } + ret = InitAecProcessor(); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "Init Aec Processor error. ret: %d.", ret); + + ret = AudioCaptureSetUp(); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "Init Get Reference error. ret: %d.", ret); + + ret = AudioCaptureStart(); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "Start Get Reference error. ret: %d.", ret); + + return DH_SUCCESS; +} + +int32_t DAudioEchoCannelManager::Start() +{ + DHLOGI("Start EchoCannel."); + int32_t ret = StartAecProcessor(); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "Start Aec Processor error. ret: %d.", ret); + + isStarted.store(true); + DHLOGI("Start EchoCannel success."); + return DH_SUCCESS; +} + +int32_t DAudioEchoCannelManager::Stop() +{ + DHLOGI("Stop EchoCannel."); + isStarted.store(false); + int32_t ret = StopAecProcessor(); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "Stop Aec Processor error. ret: %d.", ret); + ret = AudioCaptureStop(); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "Stop Get Reference error. ret: %d.", ret); + DHLOGI("Stop EchoCannel success."); + return DH_SUCCESS; +} + +int32_t DAudioEchoCannelManager::Release() +{ + DHLOGI("Release EchoCannel."); + int32_t ret = AudioCaptureRelease(); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "Release Get Reference error. ret: %d.", ret); + + ret = ReleaseAecProcessor(); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "Release Aec Processor error. ret: %d.", ret); + UnLoadAecProcessor(); + isStarted.store(false); + return DH_SUCCESS; +} + +int32_t DAudioEchoCannelManager::OnMicDataReceived(const std::shared_ptr &pipeInData) +{ + DHLOGI("GetMicDataBeforeAec."); + CHECK_AND_RETURN_RET_LOG(pipeInData == nullptr, ERR_DH_AUDIO_NULLPTR, "pipeInData is nullptr."); + CHECK_AND_RETURN_RET_LOG(devCallback_ == nullptr, ERR_DH_AUDIO_NULLPTR, "callback is nullptr."); + CHECK_AND_RETURN_RET_LOG(aecProcessor_ == nullptr, ERR_DH_AUDIO_NULLPTR, "aec processor is nullptr."); + if (isStarted.load()) { + auto micOutData = std::make_shared(pipeInData->Size()); + int32_t ret = ProcessMicData(pipeInData, micOutData); + if (ret != DH_SUCCESS) { + DHLOGE("Mic data call processor error. ret : %d.", ret); + devCallback_->OnDecodeTransDataDone(pipeInData); + return ERR_DH_AUDIO_FAILED; + } +#ifdef DUMP_FILE + SaveFile("/data/luzhi.pcm", const_cast(pipeInData->Data()), pipeInData->Size()); +#endif + devCallback_->OnDecodeTransDataDone(micOutData); + } else { + devCallback_->OnDecodeTransDataDone(pipeInData); + } + return DH_SUCCESS; +} + +int32_t DAudioEchoCannelManager::ProcessMicData(const std::shared_ptr &pipeInData, + std::shared_ptr &micOutData) +{ + DHLOGI("Process mic data."); + auto micInDataExt = std::make_shared(pipeInData->Size()); + std::shared_ptr micOutDataExt = nullptr; + CHECK_AND_RETURN_RET_LOG(pipeInData == nullptr, ERR_DH_AUDIO_NULLPTR, "pipeInData is nullptr."); + CHECK_AND_RETURN_RET_LOG(micOutData == nullptr, ERR_DH_AUDIO_NULLPTR, "micOutData is nullptr."); + CHECK_AND_RETURN_RET_LOG(aecProcessor_ == nullptr, ERR_DH_AUDIO_NULLPTR, "aec processor is nullptr."); + if (memcpy_s(micInDataExt->Data(), micInDataExt->Size(), pipeInData->Data(), pipeInData->Size()) != EOK) { + DHLOGE("copy mic data before aec error."); + return ERR_DH_AUDIO_FAILED; + } + int32_t ret = aecProcessor_->OnSendOriginData(micInDataExt, StreamType::MIC1, micOutDataExt); + if (ret != DH_SUCCESS || micOutDataExt == nullptr) { + DHLOGI("aec effect process pipeInReferenceData fail. errocode:%d", ret); + return ERR_DH_AUDIO_FAILED; + } + if (memcpy_s(micOutData->Data(), micOutData->Size(), micOutDataExt->Data(), micOutDataExt->Size()) != EOK) { + DHLOGE("copy mic data after aec error."); + return ERR_DH_AUDIO_FAILED; + } + return DH_SUCCESS; +} + +void DAudioEchoCannelManager::AecProcessData() +{ + DHLOGI("Start the aec process thread."); + if (pthread_setname_np(pthread_self(), AECTHREADNAME) != DH_SUCCESS) { + DHLOGE("aec process thread setname failed."); + } + DHLOGI("Begin the aec process thread. refDataQueueSize: %d.", + refDataQueue_.size()); + while (aecProcessor_ != nullptr && isAecRunning_.load()) { + std::shared_ptr refInData = nullptr; + std::shared_ptr refOutDataExt = nullptr; + { + std::unique_lock refLck(refQueueMtx_); + refQueueCond_.wait_for(refLck, std::chrono::milliseconds(COND_WAIT_TIME_MS), + [this]() { return !refDataQueue_.empty(); }); + if (refDataQueue_.empty()) { + DHLOGE("refDataQueue is Empty."); + continue; + } + refInData = refDataQueue_.front(); + refDataQueue_.pop(); + DHLOGI("Pop new echo ref data, ref dataqueue size: %d.", refDataQueue_.size()); + } + auto refInDataExt = std::make_shared(refInData->Size()); + if (memcpy_s(refInDataExt->Data(), refInDataExt->Size(), refInData->Data(), refInData->Size()) != EOK) { + DHLOGE("copy ref data before aec error."); + continue; + } +#ifdef DUMP_FILE + SaveFile("/data/cankao.pcm", const_cast(refInData->Data()), refInData->Size()); +#endif + int32_t ret = aecProcessor_->OnSendOriginData(refInDataExt, StreamType::REF, refOutDataExt); + if (ret != DH_SUCCESS) { + DHLOGE("aec effect process pipeInReferenceData fail. errocode:%d", ret); + } + } + DHLOGI("the aec process thread exit."); + return; +} + +void DAudioEchoCannelManager::OnReadData(size_t length) +{ + BufferDesc bufDesc; + if (audioCapturer_ == nullptr) { + DHLOGE("audioCapturer is nullptr."); + return; + } + int32_t ret = audioCapturer_->GetBufferDesc(bufDesc); + if (ret != 0 || bufDesc.buffer == nullptr || bufDesc.bufLength == 0) { + DHLOGE("Get buffer desc failed. On read data."); + return; + } + DHLOGD("Get echo ref data. size: %d.", bufDesc.bufLength); + std::shared_ptr audioData = std::make_shared(bufDesc.bufLength); + if (audioData->Capacity() != bufDesc.bufLength) { + DHLOGE("Audio data length is not equal to buflength. datalength: %d, bufLength: %d", + audioData->Capacity(), bufDesc.bufLength); + } + if (memcpy_s(audioData->Data(), audioData->Capacity(), bufDesc.buffer, bufDesc.bufLength) != EOK) { + DHLOGE("Copy audio data failed."); + } + + audioCapturer_->Enqueue(bufDesc); + + std::lock_guard lock(refQueueMtx_); + while (refDataQueue_.size() > REF_QUEUE_MAX_SIZE) { + DHLOGE("Ref Data queue overflow. max size : 10"); + refDataQueue_.pop(); + } + refDataQueue_.push(audioData); + DHLOGI("Push new echo ref data, buf len: %d.", refDataQueue_.size()); + refQueueCond_.notify_all(); +} + +int32_t DAudioEchoCannelManager::AudioCaptureSetUp() +{ + if (audioCapturer_ != nullptr) { + DHLOGI("Audio capture has been created. no need to setup."); + return DH_SUCCESS; + } + AudioStandard::AudioCaptureOptions capturerOptions = { + { + AudioStandard::AudioSamplingRate::SAMPLE_RATE_48000, + AudioStandard::AudioEncodingType::ENCODING_PCM, + AudioStandard::AudioSampleFormat::SAMPLE_S16LE, + AudioStandard::AudioChannel::STEREO, + }, + { + AudioStandard::SourceType::SOURCE_TYPE_PLAYBACK_CAPTURE, + AudioStandard::STREAM_FLAG_NORMAL, + } + }; + capturerOptions.playbackCaptureConfig.filterOptions.usages.push_back(AudioStandard:: + StreamUsage::STREAM_USAGE_MEDIA); + capturerOptions.playbackCaptureConfig.filterOptions.usages.push_back(AudioStandard:: + StreamUsage::STREAM_USAGE_UNKNOWN); + + audioCapturer_ = AudioStandard::AudioCapturer::create(capturerOptions); + CHECK_AND_RETURN_RET_LOG(audioCapturer_ == nullptr, ERR_DH_AUDIO_FAILED, "Audio capture create failed"); + + int32_t ret = audioCapturer_->SetCaptureMode(CAPTURE_MODE_CALLBACK); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "Set capture mode callback fail, ret %{public}d.", ret); + ret = audioCapturer_->SetCapturerReadCallback(shared_from_this()); + CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "Set capture data callback fail, ret %{public}d.", ret); + DHLOGI("Audio capturer create success"); + return DH_SUCCESS; +} + +int32_t DAudioEchoCannelManager::AudioCaptureStart() +{ + if (audioCapturer_ == nullptr) { + DHLOGE("Audio capturer is nullptr start."); + return ERR_DH_AUDIO_FAILED; + } + if (!audioCapturer_->Start()) { + DHLOGE("Audio capturer start failed."); + return ERR_DH_AUDIO_FAILED; + } + return DH_SUCCESS; +} + +int32_t DAudioEchoCannelManager::AudioCaptureStop() +{ + if (audioCapturer_ == nullptr) { + DHLOGIE("Audio capturer is nullptr stop."); + return ERR_DH_AUDIO_FAILED; + } + if (!audioCapturer_->Stop()) { + DHLOGE("Audio capturer stop failed."); + return ERR_DH_AUDIO_FAILED; + } + return DH_SUCCESS; +} + +int32_t DAudioEchoCannelManager::AudioCaptureRelease() +{ + if (audioCapturer_ != nullptr && !audioCapturer_->Release()) { + DHLOGE("Audio capturer release failed."); + } + audioCapturer_ == nullptr; + DHLOGE("Audio capturer release end."); + return DH_SUCCESS; +} + +int32_t DAudioEchoCannelManager::LoadAecProcessor() +{ + DHLOGI("LoadAecEffectProcessor enter"); + char path[PATH_MAX + 1] = {0x00}; + if ((LIB_LOAD_PATH.length() + ECHOCANNEL_SO_NAME.length()) > PATH_MAX || + realpath((LIB_LOAD_PATH+ ECHOCANNEL_SO_NAME).c_str(), path) == nullptr) { + DHLOGE("File open failed"); + return ERR_DH_AUDIO_NULLPTR; + } + aecHandler_ = dlopen(path, RTLD_LAZY | RTLD_NODELETE); + CHECK_AND_RETURN_RET_LOG(aecHandler_ == nullptr, ERR_DH_AUDIO_NULLPTR, "dlOpen error."); + AecEffectProcessorProvider getAecEffectProcessorFunc = (AecEffectProcessorProvider)dlsym(aecHandler_, + GET_AEC_EFFECT_PROCESSOR_FUNC.c_str()); + if (getAecEffectProcessorFunc == nullptr) { + DHLOGE("AecEffectProcessor function handler is null, failed reason : %s", dlerror()); + dlclose(aecHandler_); + aecHandler_ = nullptr; + return ERR_DH_AUDIO_NULLPTR; + } + aecProcessor_ = getAecEffectProcessorFunc(); + DHLOGI("LoadAecEffectProcessor exit."); + return DH_SUCCESS; +} + +void DAudioEchoCannelManager::UnLoadAecProcessor() +{ + if (aecHandler_ != nullptr) { + dlclose(aecHandler_); + aecHandler_ = nullptr; + } + aecProcessor_ = nullptr; +} + +int32_t DAudioEchoCannelManager::InitAecProcessor() +{ + AudioCommonParam param; + param.sampleRate = SAMPLE_RATE_48000; + param.channelMask = STEREO; + param.bitFormat = SAMPLE_S16LE; + param.frameSize = FRAME_SIZE_NORMAL; + if (aecProcessor_ == nullptr) { + DHLOGE("Aec processor is nullptr."); + return ERR_DH_AUDIO_NULLPTR; + } + int32_t ret = aecProcessor_->Init(param); + if (ret != DH_SUCESS) { + DHLOGE("Aec effect processor init fail. errorcode: %d", ret); + return ERR_DH_AUDIO_FAILED; + } + DHLOGI("Aec effect process init success."); + return DH_SUCCESS; +} + +int32_t DAudioEchoCannelManager::StartAecProcessor() +{ + if (aecProcessor_ == nullptr) { + DHLOGE("Aec process is nullptr."); + return ERR_DH_AUDIO_NULLPTR; + } + int32_t ret = aecProcessor_->StartUp(); + if (ret != DH_SUCCESS) { + DHLOGE("Aec effect process start fail. errorcode:%d", ret); + return ERR_DH_AUDIO_FAILED; + } + if (!isAecRunning.load()) { + isAecRunning.store(true); + aecProcessThread_ = std::thread(&DAudioEchoCannelManager::AecProcessData, this); + } + DHLOGI("Aec effect process start success."); + return DH_SUCCESS; +} + +int32_t DAudioEchoCannelManager::StopAecProcessor() +{ + if (aecProcessor_ == nullptr) { + DHLOGI("Aec process is nullptr."); + return ERR_DH_AUDIO_NULLPTR; + } + int32_t ret = aecProcessor_->ShutDown(); + if (ret != DH_SUCCESS) { + DHLOGE("Aec effect process stop fail. errorcode:%d", ret); + return ERR_DH_AUDIO_FAILED; + } + if (!isAecRunning.load()) { + DHLOGI("Stop the aec process thread."); + isAecRunning.store(false); + if (aecProcessThread_.joinable()) { + aecProcessThread_.join(); + } + } + DHLOGI("Aec effect process stop success."); + return DH_SUCCESS; +} + +int32_t DAudioEchoCannelManager::ReleaseAecProcessor() +{ + if (isAecRunning.load()) { + DHLOGI("Stop the aec process thread."); + isAecRunning.store(false); + if (aecProcessThread_.joinable()) { + aecProcessThread_.join(); + } + } + if (aecProcessor_ != nullptr) { + if (aecProcessor_->Release() != DH_SUCCESS) { + DHLOGE("Aec effect process release fail."); + } + aecProcessor_ = nullptr; + } + DHLOGI("Aec effect process release success."); + return DH_SUCCESS; +} +} // namespace DistributedHardware +} // namespace OHOS diff --git a/services/audiomanager/managersource/src/dmic_dev.cpp b/services/audiomanager/managersource/src/dmic_dev.cpp index b746682640073a3eae3120affd93020b3ad95e0f..b782303dcb14dc406c82ec63944deeefdcae7ef9 100644 --- a/services/audiomanager/managersource/src/dmic_dev.cpp +++ b/services/audiomanager/managersource/src/dmic_dev.cpp @@ -57,7 +57,17 @@ void DMicDev::OnEngineTransMessage(const std::shared_ptr &messag void DMicDev::OnEngineTransDataAvailable(const std::shared_ptr &audioData) { DHLOGD("On Engine Data available"); - OnDecodeTransDataDone(audioData); + if (echoCannelOn_) { +#ifdef ECHO_CANNEL_ENABLE + if (echoManager_ == nullptr) { + DHLOGE("Echo manager is nullptr."); + return; + } + echoManager_->OnMicDataReceived(audioData); +#endif + } else { + OnDecodeTransDataDone(audioData); + } } int32_t DMicDev::InitReceiverEngine(IAVEngineProvider *providerPtr) @@ -216,6 +226,20 @@ int32_t DMicDev::SetUp() DHLOGE("Mic trans set up failed. ret: %{public}d.", ret); return ret; } + echoCannelOn_ = false; +#ifdef ECHO_CANNEL_ENABLE + if (echoCannelOn_ && echoManager_ == nullptr) { + echoManager_ = std::make_shared(); + } + AudioCommonParam info; + info.sampleRate = param_.comParam.sampleRate; + info.channelMask = param_.comParam.channelMask; + info.bitFormat = param_.comParam.bitFormat; + info.frameSize = param_.comParam.frameSize; + if (echoManager_ != nullptr) { + echoManager_->SetUp(info, shared_from_this()); + } +#endif return DH_SUCCESS; } @@ -235,6 +259,14 @@ int32_t DMicDev::Start() DHLOGE("Wait channel open timeout(%{public}ds).", CHANNEL_WAIT_SECONDS); return ERR_DH_AUDIO_SA_WAIT_TIMEOUT; } +#ifdef ECHO_CANNEL_ENABLE + CHECK_NULL_RETURN(echoManager_, DH_SUCCESS); + ret = echoManager_->Start(); + if (ret != DH_SUCCESS) { + DHLOGE("Echo manager start failed. ret: %d.", ret); + return ret; + } +#endif isOpened_.store(true); return DH_SUCCESS; } @@ -261,6 +293,14 @@ int32_t DMicDev::Stop() if (ret != DH_SUCCESS) { DHLOGE("Stop mic trans failed, ret: %{public}d.", ret); } +#ifdef ECHO_CANNEL_ENABLE + CHECK_NULL_RETURN(echoManager_, DH_SUCCESS); + ret = echoManager_->Stop(); + if (ret != DH_SUCCESS) { + DHLOGE("Echo manager stop failed. ret: %d.", ret); + return ret; + } +#endif return DH_SUCCESS; } @@ -280,6 +320,12 @@ int32_t DMicDev::Release() DHLOGE("Release mic trans failed, ret: %{public}d.", ret); return ret; } +#ifdef ECHO_CANNEL_ENABLE + if (echoManager_ != nullptr) { + echoManager_->Release(); + echoManager_ = nullptr; + } +#endif dumpFlag_.store(false); return DH_SUCCESS; } diff --git a/services/audiomanager/servicesource/BUILD.gn b/services/audiomanager/servicesource/BUILD.gn index 2abf18640ed89665939bfe4ae1298fdd983d6854..b43d2d973e4f73a94025b54f135ad99da86d45a1 100755 --- a/services/audiomanager/servicesource/BUILD.gn +++ b/services/audiomanager/servicesource/BUILD.gn @@ -51,6 +51,11 @@ ohos_shared_library("distributed_audio_source") { "${services_path}/audiomanager/common/include", ] + if (distributed_audio_extension_sa) { + include_dirs += + [ "${distributedaudio_ext_path}/services/aeceffectprocessor/include" ] + } + sources = [ "${audio_control_path}/controlsource/src/daudio_source_dev_ctrl_manager.cpp", "${audio_hdi_proxy_path}/src/daudio_hdf_operate.cpp", @@ -69,6 +74,10 @@ ohos_shared_library("distributed_audio_source") { "src/daudio_source_stub.cpp", ] + if (distributed_audio_extension_sa) { + sources += [ "${services_path}/audiomanager/managersource/src/daudio_echo_cannel_manager.cpp" ] + } + deps = [ "${audio_transport_path}/receiverengine:distributed_audio_decode_transport", "${audio_transport_path}/senderengine:distributed_audio_encode_transport", @@ -80,6 +89,7 @@ ohos_shared_library("distributed_audio_source") { "access_token:libaccesstoken_sdk", "access_token:libtokenid_sdk", "audio_framework:audio_capturer", + "audio_framework:audio_client", "audio_framework:audio_renderer", "cJSON:cjson", "c_utils:utils", @@ -101,6 +111,18 @@ ohos_shared_library("distributed_audio_source") { "samgr:samgr_proxy", ] + cflags = [] + + if (distributed_audio_extension_sa) { + external_deps += [ + "distributed_audio_ext:daudio_aec_effect_processor", + "distributed_audio_ext:distributed_audio_ext_utils", + ] + cflags += [ "-DECHO_CANNEL_ENABLE" ] + } + + cflags_cc = cflags + defines = [ "HI_LOG_ENABLE", "LOG_DOMAIN=0xD004130", diff --git a/services/audiomanager/test/unittest/sourcedevice/BUILD.gn b/services/audiomanager/test/unittest/sourcedevice/BUILD.gn index 9faf4bd757e5c10ba42020a275d92b176626966a..3a249d0a9106a091aba00691fb777078f6208185 100644 --- a/services/audiomanager/test/unittest/sourcedevice/BUILD.gn +++ b/services/audiomanager/test/unittest/sourcedevice/BUILD.gn @@ -93,6 +93,7 @@ ohos_unittest("DMicDevTest") { deps = [ "${audio_transport_path}/receiverengine:distributed_audio_decode_transport", "${services_path}/audiomanager/servicesource:distributed_audio_source", + "${services_path}/common:distributed_audio_utils", "//third_party/googletest:gmock", "//third_party/googletest:gtest_main", ] @@ -119,6 +120,7 @@ ohos_unittest("DSpeakerDevTest") { deps = [ "${audio_transport_path}/senderengine:distributed_audio_encode_transport", "${services_path}/audiomanager/servicesource:distributed_audio_source", + "${services_path}/common:distributed_audio_utils", "//third_party/googletest:gmock", "//third_party/googletest:gtest_main", ] diff --git a/services/audiotransport/receiverengine/BUILD.gn b/services/audiotransport/receiverengine/BUILD.gn index d223f202ae7c39c4dc0300a5139541016a6c85a7..17e48c8e4a4b25ef51404499356fa5654efab06b 100644 --- a/services/audiotransport/receiverengine/BUILD.gn +++ b/services/audiotransport/receiverengine/BUILD.gn @@ -52,7 +52,6 @@ ohos_shared_library("distributed_audio_decode_transport") { "${audio_processor_path}/directprocessor/src/audio_direct_processor.cpp", "${audio_transport_path}/receiverengine/src/av_receiver_engine_adapter.cpp", "${audio_transport_path}/receiverengine/src/av_receiver_engine_transport.cpp", - "${services_path}/common/audiodata/src/audio_data.cpp", ] deps = [ "${services_path}/common:distributed_audio_utils" ] diff --git a/services/audiotransport/senderengine/BUILD.gn b/services/audiotransport/senderengine/BUILD.gn index b51cbd80b9c38c8771e332bbbc4b5039eedd351a..2292ecb4662bc6dc4748839be1248c2acc70a62b 100644 --- a/services/audiotransport/senderengine/BUILD.gn +++ b/services/audiotransport/senderengine/BUILD.gn @@ -52,7 +52,6 @@ ohos_shared_library("distributed_audio_encode_transport") { "${audio_processor_path}/directprocessor/src/audio_direct_processor.cpp", "${audio_transport_path}/senderengine/src/av_sender_engine_adapter.cpp", "${audio_transport_path}/senderengine/src/av_sender_engine_transport.cpp", - "${services_path}/common/audiodata/src/audio_data.cpp", ] deps = [ "${services_path}/common:distributed_audio_utils" ]