音频PCM数据淡入淡出(可视化)
📎 原始文档:https://www.kdocs.cn/l/ckIoro2KgcXO 音频PCM数据淡入淡出(可视化)
背景
客户提出了一些功能,如:
- APP上可以调整TWS耳机的左右耳的音量平衡,即APP下发指令控制音量大小偏向左边或着右边。
- 有时候需要将音乐的声音静音和解除静音,但是听感要平滑。 实现该功能的前提下,需要满足以下条件:
- 保障耳机的本地音量控制流程不受影响。
- 调整左右音量平衡时,声音处理要平滑,尽量不能有杂音。
方案
编写一个对音频PCM数据进行淡入淡出至目标音量的流程即可。
例程
接口
volatile s16 user_vol_fade = 16384;
static s16 balance_vol_fade = 16384;
s16 get_balance_vol_fade(void)
{
return balance_vol_fade;
}
void set_balance_vol_fade(s16 vol)
{
printf("%s\n",__func__);
os_mutex_pend(&dvol_attr.mutex, 0);
user_vol_fade = vol;
os_mutex_post(&dvol_attr.mutex);
}
int user_music_digital_vol_balance(s16 target_vol, u16 step, void *data, u32 len,u8 bit_wide)
{
s32 valuetemp;
s16 *buf;
s32 *buf32;
os_mutex_pend(&dvol_attr.mutex, 0);
if (bit_wide) {
buf32 = data;
len >>= 2;
} else {
buf = data;
len >>= 1; //byte to point
}
s16 vol_target = target_vol;
for (u32 i = 0; i < len; i += 2) {
if (balance_vol_fade > vol_target) {
balance_vol_fade -= step;
if (balance_vol_fade < vol_target) {
balance_vol_fade = vol_target;
}
} else if (balance_vol_fade < vol_target) {
balance_vol_fade += step;
if (balance_vol_fade > vol_target) {
balance_vol_fade = vol_target;
}
}
if (bit_wide) {
//putchar('j');
valuetemp = buf32[i];
if (valuetemp < 0) {
/*负数先转换成正数,运算完再转换回去,是为了避免负数右移位引入1的误差,增加底噪*/
valuetemp = -valuetemp;
/*rounding处理(加入0.5),减少小信号时候的误差和谐波幅值*/
valuetemp = ((long long)valuetemp * (long long)balance_vol_fade) >> DVOL_RESOLUTION ;
valuetemp = -valuetemp;
} else {
valuetemp = ((long long)valuetemp * (long long)balance_vol_fade) >> DVOL_RESOLUTION ;
}
/*饱和处理*/
if (valuetemp > 8388607) { //2^23 -1
valuetemp = 8388607;
} else if (valuetemp < -8388608) { //-2^23
valuetemp = -8388608;
}
buf32[i] = valuetemp;//
///right channel
valuetemp = buf32[i + 1];
if (valuetemp < 0) {
/*负数先转换成正数,运算完再转换回去,是为了避免负数右移位引入1的误差,增加底噪*/
valuetemp = -valuetemp;
valuetemp = ((long long)valuetemp * (long long)balance_vol_fade) >> DVOL_RESOLUTION ;
valuetemp = -valuetemp;
} else {
valuetemp = ((long long)valuetemp * (long long)balance_vol_fade) >> DVOL_RESOLUTION ;
}
/*饱和处理*/
if (valuetemp > 8388607) { //2^23 -1
valuetemp = 8388607;
} else if (valuetemp < -8388608) { //-2^23
valuetemp = -8388608;
}
buf32[i + 1] = valuetemp;
} else {
valuetemp = buf[i];
if (valuetemp < 0) {
/*负数先转换成正数,运算完再转换回去,是为了避免负数右移位引入1的误差,增加底噪*/
valuetemp = -valuetemp;
/*rounding处理(加入0.5),减少小信号时候的误差和谐波幅值*/
valuetemp = (valuetemp * balance_vol_fade) >> DVOL_RESOLUTION ;
valuetemp = -valuetemp;
} else {
valuetemp = (valuetemp * balance_vol_fade) >> DVOL_RESOLUTION ;
}
/*饱和处理*/
buf[i] = (s16)data_sat_s16(valuetemp);
///right channel
valuetemp = buf[i + 1];
if (valuetemp < 0) {
/*负数先转换成正数,运算完再转换回去,是为了避免负数右移位引入1的误差,增加底噪*/
valuetemp = -valuetemp;
valuetemp = (valuetemp * balance_vol_fade) >> DVOL_RESOLUTION ;
valuetemp = -valuetemp;
} else {
valuetemp = (valuetemp * balance_vol_fade) >> DVOL_RESOLUTION ;
}
/*饱和处理*/
buf[i + 1] = (s16)data_sat_s16(valuetemp);
}
}
// printf("f = %d\n",balance_vol_fade);
os_mutex_post(&dvol_attr.mutex);
return 0;
}
audio_dvol.c是基于SDK“TWS耳机 AC701N1.0.0(patch_07)”的源文件,添加了上述代码块。
audio_dvol.c
用例
// 设置目标音量(0~16384)
void set_balance_vol_fade(s16 vol)
// 运行淡入淡出函数
int user_music_digital_vol_balance(s16 target_vol, u16 step, void *data, u32 len,u8 bit_wide)
基于上图,客户可以调用set_balance_vol_fade,在不影响本地音量控制流程的情况下,实现对A2DP音频PCM数据音量的控制。