语音拾音通路
1 当前audio结构图 2 社区当前录音流程 录音类型如下: enum SourceType { SOURCE_TYPE_INVALID = -1, SOURCE_TYPE_MIC,// 本地录音 SOURCE_TYPE_VOICE_RECOGNITION = 1,// SOURCE_TYPE_PLAYBACK_CAPTURE = 2,// 内录࿰
1 当前audio结构图
2 社区当前录音流程
录音类型如下:
enum SourceType {
SOURCE_TYPE_INVALID = -1,
SOURCE_TYPE_MIC, // 本地录音
SOURCE_TYPE_VOICE_RECOGNITION = 1, //
SOURCE_TYPE_PLAYBACK_CAPTURE = 2, // 内录(录屏)
SOURCE_TYPE_WAKEUP = 3, // 语言唤醒
SOURCE_TYPE_VOICE_CALL = 4, // 通话中录音
SOURCE_TYPE_VOICE_COMMUNICATION = 7, // VOIP
SOURCE_TYPE_ULTRASONIC = 8,
SOURCE_TYPE_VIRTUAL_CAPTURE = 9, // only for voice call 打电话
SOURCE_TYPE_MAX = SOURCE_TYPE_VIRTUAL_CAPTURE
};
3 开发者手机的蓝牙录音流程
开发者手机pcm设备列表如下:
# cat proc/asound/pcm
00-01: DisplayPort MultiMedia (*) : : playback 1
00-02: FE_ST_NORMAL_AP01 (*) : : playback 1 : capture 1 // 本地播放和录音
00-03: FE_ST_NORMAL_AP23 (*) : : playback 1 : capture 1
00-04: FE_ST_CAPTURE_DSP (*) : : capture 1
00-05: FE_ST_FAST (*) : : playback 1
00-07: FE_ST_VOICE (*) : : playback 1 : capture 1 // 打电话设备
00-08: FE_ST_VOIP (*) : : playback 1 : capture 1 // VOIP设备
00-09: FE_ST_FM (*) : : playback 1
00-10: FE_ST_FM_C (*) : : capture 1
00-11: FE_ST_VOICE_C (*) : : capture 1 // 通话录音设备
00-12: FE_ST_LOOP (*) : : playback 1 : capture 1
00-14: FE_ST_A2DP_PCM (*) : : playback 1
00-15: FE_ST_CAPTURE_FM_DSP (*) : : capture 1
00-16: FE_ST_CAPTURE_BTSCO_DSP (*) : : capture 1 // 蓝牙录音设备
00-17: FE_ST_FM_DSP (*) : : playback 1
00-18: FE_ST_DUMP (*) : : capture 1
00-19: FE_ST_BTCAP_AP (*) : : capture 1
00-51: FE_ST_TEST_CODEC (*) : : playback 1 : capture 1
00-55: FE_ST_VOICE_PCM_P (*) : : playback 1
00-57: FE_ST_MM_P (*) : : playback 1
# amixer cget numid=149
numid=149,iface=MIXER,name='VBC_DSP_VOICE_CAPTURE_TYPE'
; type=ENUMERATED,access=rw------,values=1,items=3
; Item #0 'VOICE_CAPTURE_DOWNLINK' // 下行
; Item #1 'VOICE_CAPTURE_UPLINK' // 上行
; Item #2 'VOICE_CAPTURE_UPLINK_DOWNLINK' // 上下行
: values=0
录音本身:
audio_framework层到HDF层:
- 有蓝牙遥控器rcu hdiadapter,往下进入到audio_host拉起rcu驱动
- 有蓝牙遥控器rcu impl接口,打开相关声卡设备。
4 基于社区的方案实现录音流程
audio_framework侧增加framework的设备连接,以及ble蓝牙低功耗与hdi层的对接。
HDI侧a. 在CreateCapture中实现蓝牙录音流程,创建capture实现蓝牙录音流程
int32_t BluetoothCapturerSourceInner::CreateCapture(struct AudioPort &capturePort)
{Trace trace("BluetoothCapturerSourceInner::CreateCapture"); struct AudioSampleAttributes param; // User needs to set InitAttrsCapture(param); param.sampleRate = attr_.sampleRate; param.format = ConvertToHdiFormat(attr_.format); param.isBigEndian = attr_.isBigEndian; param.channelCount = attr_.channel; param.silenceThreshold = attr_.bufferSize; param.frameSize = param.format * param.channelCount; param.startThreshold = DEEP_BUFFER_CAPTURE_PERIOD_SIZE / (param.frameSize); struct AudioDeviceDescriptor deviceDesc; deviceDesc.portId = capturePort.portId; deviceDesc.pins = PIN_IN_MIC; deviceDesc.desc = nullptr; AUDIO_INFO_LOG("create capture sourceName:%{public}s, " \ "rate:%{public}u channel:%{public}u format:%{public}u, devicePin:%{public}u", halName_.c_str(), param.sampleRate, param.channelCount, param.format, deviceDesc.pins); int32_t ret = audioAdapter_->CreateCapture(audioAdapter_, &deviceDesc, ¶m, &audioCapture_); CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr && ret >=0, ERR_NOT_STARTED, "create capture failed"); return 0;
}
b. 在BluetoothCapturerSourceInner::Start中用于启动蓝牙音频捕获功能
int32_t BluetoothCapturerSourceInner::Start(void)
{
std::lock_guard<std::mutex> statusLock(statusMutex_);
AUDIO_INFO_LOG("sourceName %{public}s", halName_.c_str());
Trace trace("BluetoothCapturerSourceInner::Start");
InitLatencyMeasurement();
#ifdef FEATURE_POWER_MANAGER
std::shared_ptr<PowerMgr::RunningLock> keepRunningLock;
if (runningLockManager_ == nullptr) {
keepRunningLock = PowerMgr::PowerMgrClient::GetInstance().CreateRunningLock("AudioBluetoothCapturer",
PowerMgr::RunningLockType::RUNNINGLOCK_BACKGROUND_AUDIO);
if (keepRunningLock) {
runningLockManager_ = std::make_shared<AudioRunningLockManager<PowerMgr::RunningLock>> (keepRunningLock);
}
}
if (runningLockManager_ != nullptr) {
AUDIO_INFO_LOG("keepRunningLock lock result: %{public}d",
runningLockManager_->Lock(RUNNINGLOCK_LOCK_TIMEOUTMS_LASTING));
} else {
AUDIO_WARNING_LOG("keepRunningLock is null, capture can not work well");
}
#endif
dumpFileName_ = halName_ + "_" + std::to_string(attr_.sourceType) + "_" + GetTime()
+ "_bluetooth_source_" + std::to_string(attr_.sampleRate) + "_" + std::to_string(attr_.channel)
+ "_" + std::to_string(attr_.format) + ".pcm";
DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, dumpFileName_, &dumpFile_);
if (!started_) {
if (audioCapturerSourceCallback_ != nullptr) {
audioCapturerSourceCallback_->OnCapturerState(true);
}
int32_t ret = audioCapture_->control.Start(reinterpret_cast<AudioHandle>(audioCapture_));
if (ret < 0) {
#ifdef FEATURE_POWER_MANAGER
if (runningLockManager_ != nullptr) {
AUDIO_WARNING_LOG("capturer start failed, keepRunningLock unLock");
runningLockManager_->UnLock();
} else {
AUDIO_WARNING_LOG("capturer start failed, try unlock but KeepRunningLock is null!");
}
#endif
return ERR_NOT_STARTED;
}
started_ = true;
}
return SUCCESS;
}
c. SetVolume设置音量的实现
int32_t BluetoothCapturerSourceInner::SetVolume(float left, float right)
{
float volume;
CHECK_AND_RETURN_RET_LOG(audioCapture_ != nullptr, ERR_INVALID_HANDLE,
"SetVolume failed audioCapture_ null");
rightVolume_ = right;
leftVolume_ = left;
if ((leftVolume_ == 0) && (rightVolume_ != 0)) {
volume = rightVolume_;
} else if ((leftVolume_ != 0) && (rightVolume_ == 0)) {
volume = leftVolume_;
} else {
volume = (leftVolume_ + rightVolume_) / HALF_FACTOR;
}
audioCapture_->volume.SetVolume(reinterpret_cast<AudioHandle>(audioCapture_), volume);
return SUCCESS;
}
d. 停止蓝牙音频录制的实现
int32_t BluetoothCapturerSourceInner::Stop(void)
{
Trace trace("BluetoothCapturerSourceInner::Stop");
std::promise<void> promiseEnsueThreadLock;
auto futureWaitThreadLock = promiseEnsueThreadLock.get_future();
std::thread threadAsyncStop([&promiseEnsueThreadLock, this] {
std::lock_guard<std::mutex> statusLock(statusMutex_);
promiseEnsueThreadLock.set_value();
DoStop();
});
futureWaitThreadLock.get();
threadAsyncStop.detach();
return SUCCESS;
}
1.定义rcu相关接口,通过audiohost拉起rcu驱动。
struct AudioDeviceDescriptor devDesc;中的
enum AudioPortPin {
PIN_NONE = 0x0u, /**< Invalid pin */
PIN_OUT_SPEAKER = 0x1u, /**< Speaker output pin */
PIN_OUT_HEADSET = 0x2u, /**< Wired headset pin for output */
PIN_OUT_LINEOUT = 0x4u, /**< Line-out pin */
PIN_OUT_HDMI = 0x8u, /**< HDMI output pin */
PIN_OUT_USB = 0x10u, /**< USB output pin */
PIN_OUT_USB_EXT = 0x20u, /**< Extended USB output pin*/
PIN_OUT_EARPIECE = 0x30u, /**< Earpiece output pin */
PIN_OUT_BLUETOOTH_SCO = 0x40u, /**< Bluetooth SCO output pin */
PIN_OUT_DAUDIO_DEFAULT = 0x80u,
PIN_OUT_HEADPHONE = 0x100u, /**< Wired headphone output pin*/
PIN_OUT_USB_HEADSET = 0x200u, /**< ARM USB out pin */
PIN_OUT_BLUETOOTH_A2DP = 0x300u, /**< Bluetooth a2dp output pin */
PIN_IN_MIC = 0x8000001u, /**< Microphone input pin */
PIN_IN_HS_MIC = 0x8000002u, /**< Wired headset microphone pin for input */
PIN_IN_LINEIN = 0x8000004u, /**< Line-in pin */
PIN_IN_USB_EXT = 0x8000008u, /**< Extended USB input pin*/
PIN_IN_BLUETOOTH_SCO_HEADSET = 0x8000010u, /**< Bluetooth SCO headset input pin */
PIN_IN_USB_HEADSET = 0x8000040u, /**< ARM USB input pin */
};在枚举中添加PIN_IN_RCU的引脚定义
a.HdiServiceCreateCapture创建音频捕获(录音)服务
int32_t HdiServiceCreateCapture(const struct HdfDeviceIoClient *client,
struct HdfSBuf *data, struct HdfSBuf *reply)
{
if (client == nullptr || data == nullptr || reply == nullptr) {
return AUDIO_HAL_ERR_INVALID_PARAM;
}
struct AudioAdapter *adapter = nullptr;
struct AudioDeviceDescriptor devDesc;
struct AudioSampleAttributes attrs;
struct AudioCapture *capture = nullptr;
const char *adapterName = nullptr;
uint32_t capturePid = 0;
if ((adapterName = HdfSbufReadString(data)) == nullptr) {
HDF_LOGE("%{public}s: adapterNameCase Is NULL", __func__);
return AUDIO_HAL_ERR_INVALID_PARAM;
}
if (!HdfSbufReadUint32(data, &capturePid)) {
return AUDIO_HAL_ERR_INTERNAL;
}
HDF_LOGE("HdiServiceCreatRender: capturePid = %{public}u", capturePid);
int32_t ret = GetInitCapturePara(data, &devDesc, &attrs);
if (ret < 0) {
HDF_LOGE("%{public}s: GetInitCapturePara fail", __func__);
return AUDIO_HAL_ERR_INTERNAL;
}
if (AudioAdapterListGetAdapter(adapterName, &adapter)) {
HDF_LOGE("%{public}s: fail", __func__);
return AUDIO_HAL_ERR_INTERNAL;
}
if (adapter == nullptr) {
HDF_LOGE("%{public}s: adapter is NULL!", __func__);
return AUDIO_HAL_ERR_INVALID_PARAM;
}
const int32_t priority = attrs.type;
ret = AudioCreateCaptureCheck(adapterName, priority);
if (ret < 0) {
HDF_LOGE("%{public}s: AudioCreateCaptureCheck: Capture is working can not replace!", __func__);
return ret;
}
ret = adapter->CreateCapture(adapter, &devDesc, &attrs, &capture);
if (capture == nullptr || ret < 0) {
HDF_LOGE("%{public}s: Failed to CreateCapture", __func__);
return AUDIO_HAL_ERR_INTERNAL;
}
if (AudioAddCaptureInfoInAdapter(adapterName, capture, adapter, priority, capturePid)) {
HDF_LOGE("%{public}s: AudioAddCaptureInfoInAdapter", __func__);
adapter->DestroyCapture(adapter, capture);
return AUDIO_HAL_ERR_INTERNAL;
}
return AUDIO_HAL_SUCCESS;
}
b.AudioAddCaptureInfoInAdapter添加关于音频捕获实例的参数。
int32_t AudioAddCaptureInfoInAdapter(const char *adapterName, struct AudioCapture *capture,
const struct AudioAdapter *adapter, const int32_t priority, uint32_t capturePid)
{
int32_t i;
int32_t num;
if (adapterName == nullptr || adapter == nullptr || capture == nullptr) {
HDF_LOGE("%{public}s: input para is NULL. ", __func__);
return HDF_FAILURE;
}
if (g_renderAndCaptureManage == nullptr) {
return HDF_FAILURE;
}
num = (g_serverAdapterNum > MAX_AUDIO_ADAPTER_NUM_SERVER) ? MAX_AUDIO_ADAPTER_NUM_SERVER : g_serverAdapterNum;
for (i = 0; i < num; i++) {
if (g_renderAndCaptureManage[i].adapterName == nullptr) {
return HDF_FAILURE;
}
if (!strcmp(g_renderAndCaptureManage[i].adapterName, adapterName)) {
g_renderAndCaptureManage[i].captureStatus = 1;
g_renderAndCaptureManage[i].capturePriority = priority;
g_renderAndCaptureManage[i].capture = capture;
g_renderAndCaptureManage[i].capturePid = capturePid;
return HDF_SUCCESS;
}
}
HDF_LOGE("%{public}s: Can not find Adapter! ", __func__);
return HDF_FAILURE;
}
c.SetupRcuInterface基于适配器名称来设置RCU接口
bool SetupRcuInterface(struct AudioHwAdapter *hwAdapter, const struct AudioAdapterDescriptor *desc)
{
bool ret = false;
if (strcmp(desc->adapterName, "rcu_fast") == 0) {
HDF_LOGI("%{public}s, fast set up", __func__);
ret = OHOS::Rcu::FastSetUp();
} else if (strcmp(desc->adapterName, "rcu_hdap") == 0) {
HDF_LOGI("%{public}s, hdap set up", __func__);
ret = OHOS::Rcu::SetUpCapture();
} else {
HDF_LOGI("%{public}s, normal set up", __func__);
ret = OHOS::Rcu::SetUp();
}
return ret;
#endif
}
d.HdiServiceCaptureStart用于启动音频捕获服务
int32_t HdiServiceCaptureStart(const struct HdfDeviceIoClient *client, struct HdfSBuf *data, struct HdfSBuf *reply)
{
if (client == nullptr || data == nullptr || reply == nullptr) {
return AUDIO_HAL_ERR_INVALID_PARAM;
}
struct AudioCapture *capture = nullptr;
int ret = AudioAdapterListCheckAndGetCapture(&capture, data);
if (ret < 0) {
return ret;
}
return capture->control.Start((AudioHandle)capture);
}
更多推荐
所有评论(0)