Files
99_7018_lmx/cpu/br28/audio_hearing/audio_sidetone.c
2025-10-29 13:10:02 +08:00

170 lines
5.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "generic/typedef.h"
#include "board_config.h"
#include "media/includes.h"
#include "audio_config.h"
#include "sound_device.h"
#include "audio_sidetone.h"
#include "system/task.h"
#if TCFG_SIDETONE_ENABLE
extern struct audio_dac_hdl dac_hdl;
#define SIDETONE_BUF_LEN 256
#define SIDETONE_READBUF_LEN 64 //中断点数设为32则每次数据长度为64
static struct audio_sidetone_hdl {
s16 *sidetone_buf;
#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)
s16 *sidetone_buf_lr;
#endif/*(TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)*/
cbuffer_t cbuf;
OS_SEM sem;
bool busy; //检测任务是否在阻塞态
bool suspend; //暂停监听
struct audio_dac_channel dac_ch;
struct audio_dac_channel_attr attr;
};
static struct audio_sidetone_hdl *sidetone_hdl = NULL;
static inline void audio_pcm_mono_to_dual(s16 *dual_pcm, s16 *mono_pcm, int points)
{
s16 *mono = mono_pcm;
int i = 0;
u8 j = 0;
for (i = 0; i < points; i++, mono++) {
*dual_pcm++ = *mono;
*dual_pcm++ = *mono;
}
}
static void audio_sidetone_task(void)
{
if (!sidetone_hdl) {
sidetone_hdl = zalloc(sizeof(struct audio_sidetone_hdl));
if (!sidetone_hdl) {
printf("zalloc sidetone_hdl err\n");
return;
}
}
sidetone_hdl->suspend = 1;
sidetone_hdl->sidetone_buf = zalloc(SIDETONE_BUF_LEN);
#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)
sidetone_hdl->sidetone_buf_lr = zalloc(SIDETONE_READBUF_LEN * 2);
#endif/*(TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)*/
cbuf_init(&sidetone_hdl->cbuf, sidetone_hdl->sidetone_buf, SIDETONE_BUF_LEN);
os_sem_create(&sidetone_hdl->sem, 0);
audio_dac_new_channel(&dac_hdl, &sidetone_hdl->dac_ch);
sidetone_hdl->attr.delay_time = 6;
sidetone_hdl->attr.protect_time = 8;
sidetone_hdl->attr.write_mode = WRITE_MODE_BLOCK;
audio_dac_channel_set_attr(&sidetone_hdl->dac_ch, &sidetone_hdl->attr);
sound_pcm_dev_start(&sidetone_hdl->dac_ch, 16000, app_audio_get_volume(APP_AUDIO_STATE_CALL));
while (1) {
sidetone_hdl->busy = 0;
os_sem_pend(&sidetone_hdl->sem, 0);
sidetone_hdl->busy = 1;
u16 rlen = cbuf_read(&sidetone_hdl->cbuf, sidetone_hdl->sidetone_buf, SIDETONE_READBUF_LEN);
if (rlen != SIDETONE_READBUF_LEN) {
printf("rlen err : %d\n", rlen);
}
#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)
audio_pcm_mono_to_dual(sidetone_hdl->sidetone_buf_lr, sidetone_hdl->sidetone_buf, rlen >> 1);
u16 wlen = sound_pcm_dev_write(&sidetone_hdl->dac_ch, sidetone_hdl->sidetone_buf_lr, rlen <<= 1);
#else
u16 wlen = sound_pcm_dev_write(&sidetone_hdl->dac_ch, sidetone_hdl->sidetone_buf, rlen);
#endif
if (wlen != rlen) {
printf("wlen err : %d\n", wlen);
}
}
}
/*
*********************************************************************
* Audio Sidetone Inbuf
* Description: 通话监听数据流输入
* Arguments : data 输入数据地址
* len 输入数据长度
* Return : None.
* Note(s) : None.
*********************************************************************
*/
void audio_sidetone_inbuf(s16 *data, u16 len)
{
if (sidetone_hdl && sidetone_hdl->suspend) {
os_sem_post(&sidetone_hdl->sem);
u16 wlen = cbuf_write(&sidetone_hdl->cbuf, data, len);
if (wlen != len) {
printf("wlen = %d, len = %d\n", wlen, len);
}
}
}
/*
*********************************************************************
* Audio Sidetone Open
* Description: 打开通话监听
* Arguments : None.
* Return : 0成功 其他失败
* Note(s) : None.
*********************************************************************
*/
int audio_sidetone_open(void)
{
if (!sidetone_hdl) {
task_create(audio_sidetone_task, NULL, "sidetone");//创建监听任务
return 0;
}
return -1;
}
/*
*********************************************************************
* Audio Sidetone Close
* Description: 关闭通话监听
* Arguments : None.
* Return : 0成功 其他失败
* Note(s) : None.
*********************************************************************
*/
int audio_sidetone_close(void)
{
if (!sidetone_hdl) {
printf("sidetone already close\n");
return -1;
}
if (!sidetone_hdl->busy) { //任务处于挂起态
sound_pcm_dev_stop(&sidetone_hdl->dac_ch); //关闭监听
task_kill("sidetone");
free(sidetone_hdl->sidetone_buf);
#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)
free(sidetone_hdl->sidetone_buf_lr);
#endif/*(TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)*/
free(sidetone_hdl);
sidetone_hdl = NULL;
return 0;
}
return -2;
}
/*
*********************************************************************
* Audio Sidetone Suspend
* Description: 暂停通话监听
* Arguments : None.
* Return : 0成功 其他失败
* Note(s) : None.
*********************************************************************
*/
int audio_sidetone_suspend(void)
{
if (sidetone_hdl) {
sidetone_hdl->suspend ? (sidetone_hdl->suspend = 0) : (sidetone_hdl->suspend = 1);
return 0;
}
return -1;
}
#endif/*TCFG_SIDETONE_ENABLE*/