RK系列SDK -- Android HFP蓝牙通话音频处理(蓝牙音箱方案)

说明:本文适用于 RK 作为蓝牙设备的蓝牙通话设计。硬件上,BT 芯片的 PCM 时钟和数据线直接连接到 RK 芯片端的一组 i2s 。软件上,需要将 BT 芯片注册成一个声卡。

BT HFP 通话数据流程:

Downlink:
远端信号 -> 蓝牙端 -> AP -> BT SoundCard -> PCM -> SOC SoundCard -> 输出设备
Uplink:
远端信号 <- 蓝牙端 <- AP <- BT SoundCard <- PCM <- SOC SoundCard <- 输入设备

(注:以下处理以 RK3326_ANDROID8.1 为例,其他安卓版本均可参考下述代码实现)

BT 声卡 DTS 配置:

1、蓝牙端 i2s 作主,提供 PCM 时钟:

	bt-sound {
   
		compatible = "simple-audio-card";
		simple-audio-card,format = "dsp_b";
		simple-audio-card,bitclock-inversion = <1>;
		simple-audio-card,mclk-fs = <256>;
		simple-audio-card,name = "rockchip,bt";
		simple-audio-card,bitclock-master = <&sound2_master>;
		simple-audio-card,frame-master = <&sound2_master>;
		simple-audio-card,cpu {
   
			sound-dai = <&i2s2_2ch>;//RK3326 i2s2_2ch
		};
		sound2_master:simple-audio-card,codec {
   
			sound-dai = <&bt_sco>;
		};
	};

	bt_sco: bt-sco {
   
		compatible = "delta,dfbmcs320";
		#sound-dai-cells = <0>;
		status = "okay";
	};

2、RK i2s 作主,提供 PCM 时钟:

bt-sound {
   
		compatible = "simple-audio-card";
		simple-audio-card,format = "dsp_b";
		simple-audio-card,bitclock-inversion = <1>;
		simple-audio-card,mclk-fs = <256>;
		simple-audio-card,name = "rockchip,bt";
		simple-audio-card,cpu {
   
			sound-dai = <&i2s2_2ch>;//RK3326 i2s2_2ch
		};
		simple-audio-card,codec {
   
			sound-dai = <&bt_sco>;
		};
	};

	bt_sco: bt-sco {
   
		compatible = "delta,dfbmcs320";
		#sound-dai-cells = <0>;
		status = "okay";
	};
HAL层处理:

hardware/rockchip/audio/tinyalsa_hal

diff --git a/tinyalsa_hal/audio_hw.c b/tinyalsa_hal/audio_hw.c
index 0a35b80..8fef004 100755
--- a/tinyalsa_hal/audio_hw.c
+++ b/tinyalsa_hal/audio_hw.c
@@ -36,7 +36,7 @@
  * @date    2015-08-24
  */
 
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0
 #define LOG_TAG "AudioHardwareTiny"
 
 #include "alsa_audio.h"
@@ -47,13 +47,24 @@
 #include "audio_bitstream.h"
 #include "audio_setting.h"
 
+
+#include "speex/speex_echo.h"
+#include "speex/speex_preprocess.h"
+
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
+//#define BT_HFP_DUMP_FAR_IN 		//touch /data/fd_far_in.pcm 		8K 
+//#define BT_HFP_DUMP_NEAR_OUT		//touch /data/fd_near_out.pcm	 	48k
+//#define BT_HFP_DUMP_NEAR_IN		//touch /data/fd_near_in.pcm		48k
+//#define BT_HFP_DUMP_FAR_OUT		//touch /data/fd_far_out.pcm		8k
+
 //#define ALSA_DEBUG
 #ifdef ALSA_IN_DEBUG
 FILE *in_debug;
 #endif
 
+bool hfp_status = false;
+
 int in_dump(const struct audio_stream *stream, int fd);
 int out_dump(const struct audio_stream *stream, int fd);
 
@@ -123,6 +134,432 @@ int get_input_source_id(audio_source_t source)
     }
 }
 
+
+int SCO_PCM_FAR_IN = 1;    // read pcm date for bt pcm  sound card
+int SCO_PCM_FAR_OUT = 1;   // out to bt pcm sound card
+int SCO_PCM_NEAR_IN = 0;   // mic in sound card
+int SCO_PCM_NEAR_OUT = 0;  // speaker out sound card
+//#define SPEEX_AEC
+#ifdef SPEEX_AEC
+//#define AEC_DUMP
+#endif
+void volume_process(const void *buffer, size_t length, float volume) {
   
+
+	short * buffer_end = (short*)buffer + (length/2);
+	short * pcmData = (short *)buffer;
+
+	while (pcmData < buffer_end) {
   
+		*pcmData = (short)((float)*pcmData * volume);
+		++pcmData;
+	}
+}
+
+#define INT16_MIN (-32768)
+#define INT16_MAX (32767)
+/*left & right channel right mix data*/
+void stereo_lr_mix(void * indata, int bytes)
+{
   
+	int i = 0;
+	float channell = 0.0;
+	float channelr = 0.0;
+	float channelmix = 0.0;
+	short *buffer = (short *)indata;
+
+	for (i = 0; i < bytes / 2 ; i = i + 2) {
   
+		channell = (float)(((short *)buffer)[i]);
+		channelr = (float)(((short *)buffer)[i + 1]);
+		if ((channell > 0.0) && (channelr > 0.0)) {
   
+			channelmix = (channell + channelr) - ((channell * channelr) / INT16_MAX);
+		} else if ((channell < 0.0) && (channelr < 0.0)) {
   
+			channelmix = (channell + channelr) - ((channell * channelr) / INT16_MIN);
+		} else {
   
+			channelmix = channell + channelr;
+		}
+		((short *)buffer)[i] = ((short *)buffer)[i + 1] = (short)channelmix;
+	}
+}
+/*left channel is noise data so copy right to left*/
+void stereo_rtol(void * indata, int bytes)
+{
   
+	int i = 0;
+	short 
  • 0
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值