170 lines
5.3 KiB
C
170 lines
5.3 KiB
C
|
|
#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*/
|