pure sdk for main
This commit is contained in:
@@ -0,0 +1,568 @@
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "string.h"
|
||||
#include "osal/task.h"
|
||||
#include "osal/string.h"
|
||||
#include "hal/auadc.h"
|
||||
#include "utlist.h"
|
||||
#include "audio_adc.h"
|
||||
#include "osal_file.h"
|
||||
#include "stream_frame.h"
|
||||
#include "osal_file.h"
|
||||
#include "dev/spi/hgspi_xip.h"
|
||||
#include "t_queue.h"
|
||||
#include "csi_kernel.h"
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
#define ADUIO_MALLOC os_malloc_psram
|
||||
#define ADUIO_FREE os_free_psram
|
||||
#define AUDIONUM (16) //因为带了psram,如果需要容忍更多容错防止丢帧,这里可以增加更多节点
|
||||
#define AUDIOSRAM_NUM (4)//sram的空间个数,所以单个节点不能太大,否则有可能有问题空间不够
|
||||
#else
|
||||
#define ADUIO_MALLOC os_malloc
|
||||
#define ADUIO_FREE os_free
|
||||
#define AUDIONUM (4)
|
||||
#endif
|
||||
|
||||
#define HIGHPASS_FILTER 0
|
||||
|
||||
#define ROUNDING_14(data) ( (short int)( ( ((int)( ( (int)data) + ((int)(1<<13)))) >> 14) & 0xFFFF))
|
||||
|
||||
#if HIGHPASS_FILTER == 1
|
||||
//adc采集的前面75个sample点不能用,经过高通滤波后,才可以用
|
||||
#define AUDIOLEN (960)
|
||||
#define FILTER_SAMPLE_LEN 76
|
||||
#define REAL_FILTER_SAMPLE_LEN 75
|
||||
#else
|
||||
#define AUDIOLEN (1024)
|
||||
#define FILTER_SAMPLE_LEN 0
|
||||
#endif
|
||||
|
||||
#define SOFT_GAIN (8)
|
||||
|
||||
typedef uint32_t (*highpass_filter_100hz_asm_func)(int16_t *p_cur);
|
||||
|
||||
struct audio_ad_config;
|
||||
//返回值是一个buf,录音的buf,priv_el则是应用层的一个结构,el_point则是一个指针地址,audio_set_buf在返回buf前同时要配置el_point的值(最后在audio_get_buf的时候会需要调用)
|
||||
typedef void *(*set_buf)(void *priv_el,void *el_point);
|
||||
//priv_el则是应用层的一个结构,el_point则是可以寻找到buf的一个结构体,el_point的值是audio_set_buf赋值的
|
||||
typedef void (*get_buf)(void *priv_el,void *el_point);
|
||||
|
||||
typedef int32 (*audio_ad_read)(struct audio_ad_config *audio, void* buf, uint32 len);
|
||||
|
||||
struct audio_ad_config
|
||||
{
|
||||
//struct hgpdm_v0* pdm_hdl;
|
||||
struct auadc_device *adc;
|
||||
void *current_node;
|
||||
void *reg_node;
|
||||
set_buf set_buf;
|
||||
get_buf get_buf;
|
||||
int buf_size;
|
||||
//私有结构元素
|
||||
void *priv_el;
|
||||
audio_ad_read irq_func;
|
||||
};
|
||||
|
||||
void *audio_custom_malloc(uint32_t size)
|
||||
{
|
||||
return os_malloc(size);
|
||||
}
|
||||
|
||||
void audio_custom_free(void *ptr)
|
||||
{
|
||||
os_free(ptr);
|
||||
}
|
||||
|
||||
void audio_adc_irq(uint32 irq, uint32 irq_data)
|
||||
{
|
||||
struct audio_ad_config *audio_ad = (struct audio_ad_config *)irq_data;
|
||||
struct audio_ad_config *priv = (struct audio_ad_config*)audio_ad;
|
||||
void *buf;
|
||||
|
||||
if(irq == AUADC_IRQ_FLAG_HALF)
|
||||
{
|
||||
if(!priv->reg_node)
|
||||
{
|
||||
buf = priv->set_buf(priv->priv_el,&priv->reg_node);
|
||||
//如果reg_node为NULL,则音频录音buf还是原来的buf
|
||||
if(priv->reg_node)
|
||||
{
|
||||
priv->irq_func(audio_ad , buf, priv->buf_size);
|
||||
}
|
||||
}
|
||||
//这里由于其他地方关闭中断导致错过了很多中断,这里需要处理异常数据(这些数据依然发送,实际已经不再正确的音频)
|
||||
else
|
||||
{
|
||||
//如果相等,证明上一次执行了full中断
|
||||
if(priv->current_node == priv->reg_node)
|
||||
{
|
||||
priv->current_node = NULL;
|
||||
}
|
||||
//不相等,说明可以发送一些节点,实际数据并不是所需要,但还是要管理buf
|
||||
else
|
||||
{
|
||||
priv->get_buf(priv->priv_el,priv->current_node);
|
||||
priv->current_node = priv->reg_node;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(irq == AUADC_IRQ_FLAG_FULL)
|
||||
{
|
||||
//半中断有配置新的buf,则将完成的录音帧通知应用层,如果为NULL,则代表没有配置新的buf,只能使用旧的buf
|
||||
if(priv->reg_node)
|
||||
{
|
||||
if(priv->current_node)
|
||||
{
|
||||
priv->get_buf(priv->priv_el,priv->current_node);
|
||||
}
|
||||
priv->current_node = priv->reg_node;
|
||||
priv->reg_node = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void audio_adc_register(void *audio_hdl,void *priv_el,int play_size,set_buf audio_set_buf,get_buf audio_get_buf)
|
||||
{
|
||||
struct audio_ad_config *priv = (struct audio_ad_config*)audio_hdl;
|
||||
priv->buf_size = play_size;
|
||||
priv->set_buf = audio_set_buf;
|
||||
priv->get_buf = audio_get_buf;
|
||||
priv->priv_el = priv_el;
|
||||
}
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
static void *audio_set_buf(void *priv_el,void *el_point)
|
||||
{
|
||||
void *buf = NULL;
|
||||
stream *s = (stream *)priv_el;
|
||||
struct audio_adc_s *audio_priv = (struct audio_adc_s*)s->priv;
|
||||
struct tqueue_s *queue_data;
|
||||
|
||||
queue_data = tqueue_pop(audio_priv->queue);
|
||||
struct tqueue_s **point = (struct tqueue_s**)el_point;
|
||||
if(queue_data)
|
||||
{
|
||||
buf = queue_data->data;
|
||||
#if HIGHPASS_FILTER == 1
|
||||
//偏移75个sample点
|
||||
buf = (uint16_t*)buf+FILTER_SAMPLE_LEN;
|
||||
#endif
|
||||
}
|
||||
*point = queue_data;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void audio_get_buf(void *priv_el,void *el_point)
|
||||
{
|
||||
stream *s = (stream *)priv_el;
|
||||
struct audio_adc_s *self_priv = (struct audio_adc_s*)s->priv;
|
||||
struct tqueue_s *queue_data = (struct tqueue_s*)el_point;
|
||||
int res;
|
||||
|
||||
if(!queue_data)
|
||||
{
|
||||
_os_printf("%s:%d err\n",__FUNCTION__,__LINE__);
|
||||
return;
|
||||
}
|
||||
|
||||
struct data_structure *data = get_src_data_f(s);
|
||||
if(data)
|
||||
{
|
||||
data->priv = queue_data;
|
||||
set_stream_data_time(data,os_jiffies());
|
||||
res = csi_kernel_msgq_put(self_priv->adc_msgq,&data,0,0);
|
||||
//正常应该保证不进这里,如果进来代表任务没有获取队列,直接配置下一个buf导致的
|
||||
if(res)
|
||||
{
|
||||
_os_printf("P");
|
||||
force_del_data(data);
|
||||
tqueue_push(self_priv->queue,queue_data);
|
||||
}
|
||||
}
|
||||
//找不到节点,则queue_data需要放回到队列里面去
|
||||
else
|
||||
{
|
||||
tqueue_push(self_priv->queue,queue_data);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
#else
|
||||
static void *audio_set_buf(void *priv_el,void *el_point)
|
||||
{
|
||||
void *buf = NULL;
|
||||
stream *s = (stream *)priv_el;
|
||||
struct data_structure *data;
|
||||
|
||||
data = get_src_data_f(s);
|
||||
struct data_structure **point = (struct data_structure**)el_point;
|
||||
if(data)
|
||||
{
|
||||
buf = get_stream_real_data(data);
|
||||
#if HIGHPASS_FILTER == 1
|
||||
//偏移75个sample点
|
||||
buf = (uint16_t*)buf+FILTER_SAMPLE_LEN;
|
||||
#endif
|
||||
}
|
||||
*point = data;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void audio_get_buf(void *priv_el,void *el_point)
|
||||
{
|
||||
stream *s = (stream *)priv_el;
|
||||
struct audio_adc_s *self_priv = (struct audio_adc_s*)s->priv;
|
||||
struct data_structure *data = (struct data_structure*)el_point;
|
||||
int res;
|
||||
if(!data)
|
||||
{
|
||||
_os_printf("%s:%d err\n",__FUNCTION__,__LINE__);
|
||||
return;
|
||||
}
|
||||
set_stream_data_time(data,os_jiffies());
|
||||
res = csi_kernel_msgq_put(self_priv->adc_msgq,&data,0,0);
|
||||
//正常应该保证不进这里,如果进来代表任务没有获取队列,直接配置下一个buf导致的
|
||||
if(res)
|
||||
{
|
||||
_os_printf("P");
|
||||
force_del_data(data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void audio_deal_task(void *arg)
|
||||
{
|
||||
stream *s = (stream *)arg;
|
||||
#if HIGHPASS_FILTER == 1
|
||||
int16_t filter_asm_buf[75] = {0};
|
||||
#endif
|
||||
int res;
|
||||
struct data_structure *data ;
|
||||
int16_t *p_buf;
|
||||
uint32_t sample_len;
|
||||
|
||||
struct audio_adc_s *self_priv = (struct audio_adc_s*)s->priv;
|
||||
#ifdef PSRAM_HEAP
|
||||
struct tqueue_s *queue_data;
|
||||
#endif
|
||||
|
||||
while(1)
|
||||
{
|
||||
res = csi_kernel_msgq_get(self_priv->adc_msgq,&data,-1);
|
||||
if(!res)
|
||||
{
|
||||
//发送
|
||||
#ifdef PSRAM_HEAP
|
||||
queue_data = (struct tqueue_s *)data->priv;
|
||||
p_buf = queue_data->data;
|
||||
sample_len = get_stream_real_data_len(data)/2;
|
||||
#else
|
||||
p_buf = get_stream_real_data(data);
|
||||
sample_len = get_stream_real_data_len(data)/2;
|
||||
#endif
|
||||
|
||||
#if HIGHPASS_FILTER == 1
|
||||
extern uint32_t highpass_filter_100hz_asm(int16_t *p_cur);
|
||||
//进行高通滤波
|
||||
uint32_t filter_sample_point;
|
||||
uint32_t i,sample_len;
|
||||
int16_t *deal_p_buf;
|
||||
highpass_filter_100hz_asm_func func;
|
||||
if(sysctrl_get_chip_dcn())
|
||||
{
|
||||
func = (highpass_filter_100hz_asm_func)get_msrom_func(MSROM_HIGHPASS_FILTER_100HZ_ASM);
|
||||
}
|
||||
else
|
||||
{
|
||||
func = highpass_filter_100hz_asm;
|
||||
}
|
||||
//实际数据的地址
|
||||
int16_t *sample_buf = p_buf+FILTER_SAMPLE_LEN ;
|
||||
|
||||
//处理要考虑原来buf数据长度是否对齐,因为滤波的函数需要连续的
|
||||
deal_p_buf = p_buf + FILTER_SAMPLE_LEN - REAL_FILTER_SAMPLE_LEN;
|
||||
memcpy((void*)deal_p_buf,(void*)filter_asm_buf,sizeof(filter_asm_buf));
|
||||
|
||||
for(i=0;i<sample_len;i++)
|
||||
{
|
||||
filter_sample_point = func(sample_buf);
|
||||
//这里使用p_buf是为了数据在buf的头部,deal_p_buf可能头部会有有空位,所以这里要注意
|
||||
*p_buf = ROUNDING_14(filter_sample_point)*SOFT_GAIN;
|
||||
sample_buf++;
|
||||
deal_p_buf++;
|
||||
p_buf++;
|
||||
}
|
||||
|
||||
//保留最后75个sample点,正常p_buf已经偏移到正常地址了
|
||||
memcpy(filter_asm_buf,deal_p_buf,sizeof(filter_asm_buf));
|
||||
#else
|
||||
uint32_t i;
|
||||
for(i=0;i<sample_len;i++)
|
||||
{
|
||||
*p_buf = (*p_buf)*SOFT_GAIN;
|
||||
p_buf++;
|
||||
}
|
||||
#endif
|
||||
data->type = SET_DATA_TYPE(SOUND,SOUND_MIC);
|
||||
send_data_to_stream(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
_os_printf("%s:%d err @@@@@@@@@@@@\n",__FUNCTION__,__LINE__);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int opcode_func(stream *s,void *priv,int opcode)
|
||||
{
|
||||
static uint8_t *adc_audio_buf = NULL;
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
s->priv = (void*)os_malloc(sizeof(struct audio_adc_s));
|
||||
struct audio_adc_s *self_priv = (struct audio_adc_s*)s->priv;
|
||||
if(s->priv)
|
||||
{
|
||||
self_priv->adc_msgq = (void*)csi_kernel_msgq_new(1,sizeof(uint8_t*));
|
||||
OS_TASK_INIT("adc_audio_deal", &self_priv->thread_hdl, audio_deal_task, s, OS_TASK_PRIORITY_ABOVE_NORMAL, 1024);
|
||||
}
|
||||
uint32_t one_buf_size = (AUDIOLEN + FILTER_SAMPLE_LEN*2);
|
||||
adc_audio_buf = ADUIO_MALLOC(AUDIONUM * one_buf_size);
|
||||
if(adc_audio_buf)
|
||||
{
|
||||
stream_data_dis_mem_custom(s);
|
||||
}
|
||||
#ifdef PSRAM_HEAP
|
||||
//申请auadc的一个临时sram空间
|
||||
//临时空间的链表头,默认这里都是可以创建成功的
|
||||
void *queue_head = self_priv->queue = tqueue_init();
|
||||
//创建多个临时内存空间
|
||||
for(int i=0;i<AUDIOSRAM_NUM;i++)
|
||||
{
|
||||
void *mem_data = (void*)os_malloc(one_buf_size);
|
||||
struct tqueue_s *queue_data = tqueue_gen_data(mem_data,audio_custom_malloc);
|
||||
tqueue_push(queue_head,queue_data);
|
||||
}
|
||||
#endif
|
||||
//绑定到对应的流
|
||||
streamSrc_bind_streamDest(s,R_RECORD_AUDIO);
|
||||
streamSrc_bind_streamDest(s,R_RTP_AUDIO);
|
||||
streamSrc_bind_streamDest(s,R_AUDIO_TEST);
|
||||
streamSrc_bind_streamDest(s,R_SPEAKER);
|
||||
streamSrc_bind_streamDest(s,R_AT_SAVE_AUDIO);
|
||||
streamSrc_bind_streamDest(s,R_AT_AVI_AUDIO);
|
||||
streamSrc_bind_streamDest(s,R_SPEECH_RECOGNITION);
|
||||
streamSrc_bind_streamDest(s,R_USB_AUDIO_MIC);
|
||||
}
|
||||
break;
|
||||
case STREAM_DATA_DIS:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
int data_num = (int)data->priv;
|
||||
data->type = DATA_TYPE_AUDIO_ADC;//设置声音的类型
|
||||
//data->priv = (void*)AUDIOLEN;
|
||||
set_stream_real_data_len(data,AUDIOLEN);
|
||||
//注册对应函数
|
||||
//data->ops = &stream_sound_ops;
|
||||
uint32_t one_buf_size = (AUDIOLEN + FILTER_SAMPLE_LEN*2);
|
||||
data->data = adc_audio_buf + (data_num)*one_buf_size;
|
||||
}
|
||||
break;
|
||||
|
||||
//音频发送之前先拷贝到psram
|
||||
case STREAM_SEND_DATA_START:
|
||||
{
|
||||
//在打开psram的情况下,才需要拷贝
|
||||
#ifdef PSRAM_HEAP
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
struct audio_adc_s *self_priv = (struct audio_adc_s*)s->priv;
|
||||
struct tqueue_s *queue_data = (struct tqueue_s *)data->priv;
|
||||
hw_memcpy(get_stream_real_data(data),queue_data->data,get_stream_real_data_len(data));
|
||||
//将priv返回队列中
|
||||
tqueue_push(self_priv->queue,queue_data);
|
||||
data->priv = NULL;
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int audio_adc_start(void *audio_hdl)
|
||||
{
|
||||
int ret = 0;
|
||||
int res = 0;
|
||||
void *buf;
|
||||
struct audio_ad_config *priv = (struct audio_ad_config*)audio_hdl;
|
||||
buf = priv->set_buf(priv->priv_el,&priv->current_node);
|
||||
if(!buf)
|
||||
{
|
||||
ret = -1;
|
||||
goto audio_adc_start_err;
|
||||
}
|
||||
priv->irq_func(priv , buf, priv->buf_size);
|
||||
audio_adc_start_err:
|
||||
return res;
|
||||
}
|
||||
|
||||
static int32 global_audio_ad_read(struct audio_ad_config *audio, void* buf, uint32 len)
|
||||
{
|
||||
auadc_read(audio->adc, buf, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static stream *global_audio_adc_s = NULL;
|
||||
//优先创建音频的流
|
||||
stream *audio_adc_stream_init(const char *name)
|
||||
{
|
||||
stream *s = open_stream_available(name,AUDIONUM,0,opcode_func,NULL);
|
||||
if(s)
|
||||
{
|
||||
global_audio_adc_s = s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
//关闭音频流
|
||||
void audio_adc_stream_deinit()
|
||||
{
|
||||
int res;
|
||||
if(global_audio_adc_s)
|
||||
{
|
||||
res = close_stream(global_audio_adc_s);
|
||||
if(!res)
|
||||
{
|
||||
global_audio_adc_s = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int audio_adc_init()
|
||||
{
|
||||
int res = 0;
|
||||
struct auadc_device *adc = (struct auadc_device *)dev_get(HG_AUADC_DEVID);
|
||||
|
||||
stream *s = NULL;
|
||||
s = audio_adc_stream_init(S_ADC_AUDIO);
|
||||
if(!s)
|
||||
{
|
||||
res = -1;
|
||||
goto audio_adc_init_err;
|
||||
}
|
||||
|
||||
struct audio_adc_s *audio_priv = (struct audio_adc_s*)s->priv;
|
||||
if(audio_priv)
|
||||
{
|
||||
struct audio_ad_config *ad_config = (struct audio_ad_config*)os_malloc(sizeof(struct audio_ad_config));
|
||||
memset(ad_config,0,sizeof(struct audio_ad_config));
|
||||
ad_config->adc = adc;
|
||||
ad_config->priv_el = s;
|
||||
audio_priv->audio_hardware_hdl = ad_config;
|
||||
audio_adc_register(ad_config,s,AUDIOLEN,audio_set_buf,audio_get_buf);
|
||||
ad_config->irq_func = global_audio_ad_read;
|
||||
auadc_open(adc, AUADC_SAMPLE_RATE_8K);
|
||||
auadc_request_irq(adc, AUADC_IRQ_FLAG_HALF | AUADC_IRQ_FLAG_FULL, (auadc_irq_hdl)audio_adc_irq, (uint32)ad_config);
|
||||
audio_adc_start(ad_config);
|
||||
}
|
||||
audio_adc_init_err:
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
int audio_adc_deinit()
|
||||
{
|
||||
struct auadc_device *adc = (struct auadc_device *)dev_get(HG_AUADC_DEVID);
|
||||
auadc_close(adc);
|
||||
stream *s = NULL;
|
||||
s = audio_adc_stream_init(S_ADC_AUDIO);
|
||||
//将对应资源释放管理好
|
||||
struct audio_adc_s *audio_priv = (struct audio_adc_s*)s->priv;
|
||||
struct audio_ad_config *ad_config = audio_priv->audio_hardware_hdl;
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
//将adc保存的流数据节点释放(因为中断被关闭),这里正常可以将资源释放不至于异常
|
||||
if(ad_config->current_node)
|
||||
{
|
||||
os_printf("adc force current data:%X\n",ad_config->current_node);
|
||||
tqueue_push(audio_priv->queue,(struct tqueue_s *)ad_config->current_node);
|
||||
ad_config->current_node = NULL;
|
||||
}
|
||||
|
||||
if(ad_config->reg_node)
|
||||
{
|
||||
os_printf("adc force reg_node data:%X\n",ad_config->reg_node);
|
||||
tqueue_push(audio_priv->queue,(struct tqueue_s *)ad_config->reg_node);
|
||||
ad_config->reg_node = NULL;
|
||||
}
|
||||
audio_adc_stream_deinit();
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int audio_adc_deinit()
|
||||
{
|
||||
struct auadc_device *adc = (struct auadc_device *)dev_get(HG_AUADC_DEVID);
|
||||
auadc_close(adc);
|
||||
stream *s = NULL;
|
||||
s = audio_adc_stream_init(S_ADC_AUDIO);
|
||||
//将对应资源释放管理好
|
||||
struct audio_adc_s *audio_priv = (struct audio_adc_s*)s->priv;
|
||||
struct audio_ad_config *ad_config = audio_priv->audio_hardware_hdl;
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
//将adc保存的流数据节点释放(因为中断被关闭),这里正常可以将资源释放不至于异常
|
||||
if(ad_config->current_node)
|
||||
{
|
||||
os_printf("adc force current data:%X\n",ad_config->current_node);
|
||||
force_del_data(ad_config->current_node);
|
||||
ad_config->current_node = NULL;
|
||||
}
|
||||
|
||||
if(ad_config->reg_node)
|
||||
{
|
||||
os_printf("adc force reg_node data:%X\n",ad_config->reg_node);
|
||||
force_del_data(ad_config->reg_node);
|
||||
ad_config->reg_node = NULL;
|
||||
}
|
||||
|
||||
audio_adc_stream_deinit();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
//这个重新打开流(但流应该没有实际被重新打开,只是获取流的句柄,然后重新初始化adc)
|
||||
int audio_adc_reinit()
|
||||
{
|
||||
stream *s = NULL;
|
||||
struct auadc_device *adc = (struct auadc_device *)dev_get(HG_AUADC_DEVID);
|
||||
//这里应该流不能被释放过,所以s一定是要在之前就存在,否则后续的逻辑会有问题
|
||||
s = audio_adc_stream_init(S_ADC_AUDIO);
|
||||
struct audio_adc_s *audio_priv = (struct audio_adc_s*)s->priv;
|
||||
if(s && audio_priv)
|
||||
{
|
||||
struct audio_ad_config *ad_config = audio_priv->audio_hardware_hdl;
|
||||
memset(ad_config,0,sizeof(struct audio_ad_config));
|
||||
ad_config->adc = adc;
|
||||
ad_config->priv_el = s;
|
||||
audio_priv->audio_hardware_hdl = ad_config;
|
||||
audio_adc_register(ad_config,s,AUDIOLEN,audio_set_buf,audio_get_buf);
|
||||
ad_config->irq_func = global_audio_ad_read;
|
||||
auadc_open(adc, AUADC_SAMPLE_RATE_8K);
|
||||
auadc_request_irq(adc, AUADC_IRQ_FLAG_HALF | AUADC_IRQ_FLAG_FULL, (auadc_irq_hdl)audio_adc_irq, (uint32)ad_config);
|
||||
audio_adc_start(ad_config);
|
||||
}
|
||||
audio_adc_stream_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef __AUDIO_ADC_H
|
||||
#define __AUDIO_ADC_H
|
||||
|
||||
|
||||
struct audio_adc_s
|
||||
{
|
||||
void *adc_msgq;
|
||||
void *audio_hardware_hdl;
|
||||
struct os_task thread_hdl;
|
||||
void *queue;
|
||||
};
|
||||
int audio_adc_init();
|
||||
#endif
|
||||
@@ -0,0 +1,934 @@
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "string.h"
|
||||
|
||||
#include "osal/task.h"
|
||||
#include "osal/semaphore.h"
|
||||
#include "osal/msgqueue.h"
|
||||
#include "osal/string.h"
|
||||
#include "hal/audac.h"
|
||||
#include "stream_frame.h"
|
||||
#include "osal_file.h"
|
||||
#include "stream_frame.h"
|
||||
#include "dev/audio/components/fade/aufade.h"
|
||||
#include "sonic_process.h"
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
#define ADUIO_MALLOC os_malloc_psram
|
||||
#define ADUIO_FREE os_free_psram
|
||||
#define ADUIO_ZALLOC os_zalloc_psram
|
||||
#define AUDIONUM (16)
|
||||
#else
|
||||
#define ADUIO_MALLOC os_malloc
|
||||
#define ADUIO_FREE os_free
|
||||
#define ADUIO_ZALLOC os_zalloc
|
||||
#define AUDIONUM (8)
|
||||
#endif
|
||||
|
||||
#define SONIC_PROCESS 0
|
||||
#define FADE_PROCESS 1
|
||||
|
||||
#define AUDIOLEN 1024
|
||||
#define CACHE_BUF_LEN 1024
|
||||
|
||||
static int prev_filter_type = 0;
|
||||
static stream *global_audio_dac_s = NULL;
|
||||
struct audio_da_config;
|
||||
typedef int32 (*audio_da_write)(struct audio_da_config *audio, void* buf, uint32 len);
|
||||
|
||||
static uint32_t empty_buf[AUDIOLEN/4];
|
||||
|
||||
#if SONIC_PROCESS
|
||||
struct sonic_process_priv {
|
||||
sonicStream sonic_s;
|
||||
int samplingRate;
|
||||
int channel;
|
||||
float pitch;
|
||||
float speed;
|
||||
struct os_task task_hdl;
|
||||
struct os_semaphore sema;
|
||||
struct data_structure *r_current_data;
|
||||
struct data_structure *s_current_data;
|
||||
};
|
||||
static struct sonic_process_priv *sonic_priv = NULL;
|
||||
#endif
|
||||
|
||||
struct audio_dac_priv {
|
||||
struct os_semaphore cache_sema;
|
||||
struct os_task cache_task_hdl;
|
||||
uint32_t s_offset;
|
||||
uint32_t d_offset;
|
||||
uint32_t res_len;
|
||||
uint32_t buf_len;
|
||||
uint32_t buf_index;
|
||||
int8_t status;
|
||||
int16_t *buf[4];
|
||||
struct data_structure *current_data;
|
||||
#if FADE_PROCESS
|
||||
struct os_msgqueue fade_msg;
|
||||
struct os_task fade_task_hdl;
|
||||
uint8_t fade_mode;
|
||||
#endif
|
||||
};
|
||||
static struct audio_dac_priv *audac_priv = NULL;
|
||||
|
||||
typedef struct audio_da_config
|
||||
{
|
||||
struct audac_device *dac;
|
||||
void *current_node;
|
||||
void *reg_node;
|
||||
audio_da_write irq_func;
|
||||
void *play_empty_buf; //作为喇叭的时候,需要配置,size与buf_size一致,可以是malloc也可以是固定,如果是malloc,需要自己去free
|
||||
int buf_size;
|
||||
uint8_t audio_hz;
|
||||
uint8_t is_empty;
|
||||
}audio_da_config;
|
||||
|
||||
audio_da_config global_audio_da;
|
||||
|
||||
int get_audio_dac_set_filter_type(void);
|
||||
void audio_dac_set_filter_type(int filter_type);
|
||||
int audio_dac_get_samplingrate(void);
|
||||
|
||||
#ifndef PSRAM_HEAP
|
||||
static void *audio_dac_get_buf(void *priv_el,void *el_point,int *buf_size)
|
||||
{
|
||||
stream *dest = (stream *)priv_el;
|
||||
struct data_structure *data_s = recv_real_data(dest);
|
||||
void *buf = NULL;
|
||||
void **point = (void**)el_point;
|
||||
if(data_s) {
|
||||
buf = get_stream_real_data(data_s);
|
||||
*buf_size = get_stream_real_data_len(data_s);
|
||||
*point = (void*)data_s;
|
||||
}
|
||||
else {
|
||||
*point = NULL;
|
||||
return NULL;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void audio_dac_free_buf(void *el_point)
|
||||
{
|
||||
struct data_structure *data_s = (struct data_structure *)el_point;
|
||||
if(!data_s) {
|
||||
return;
|
||||
}
|
||||
free_data(data_s);
|
||||
data_s = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
void audio_dac_irq(uint32 irq, uint32 irq_data)
|
||||
{
|
||||
audio_da_config *audio_da_cfg = (audio_da_config *)irq_data;
|
||||
#ifndef PSRAM_HEAP
|
||||
void *buf = NULL;
|
||||
int32_t buf_size = 0;
|
||||
#endif
|
||||
//满
|
||||
if (irq & AUDAC_IRQ_FLAG_FULL) {
|
||||
if(audio_da_cfg->current_node) {
|
||||
#ifdef PSRAM_HEAP
|
||||
os_sema_up(&audac_priv->cache_sema);
|
||||
#else
|
||||
audio_dac_free_buf(audio_da_cfg->current_node);
|
||||
#endif
|
||||
audio_da_cfg->current_node = NULL;
|
||||
}
|
||||
else {
|
||||
audio_da_cfg->is_empty = 1;
|
||||
}
|
||||
if(audio_da_cfg->reg_node) {
|
||||
#if FADE_PROCESS
|
||||
if(audac_priv->fade_mode == 1) {
|
||||
audac_priv->fade_mode = 0;
|
||||
if(os_msgq_put(&audac_priv->fade_msg, audac_priv->fade_mode, 0) < 0) {
|
||||
audac_priv->fade_mode = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
audio_da_cfg->current_node = audio_da_cfg->reg_node;
|
||||
audio_da_cfg->reg_node = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//半
|
||||
if (irq & AUDAC_IRQ_FLAG_HALF) {
|
||||
#ifdef PSRAM_HEAP
|
||||
if(audio_da_cfg->reg_node) {
|
||||
os_sema_up(&audac_priv->cache_sema);
|
||||
}
|
||||
if(audac_priv->status > 0) {
|
||||
audac_priv->status--;
|
||||
audio_da_cfg->reg_node = audac_priv->buf[audac_priv->buf_index%4];
|
||||
audac_priv->buf_index++;
|
||||
audio_da_cfg->irq_func(audio_da_cfg , audio_da_cfg->reg_node, audac_priv->buf_len);
|
||||
audio_da_cfg->is_empty = 0;
|
||||
}
|
||||
#else
|
||||
buf = audio_dac_get_buf(global_audio_dac_s, &audio_da_cfg->reg_node, &buf_size);
|
||||
if(buf) {
|
||||
audio_da_cfg->irq_func(audio_da_cfg, buf, buf_size);
|
||||
audio_da_cfg->is_empty = 0;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
if(audio_da_cfg->play_empty_buf)
|
||||
{
|
||||
#if FADE_PROCESS
|
||||
if(audac_priv->fade_mode == 0) {
|
||||
audac_priv->fade_mode = 1;
|
||||
if(os_msgq_put(&audac_priv->fade_msg, audac_priv->fade_mode, 0) < 0) {
|
||||
audac_priv->fade_mode = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
audio_da_cfg->irq_func(audio_da_cfg , audio_da_cfg->play_empty_buf, audio_da_cfg->buf_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int32 global_audio_da_write(struct audio_da_config *audio, void* buf, uint32 len)
|
||||
{
|
||||
audac_write(audio->dac, buf, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if SONIC_PROCESS
|
||||
static int opcode_func_sonic_r(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
enable_stream(s,1);
|
||||
s->priv = (void*)SOUND_ALL;
|
||||
}
|
||||
break;
|
||||
case STREAM_OPEN_FAIL:
|
||||
break;
|
||||
//在发送到这个流的时候,进行数据包过滤
|
||||
//在发送到这个流的时候,进行数据包过滤
|
||||
case STREAM_FILTER_DATA:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
int filter_type = (int)get_audio_dac_set_filter_type();
|
||||
//os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
if(GET_DATA_TYPE1(data->type) != SOUND) {
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
//永远不过滤
|
||||
if(!filter_type || GET_DATA_TYPE2(data->type) == SOUND_ALL) {
|
||||
}
|
||||
else {
|
||||
//过滤不匹配的数据包
|
||||
if(!(filter_type && (filter_type == GET_DATA_TYPE2(data->type))))
|
||||
{
|
||||
//os_printf("filter_type:%X\tdata_type:%X\t%X\n",filter_type,GET_DATA_TYPE2(data->type),s);
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//流接收后,数据包也要检查是否需要过滤或者是不是因为逻辑条件符合需要过滤
|
||||
case STREAM_RECV_FILTER_DATA:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
if(GET_DATA_TYPE1(data->type) != SOUND) {
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
int filter_type = (int)get_audio_dac_set_filter_type();
|
||||
//永远不过滤
|
||||
if(!filter_type || GET_DATA_TYPE2(data->type) == SOUND_ALL) {
|
||||
}
|
||||
else {
|
||||
//过滤不匹配的数据包
|
||||
if(!(filter_type && (GET_DATA_TYPE2(filter_type)== GET_DATA_TYPE2(data->type)))) {
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
//接收到命令,可以尝试执行命令的接口
|
||||
case STREAM_SEND_CMD:
|
||||
{
|
||||
uint32_t cmd = (uint32_t)priv;
|
||||
//只是接受支持的命令
|
||||
if(GET_CMD_TYPE1(cmd) == CMD_AUDIO_DAC) {
|
||||
os_printf("!!!!!!!!!cmd:%X\n",cmd);
|
||||
s->priv = (void*)GET_CMD_TYPE2(cmd);
|
||||
}
|
||||
else if(GET_CMD_TYPE1(cmd) == CMD_AUDIO_DAC_MODIFY_HZ) {
|
||||
extern void audio_da_recfg(uint32_t hz);
|
||||
audio_da_recfg(GET_CMD_TYPE2(cmd));
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
static uint32_t get_sonic_data_len(void *data)
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
return (uint32_t)d->priv;
|
||||
}
|
||||
static uint32_t set_sonic_data_len(void *data,uint32_t len)
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
d->priv = (void*)len;
|
||||
return (uint32_t)len;
|
||||
}
|
||||
static stream_ops_func stream_sonic_ops =
|
||||
{
|
||||
.get_data_len = get_sonic_data_len,
|
||||
.set_data_len = set_sonic_data_len,
|
||||
};
|
||||
static int opcode_func_sonic_s(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
stream_data_dis_mem_custom(s);
|
||||
streamSrc_bind_streamDest(s,R_AUDIO_TEST);
|
||||
streamSrc_bind_streamDest(s,R_SPEAKER);
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_DIS:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
data->ops = &stream_sonic_ops;
|
||||
data->data = (void*)ADUIO_MALLOC(AUDIOLEN);
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_DESTORY:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
if(data->data)
|
||||
{
|
||||
ADUIO_FREE(data->data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void set_sonic_speed(struct sonic_process_priv *sonic_priv, float speed)
|
||||
{
|
||||
if(!sonic_priv)
|
||||
return;
|
||||
sonic_priv->speed = speed;
|
||||
os_sema_up(&sonic_priv->sema);
|
||||
}
|
||||
void set_sonic_pitch(struct sonic_process_priv *sonic_priv, float pitch)
|
||||
{
|
||||
sonic_priv->pitch = pitch;
|
||||
os_sema_up(&sonic_priv->sema);
|
||||
}
|
||||
void set_sonic_samplingRate(struct sonic_process_priv *sonic_priv, int samplingRate)
|
||||
{
|
||||
if(!sonic_priv)
|
||||
return;
|
||||
sonic_priv->samplingRate = samplingRate;
|
||||
os_sema_up(&sonic_priv->sema);
|
||||
}
|
||||
|
||||
static void audac_sonic_process(void *d)
|
||||
{
|
||||
sonicStream sonic_s = (sonicStream)d;
|
||||
int16_t *sonic_stream_inbuf = NULL;
|
||||
int16_t *sonic_stream_outbuf = NULL;
|
||||
struct data_structure *sonic_data_r = NULL;
|
||||
struct data_structure *sonic_data_s = NULL;
|
||||
stream* sonic_stream_s = NULL;
|
||||
stream* sonic_stream_r = NULL;
|
||||
int sonicstream_cache = 0;
|
||||
volatile int sonicstream_input_len = 0;
|
||||
int sonicstream_output_len = 0;
|
||||
|
||||
sonic_stream_s = open_stream_available(S_SONIC_PROCESS,AUDIONUM,0,opcode_func_sonic_s,NULL);
|
||||
sonic_stream_r = open_stream_available(R_SONIC_PROCESS,0,AUDIONUM,opcode_func_sonic_r,NULL);
|
||||
if(!sonic_stream_s || !sonic_stream_r)
|
||||
{
|
||||
os_printf("open sonic process stream err\n");
|
||||
goto audac_sonic_process_end;
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(os_sema_down(&sonic_priv->sema,0) == 1) {
|
||||
sonic_flush_stream(sonic_s);
|
||||
sonicstream_cache = sonicStream_output_available(sonic_s);
|
||||
while(sonicstream_cache > 0) {
|
||||
sonic_data_s = get_src_data_f(sonic_stream_s);
|
||||
sonic_priv->s_current_data = sonic_data_s;
|
||||
if(sonic_data_s) {
|
||||
sonic_stream_outbuf = get_stream_real_data(sonic_data_s);
|
||||
sonicstream_output_len = sonicStream_output_data(sonic_s, sonic_stream_outbuf, (AUDIOLEN>>1));
|
||||
if(sonicstream_output_len > 0) {
|
||||
sonic_data_s->type = SET_DATA_TYPE(SOUND, GET_DATA_TYPE2(sonic_data_r->type));
|
||||
set_stream_real_data_len(sonic_data_s,(sonicstream_output_len<<1));
|
||||
send_data_to_stream(sonic_data_s);
|
||||
sonic_priv->s_current_data = NULL;
|
||||
sonicstream_cache -= sonicstream_output_len;
|
||||
}
|
||||
}
|
||||
else
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
sonicStream_deinit(sonic_s);
|
||||
sonic_priv->sonic_s = sonicStream_init(sonic_priv->samplingRate,sonic_priv->channel,sonic_priv->speed,sonic_priv->pitch);
|
||||
}
|
||||
|
||||
sonic_data_r = recv_real_data(sonic_stream_r);
|
||||
sonic_priv->r_current_data = sonic_data_r;
|
||||
if(sonic_data_r)
|
||||
{
|
||||
sonic_stream_inbuf = get_stream_real_data(sonic_data_r);
|
||||
sonicstream_input_len = get_stream_real_data_len(sonic_data_r);
|
||||
sonicStream_input_data(sonic_s, sonic_stream_inbuf, sonicstream_input_len/2);
|
||||
sonicstream_cache = sonicStream_output_available(sonic_s);
|
||||
while(sonicstream_cache >= (AUDIOLEN>>1)) {
|
||||
sonic_data_s = get_src_data_f(sonic_stream_s);
|
||||
sonic_priv->s_current_data = sonic_data_s;
|
||||
if(sonic_data_s) {
|
||||
sonic_stream_outbuf = get_stream_real_data(sonic_data_s);
|
||||
sonicstream_output_len = sonicStream_output_data(sonic_s, sonic_stream_outbuf, (AUDIOLEN>>1));
|
||||
if(sonicstream_output_len > 0) {
|
||||
sonic_data_s->type = SET_DATA_TYPE(SOUND, GET_DATA_TYPE2(sonic_data_r->type));
|
||||
set_stream_real_data_len(sonic_data_s,(sonicstream_output_len<<1));
|
||||
send_data_to_stream(sonic_data_s);
|
||||
sonic_priv->s_current_data = NULL;
|
||||
sonicstream_cache -= sonicstream_output_len;
|
||||
}
|
||||
}
|
||||
else
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
free_data(sonic_data_r);
|
||||
sonic_priv->r_current_data = NULL;
|
||||
}
|
||||
else {
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
audac_sonic_process_end:
|
||||
if(sonic_stream_s)
|
||||
{
|
||||
close_stream(sonic_stream_s);
|
||||
}
|
||||
|
||||
if(sonic_stream_r)
|
||||
{
|
||||
close_stream(sonic_stream_r);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FADE_PROCESS
|
||||
static void audio_dac_fade(void *d)
|
||||
{
|
||||
uint32_t fade_mode = 0;
|
||||
struct aufade_device *fade = (struct aufade_device *)dev_get(HG_AUFADE_DEVID);
|
||||
|
||||
while(1) {
|
||||
fade_mode = os_msgq_get(&audac_priv->fade_msg,-1);
|
||||
//fade out
|
||||
if(fade_mode == 1) {
|
||||
os_printf("\n*********fade mode:%d*********\n",fade_mode);
|
||||
aufade_ioctl(fade, AUFADE_IOCTL_CMD_SET_STEP, AUFADE_STEP_4, 0);
|
||||
aufade_ioctl(fade, AUFADE_IOCTL_CMD_SET_SAMPLE, AUFADE_SAMPLE_1, 0);
|
||||
aufade_start(fade, AUFADE_OUT);
|
||||
}
|
||||
else if(fade_mode == 0) {
|
||||
os_printf("\n*********fade mode:%d*********\n",fade_mode);
|
||||
aufade_ioctl(fade, AUFADE_IOCTL_CMD_SET_STEP, AUFADE_STEP_4, 0);
|
||||
aufade_ioctl(fade, AUFADE_IOCTL_CMD_SET_SAMPLE, AUFADE_SAMPLE_1, 0);
|
||||
aufade_start(fade, AUFADE_IN);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void audac_priv_clear()
|
||||
{
|
||||
audac_priv->res_len = CACHE_BUF_LEN;
|
||||
audac_priv->d_offset = 0;
|
||||
audac_priv->s_offset = 0;
|
||||
}
|
||||
|
||||
void audio_dac_cache(void *d)
|
||||
{
|
||||
stream *s = (stream *)d;
|
||||
struct data_structure *data = NULL;
|
||||
int16_t *s_buf = NULL;
|
||||
uint32_t get_buf_len = 0;
|
||||
uint8_t buf_index = 0;
|
||||
|
||||
audac_priv_clear();
|
||||
audac_priv->status = 0;
|
||||
audac_priv->buf_index = 0;
|
||||
|
||||
while(1) {
|
||||
data = recv_real_data(s);
|
||||
if(data)
|
||||
{
|
||||
audac_priv->current_data = data;
|
||||
s_buf = get_stream_real_data(data);
|
||||
get_buf_len = get_stream_real_data_len(data);
|
||||
audac_priv->s_offset = 0;
|
||||
while(get_buf_len >= audac_priv->res_len) {
|
||||
hw_memcpy(audac_priv->buf[buf_index%4]+(audac_priv->d_offset/2), s_buf+(audac_priv->s_offset/2), audac_priv->res_len);
|
||||
get_buf_len -= audac_priv->res_len;
|
||||
audac_priv->buf_len = CACHE_BUF_LEN;
|
||||
audac_priv->s_offset += audac_priv->res_len;
|
||||
audac_priv->status++;
|
||||
os_sema_down(&audac_priv->cache_sema, -1);
|
||||
audac_priv->res_len = CACHE_BUF_LEN;
|
||||
audac_priv->d_offset = 0;
|
||||
buf_index++;
|
||||
}
|
||||
if(get_buf_len) {
|
||||
hw_memcpy(audac_priv->buf[buf_index%4]+(audac_priv->d_offset/2), s_buf+(audac_priv->s_offset/2), get_buf_len);
|
||||
audac_priv->res_len = CACHE_BUF_LEN - get_buf_len;
|
||||
audac_priv->d_offset = get_buf_len;
|
||||
audac_priv->s_offset = 0;
|
||||
get_buf_len = 0;
|
||||
}
|
||||
free_data(data);
|
||||
audac_priv->current_data = NULL;
|
||||
}
|
||||
else {
|
||||
if(audac_priv->status == 0) {
|
||||
if(audac_priv->d_offset > 0) {
|
||||
hw_memset(audac_priv->buf[buf_index%4]+(audac_priv->d_offset/2), 0, (CACHE_BUF_LEN-audac_priv->d_offset));
|
||||
audac_priv->buf_len = CACHE_BUF_LEN;
|
||||
audac_priv->status++;
|
||||
os_sema_down(&audac_priv->cache_sema, -1);
|
||||
buf_index++;
|
||||
audac_priv_clear();
|
||||
get_buf_len = 0;
|
||||
}
|
||||
else
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
else
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int opcode_func(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
enable_stream(s,1);
|
||||
s->priv = (void*)SOUND_ALL;
|
||||
audac_priv = (struct audio_dac_priv*)ADUIO_ZALLOC(sizeof(struct audio_dac_priv));
|
||||
if(audac_priv) {
|
||||
#ifdef PSRAM_HEAP
|
||||
audac_priv->buf[0] = (int16_t *)custom_malloc(CACHE_BUF_LEN);
|
||||
audac_priv->buf[1] = (int16_t *)custom_malloc(CACHE_BUF_LEN);
|
||||
audac_priv->buf[2] = (int16_t *)custom_malloc(CACHE_BUF_LEN);
|
||||
audac_priv->buf[3] = (int16_t *)custom_malloc(CACHE_BUF_LEN);
|
||||
os_sema_init(&audac_priv->cache_sema,3);
|
||||
OS_TASK_INIT("audio_dac_cache", &audac_priv->cache_task_hdl, audio_dac_cache, s, OS_TASK_PRIORITY_ABOVE_NORMAL, 1024);
|
||||
#endif
|
||||
#if FADE_PROCESS
|
||||
os_msgq_init(&audac_priv->fade_msg, 1);
|
||||
OS_TASK_INIT("audio_dac_fade", &audac_priv->fade_task_hdl, audio_dac_fade, NULL, OS_TASK_PRIORITY_ABOVE_NORMAL, 1024);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SONIC_PROCESS
|
||||
sonic_priv = (struct sonic_process_priv*)ADUIO_ZALLOC(sizeof(struct sonic_process_priv));
|
||||
if(sonic_priv) {
|
||||
sonic_priv->samplingRate = audio_dac_get_samplingrate();
|
||||
sonic_priv->channel = 1;
|
||||
sonic_priv->pitch = 1.0;
|
||||
sonic_priv->speed = 1.0;
|
||||
sonic_priv->sonic_s = sonicStream_init(sonic_priv->samplingRate,sonic_priv->channel,sonic_priv->speed,sonic_priv->pitch);
|
||||
os_sema_init(&sonic_priv->sema,0);
|
||||
OS_TASK_INIT("audac_sonic_process", &sonic_priv->task_hdl, audac_sonic_process, sonic_priv->sonic_s, OS_TASK_PRIORITY_ABOVE_NORMAL-1, 1024);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
//在发送到这个流的时候,进行数据包过滤
|
||||
case STREAM_FILTER_DATA:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
int filter_type = (int)s->priv;
|
||||
//os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
if(GET_DATA_TYPE1(data->type) != SOUND)
|
||||
{
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
//永远不过滤
|
||||
if(!filter_type || GET_DATA_TYPE2(data->type) == SOUND_ALL)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
//过滤不匹配的数据包
|
||||
if(!(filter_type && (filter_type == GET_DATA_TYPE2(data->type))))
|
||||
{
|
||||
//os_printf("filter_type:%X\tdata_type:%X\t%X\n",filter_type,GET_DATA_TYPE2(data->type),s);
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
//流接收后,数据包也要检查是否需要过滤或者是不是因为逻辑条件符合需要过滤
|
||||
case STREAM_RECV_FILTER_DATA:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
if(GET_DATA_TYPE1(data->type) != SOUND)
|
||||
{
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
int filter_type = (int)s->priv;
|
||||
//永远不过滤
|
||||
if(!filter_type || GET_DATA_TYPE2(data->type) == SOUND_ALL)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
//过滤不匹配的数据包
|
||||
if(!(filter_type && (GET_DATA_TYPE2(filter_type)== GET_DATA_TYPE2(data->type))))
|
||||
{
|
||||
res = 1;
|
||||
//_os_printf("FILTER\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
//接收到命令,可以尝试执行命令的接口
|
||||
case STREAM_SEND_CMD:
|
||||
{
|
||||
uint32_t cmd = (uint32_t)priv;
|
||||
//只是接受支持的命令
|
||||
if(GET_CMD_TYPE1(cmd) == CMD_AUDIO_DAC)
|
||||
{
|
||||
os_printf("!!!!!!!!!cmd:%X\n",cmd);
|
||||
s->priv = (void*)GET_CMD_TYPE2(cmd);
|
||||
}
|
||||
else if(GET_CMD_TYPE1(cmd) == CMD_AUDIO_DAC_MODIFY_HZ)
|
||||
{
|
||||
extern void audio_da_recfg(uint32_t hz);
|
||||
audio_da_recfg(GET_CMD_TYPE2(cmd));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
//优先创建音频的流
|
||||
stream *audio_dac_stream_init(const char *name)
|
||||
{
|
||||
stream *s = open_stream_available(name,0,AUDIONUM,opcode_func,NULL);
|
||||
if(s)
|
||||
{
|
||||
global_audio_dac_s = s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
//关闭音频流
|
||||
void audio_dac_stream_deinit()
|
||||
{
|
||||
int res;
|
||||
if(global_audio_dac_s)
|
||||
{
|
||||
res = close_stream(global_audio_dac_s);
|
||||
if(!res)
|
||||
{
|
||||
global_audio_dac_s = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void audio_da_init()
|
||||
{
|
||||
struct aufade_device *fade = (struct aufade_device *)dev_get(HG_AUFADE_DEVID);
|
||||
aufade_open(fade);
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
struct audac_device *audio_da = (struct audac_device *)dev_get(HG_AUDAC_DEVID);
|
||||
|
||||
memset(&global_audio_da,0,sizeof(global_audio_da));
|
||||
audio_da_config *audio_da_cfg = &global_audio_da;
|
||||
audio_da_cfg->dac = audio_da;
|
||||
|
||||
audio_da_cfg->buf_size = AUDIOLEN;
|
||||
audio_da_cfg->play_empty_buf = empty_buf;
|
||||
audio_da_cfg->irq_func = global_audio_da_write;
|
||||
audio_da_cfg->audio_hz = AUDAC_SAMPLE_RATE_8K;
|
||||
stream *dest = audio_dac_stream_init(R_SPEAKER);
|
||||
*((uint32_t*)0x4000802c) |= 0x690000;
|
||||
audac_open(audio_da, audio_da_cfg->audio_hz );
|
||||
audac_request_irq(audio_da, AUDAC_IRQ_FLAG_HALF | AUDAC_IRQ_FLAG_FULL, (audac_irq_hdl)audio_dac_irq, (uint32_t)audio_da_cfg);
|
||||
audio_da_cfg->irq_func(audio_da_cfg , audio_da_cfg->play_empty_buf, audio_da_cfg->buf_size);
|
||||
global_audio_dac_s = dest;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void audio_da_deinit()
|
||||
{
|
||||
struct audac_device *audio_da = (struct audac_device *)dev_get(HG_AUDAC_DEVID);
|
||||
audio_da_config *audio_da_cfg = &global_audio_da;
|
||||
struct aufade_device *fade = (struct aufade_device *)dev_get(HG_AUFADE_DEVID);
|
||||
aufade_close(fade);
|
||||
audac_close(audio_da);
|
||||
prev_filter_type = get_audio_dac_set_filter_type();
|
||||
audio_dac_set_filter_type(SOUND_NONE);
|
||||
//清除中断没有处理完的数据
|
||||
#ifdef PSRAM_HEAP
|
||||
if(audac_priv->current_data)
|
||||
{
|
||||
free_data(audac_priv->current_data);
|
||||
audac_priv->current_data = NULL;
|
||||
}
|
||||
if(audio_da_cfg->reg_node) {
|
||||
os_sema_up(&audac_priv->cache_sema);
|
||||
}
|
||||
if(audio_da_cfg->current_node) {
|
||||
os_sema_up(&audac_priv->cache_sema);
|
||||
}
|
||||
#else
|
||||
if(audio_da_cfg->reg_node) {
|
||||
free_data(audio_da_cfg->reg_node);
|
||||
audio_da_cfg->reg_node = NULL;
|
||||
}
|
||||
if(audio_da_cfg->reg_node) {
|
||||
free_data(audio_da_cfg->reg_node);
|
||||
audio_da_cfg->reg_node = NULL;
|
||||
}
|
||||
#endif
|
||||
#ifdef SONIC_PRIV
|
||||
if(sonic_priv->r_current_data)
|
||||
{
|
||||
free_data(sonic_priv->r_current_data);
|
||||
sonic_priv->r_current_data = NULL;
|
||||
}
|
||||
if(sonic_priv->s_current_data)
|
||||
{
|
||||
force_del_data(sonic_priv->s_current_data);
|
||||
sonic_priv->s_current_data = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void audio_da_reinit()
|
||||
{
|
||||
struct audac_device *audio_da = (struct audac_device *)dev_get(HG_AUDAC_DEVID);
|
||||
struct aufade_device *fade = (struct aufade_device *)dev_get(HG_AUFADE_DEVID);
|
||||
aufade_open(fade);
|
||||
//这里成立的前提是原来stream已经创建过,否则可能有问题
|
||||
stream *dest = audio_dac_stream_init(R_SPEAKER);
|
||||
memset(&global_audio_da,0,sizeof(global_audio_da));
|
||||
audio_da_config *audio_da_cfg = &global_audio_da;
|
||||
audio_da_cfg->dac = audio_da;
|
||||
|
||||
audio_da_cfg->buf_size = AUDIOLEN;
|
||||
audio_da_cfg->play_empty_buf = empty_buf;
|
||||
audio_da_cfg->irq_func = global_audio_da_write;
|
||||
audio_da_cfg->audio_hz = AUDAC_SAMPLE_RATE_8K;
|
||||
*((uint32_t*)0x4000802c) |= 0x690000;
|
||||
audac_open(audio_da, audio_da_cfg->audio_hz);
|
||||
os_printf("!!!!audio_da_cfg:%X\n",audio_da_cfg);
|
||||
audac_request_irq(audio_da, AUDAC_IRQ_FLAG_HALF | AUDAC_IRQ_FLAG_FULL, (audac_irq_hdl)audio_dac_irq, (uint32_t)audio_da_cfg);
|
||||
audio_da_cfg->irq_func(audio_da_cfg , audio_da_cfg->play_empty_buf, audio_da_cfg->buf_size);
|
||||
global_audio_dac_s = dest;
|
||||
//这个函数只是重新初始化dac硬件,所以流与init的时候有区别,这里需要关闭一次(实际内部没有关闭,与audio_dac_stream_init成对使用)
|
||||
audio_dac_stream_deinit();
|
||||
audio_dac_set_filter_type(prev_filter_type);
|
||||
|
||||
}
|
||||
|
||||
//音频采样率重新修改
|
||||
void audio_da_recfg(uint32_t hz)
|
||||
{
|
||||
os_printf("%s hz:%d\n",__FUNCTION__,hz);
|
||||
//识别采样率,如果一样,则直接退出
|
||||
int8_t now_hz_enum = -1;
|
||||
switch(hz)
|
||||
{
|
||||
case 8000:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_8K;
|
||||
break;
|
||||
case 11025:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_11_025K;
|
||||
break;
|
||||
case 16000:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_16K;
|
||||
break;
|
||||
case 22050:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_22_05K;
|
||||
break;
|
||||
case 32000:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_32K;
|
||||
break;
|
||||
case 44100:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_44_1K;
|
||||
break;
|
||||
case 48000:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_48K;
|
||||
break;
|
||||
case 24000:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_24K;
|
||||
break;
|
||||
case 12000:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_12K;
|
||||
break;
|
||||
default:
|
||||
now_hz_enum = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
audio_da_config *audio_da_cfg = &global_audio_da;
|
||||
os_printf("now_hz_enum:%d\tlast now_hz_enum:%d\n",now_hz_enum,audio_da_cfg->audio_hz);
|
||||
|
||||
//采样率不需要修改或者采样率设置错误
|
||||
if(audio_da_cfg->audio_hz == now_hz_enum || now_hz_enum == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
struct audac_device *audac_dev = (struct audac_device *)dev_get(HG_AUDAC_DEVID);
|
||||
|
||||
//将当前流的数据也删除,然后才可以接收其他正确采样率的数据
|
||||
int last_type = get_audio_dac_set_filter_type();
|
||||
|
||||
audio_dac_set_filter_type(SOUND_NONE);
|
||||
#if SONIC_PROCESS
|
||||
set_sonic_samplingRate(sonic_priv, hz);
|
||||
#endif
|
||||
//等待播放数据完毕,然后切换采样率
|
||||
uint32_t count = 0;
|
||||
//等待中断数据播放完毕
|
||||
while( !(audio_da_cfg->is_empty) && count++<1000)
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
|
||||
audac_ioctl(audac_dev,AUDAC_IOCTL_CMD_CHANGE_SAMPLE_RATE,now_hz_enum,0);
|
||||
audio_dac_set_filter_type(last_type);
|
||||
|
||||
audio_da_cfg->audio_hz = now_hz_enum;
|
||||
os_printf("audio_da_cfg:%X\tnow_hz_enum:%d\n",audio_da_cfg,now_hz_enum);
|
||||
audio_da_cfg->irq_func(audio_da_cfg , audio_da_cfg->play_empty_buf, audio_da_cfg->buf_size);
|
||||
}
|
||||
|
||||
//写一些通用dac输出的接口
|
||||
/***********************************************************
|
||||
设置接收和播放声音的类型(只是将当前不匹配的音频都会过滤掉)
|
||||
使用场景:比如进入音乐播放后,就不再响应按键的音频了
|
||||
***********************************************************/
|
||||
void audio_dac_set_filter_type(int filter_type)
|
||||
{
|
||||
if(global_audio_dac_s)
|
||||
{
|
||||
os_printf("filter_type:%d\t%X\n",filter_type,global_audio_dac_s);
|
||||
global_audio_dac_s->priv = (void*)filter_type;
|
||||
}
|
||||
}
|
||||
|
||||
void print_audio_dac_set_filter_type()
|
||||
{
|
||||
if(global_audio_dac_s)
|
||||
{
|
||||
os_printf("type:%X\n",global_audio_dac_s->priv);
|
||||
}
|
||||
}
|
||||
|
||||
int get_audio_dac_set_filter_type(void)
|
||||
{
|
||||
if(global_audio_dac_s)
|
||||
{
|
||||
return (int)global_audio_dac_s->priv;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_dac_get_samplingrate(void)
|
||||
{
|
||||
audio_da_config *play = &global_audio_da;
|
||||
int32_t samplingrate = -1;
|
||||
|
||||
switch(play->audio_hz)
|
||||
{
|
||||
case AUDAC_SAMPLE_RATE_8K:
|
||||
samplingrate = 8000;
|
||||
break;
|
||||
case AUDAC_SAMPLE_RATE_11_025K:
|
||||
samplingrate = 11025;
|
||||
break;
|
||||
case AUDAC_SAMPLE_RATE_12K:
|
||||
samplingrate = 12000;
|
||||
break;
|
||||
case AUDAC_SAMPLE_RATE_16K:
|
||||
samplingrate = 16000;
|
||||
break;
|
||||
case AUDAC_SAMPLE_RATE_22_05K:
|
||||
samplingrate = 22050;
|
||||
break;
|
||||
case AUDAC_SAMPLE_RATE_24K:
|
||||
samplingrate = 24000;
|
||||
break;
|
||||
case AUDAC_SAMPLE_RATE_32K:
|
||||
samplingrate = 32000;
|
||||
break;
|
||||
case AUDAC_SAMPLE_RATE_44_1K:
|
||||
samplingrate = 44100;
|
||||
break;
|
||||
case AUDAC_SAMPLE_RATE_48K:
|
||||
samplingrate = 48000;
|
||||
break;
|
||||
|
||||
}
|
||||
printf("now DAC samplingrate:%d\n",samplingrate);
|
||||
return samplingrate;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef __AUDIO_DAC_H
|
||||
#define __AUDIO_DAC_H
|
||||
void audio_da_init();
|
||||
void audio_dac_set_filter_type(int filter_type);
|
||||
int get_audio_dac_set_filter_type(void);
|
||||
int audio_dac_get_samplingrate(void);
|
||||
void audio_da_recfg(uint32_t hz);
|
||||
#endif
|
||||
@@ -0,0 +1,198 @@
|
||||
#include "osal/string.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
#include "stream_frame.h"
|
||||
#include "osal/task.h"
|
||||
#include "dev/usb/uvc_host.h"
|
||||
#include "osal/task.h"
|
||||
#include <csi_kernel.h>
|
||||
|
||||
#define AUDIO_LEN (1024)
|
||||
k_task_handle_t send_usbmic_audio_handle;
|
||||
k_task_handle_t *send_usbmic_audio_hd;
|
||||
stream *g_usbmic_s = NULL;
|
||||
|
||||
static struct data_structure *g_usbmic_stream_current_data = NULL;
|
||||
|
||||
int get_usbmic_audio(void *d);
|
||||
void usbmic_audio_stream_del(void);
|
||||
|
||||
static uint32_t get_sound_data_len(void *data)
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
return (uint32_t)d->priv;
|
||||
}
|
||||
static uint32_t set_sound_data_len(void *data,uint32_t len)
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
d->priv = (void*)len;
|
||||
return len;
|
||||
}
|
||||
static stream_ops_func stream_sound_ops =
|
||||
{
|
||||
.get_data_len = get_sound_data_len,
|
||||
.set_data_len = set_sound_data_len,
|
||||
};
|
||||
|
||||
static int opcode_func(stream *s,void *priv,int opcode)
|
||||
{
|
||||
static uint8 *audio_buf = NULL;
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_ENTER:
|
||||
break;
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
audio_buf = os_malloc(4 * AUDIO_LEN);
|
||||
if(audio_buf)
|
||||
{
|
||||
stream_data_dis_mem(s,4);
|
||||
}
|
||||
streamSrc_bind_streamDest(s,R_USB_SPK);
|
||||
// streamSrc_bind_streamDest(s,R_SPEAKER);
|
||||
}
|
||||
break;
|
||||
case STREAM_OPEN_FAIL:
|
||||
break;
|
||||
|
||||
case STREAM_FILTER_DATA:
|
||||
break;
|
||||
|
||||
case STREAM_DATA_DIS:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
int data_num = (int)data->priv;
|
||||
data->ops = &stream_sound_ops;
|
||||
data->data = audio_buf + (data_num)*AUDIO_LEN;
|
||||
}
|
||||
break;
|
||||
case STREAM_DATA_DESTORY:
|
||||
{
|
||||
if(audio_buf)
|
||||
os_free(audio_buf);
|
||||
}
|
||||
break;
|
||||
case STREAM_DATA_FREE:
|
||||
//_os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
break;
|
||||
|
||||
|
||||
//数据发送完成,可以选择唤醒对应的任务
|
||||
case STREAM_RECV_DATA_FINISH:
|
||||
break;
|
||||
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
extern int usb_dma_irq_times;
|
||||
extern int get_audio_dac_set_filter_type(void);
|
||||
extern void audio_dac_set_filter_type(int filter_type);
|
||||
extern void usbmic_room_del(void);
|
||||
int get_usbmic_audio(void *d)
|
||||
{
|
||||
uint32_t usbmic_timeout = 0;
|
||||
uint32_t usb_dma_irq_count = 0;
|
||||
struct data_structure *data = NULL;
|
||||
volatile int16 *realdata = NULL;
|
||||
//int former_dac_priv = 0;
|
||||
int16 *audio_addr = NULL;
|
||||
uint32 audio_len = 0;
|
||||
UAC_MANAGE *usbmic_manage = NULL;
|
||||
stream *src = (stream *)d;
|
||||
|
||||
|
||||
if(!src)
|
||||
{
|
||||
os_printf("\n*******open usbmic stream err");
|
||||
return 0;
|
||||
}
|
||||
// former_dac_priv = get_audio_dac_set_filter_type();
|
||||
// audio_dac_set_filter_type(SOUND_MIC);
|
||||
while(1)
|
||||
{
|
||||
if(usbmic_timeout > 500) {
|
||||
if(usb_dma_irq_count == usb_dma_irq_times) {
|
||||
goto get_usbmic_audio_end;
|
||||
}
|
||||
usb_dma_irq_count = usb_dma_irq_times;
|
||||
usbmic_timeout = 0;
|
||||
}
|
||||
usbmic_timeout++;
|
||||
usbmic_manage = get_usbmic_frame();
|
||||
if(usbmic_manage)
|
||||
{
|
||||
data = get_src_data_f(src);
|
||||
g_usbmic_stream_current_data = data;
|
||||
if(data) {
|
||||
printf("L");
|
||||
audio_len = get_uac_frame_datalen(usbmic_manage);
|
||||
audio_addr = (int16*)get_uac_frame_data(usbmic_manage);
|
||||
realdata = get_stream_real_data(data);
|
||||
os_memcpy(realdata, audio_addr, audio_len);
|
||||
del_usbmic_frame(usbmic_manage);
|
||||
data->type = SET_DATA_TYPE(SOUND, SOUND_MIC);
|
||||
set_stream_real_data_len(data,audio_len);
|
||||
send_data_to_stream(data);
|
||||
g_usbmic_stream_current_data = NULL;
|
||||
data = NULL;
|
||||
usbmic_timeout = 0;
|
||||
}
|
||||
else {
|
||||
del_usbmic_frame(usbmic_manage);
|
||||
usbmic_manage = NULL;
|
||||
}
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
get_usbmic_audio_end:
|
||||
usbmic_audio_stream_del();
|
||||
usbmic_room_del();
|
||||
send_usbmic_audio_hd = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usbmic_audio_stream_init(void)
|
||||
{
|
||||
if(!g_usbmic_s) {
|
||||
os_printf("%s %d\n",__FUNCTION__,__LINE__);
|
||||
g_usbmic_s = open_stream_available(S_USB_MIC, 4, 0, opcode_func,NULL);
|
||||
// OS_TASK_INIT("get_usbmic_audio", &get_usbmic_audio_task, get_usbmic_audio, g_usbmic_s, OS_TASK_PRIORITY_NORMAL, 512);
|
||||
}
|
||||
if(!g_usbmic_s) {
|
||||
_os_printf("%s open stream err!\n",__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
if(!send_usbmic_audio_hd) {
|
||||
if(csi_kernel_task_new((k_task_entry_t)get_usbmic_audio, "get_usbmic_audio", (void*)g_usbmic_s, 17, 0, NULL, 512, &send_usbmic_audio_handle)==0)
|
||||
send_usbmic_audio_hd = &send_usbmic_audio_handle;
|
||||
}
|
||||
}
|
||||
|
||||
void usbmic_audio_stream_del(void)
|
||||
{
|
||||
int ret = 0;
|
||||
if(g_usbmic_s) {
|
||||
ret = close_stream(g_usbmic_s);
|
||||
if(!ret)
|
||||
g_usbmic_s = NULL;
|
||||
os_printf("%s!\n",__FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
void usbmic_audio_stream_deinit(void)
|
||||
{
|
||||
if(send_usbmic_audio_hd) {
|
||||
csi_kernel_task_del(send_usbmic_audio_handle);
|
||||
send_usbmic_audio_hd = NULL;
|
||||
}
|
||||
if(g_usbmic_stream_current_data)
|
||||
force_del_data(g_usbmic_stream_current_data);
|
||||
}
|
||||
void usbmic_enum_finish(void)
|
||||
{
|
||||
usbmic_audio_stream_init();
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
#include "osal/string.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
#include "stream_frame.h"
|
||||
#include "osal/task.h"
|
||||
#include "dev/usb/uvc_host.h"
|
||||
#include "osal/task.h"
|
||||
#include <csi_kernel.h>
|
||||
|
||||
#define AUDIO_LEN (1024)
|
||||
k_task_handle_t send_usbspk_audio_handle;
|
||||
struct os_task *send_usbspk_audio_hd = NULL;
|
||||
stream *g_usbspk_s = NULL;
|
||||
|
||||
static struct data_structure *g_usbspk_stream_current_data = NULL;
|
||||
|
||||
void usbspk_audio_stream_del(void);
|
||||
void send_usbspk_audio(void *d);
|
||||
|
||||
static int opcode_func(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
//_os_printf("%s:%d\topcode:%d\n",__FUNCTION__,__LINE__,opcode);
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_ENTER:
|
||||
break;
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
enable_stream(s,1);
|
||||
}
|
||||
break;
|
||||
case STREAM_OPEN_FAIL:
|
||||
break;
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
extern uint32_t usbspk_tx_cnt;
|
||||
extern int usb_dma_irq_times;
|
||||
extern void del_usbspk_frame(UAC_MANAGE *uac_manage);
|
||||
extern void usbspk_room_del(void);
|
||||
void send_usbspk_audio(void *d)
|
||||
{
|
||||
struct data_structure *data_s = NULL;
|
||||
stream* s = NULL;
|
||||
volatile int16 *buf = NULL;
|
||||
uint32 len = 0;
|
||||
volatile uint8 *audio_addr = NULL;
|
||||
UAC_MANAGE *usbspk_manage = NULL;
|
||||
uint32_t usbspk_timeout = 0;
|
||||
uint32_t usb_dma_irq_count = 0;
|
||||
|
||||
s = (stream *)d;
|
||||
if(!s)
|
||||
{
|
||||
os_printf("open usbspk stream err\n");
|
||||
}
|
||||
while(1)
|
||||
{
|
||||
if(usbspk_timeout > 500) {
|
||||
if(usb_dma_irq_count == usb_dma_irq_times) {
|
||||
goto send_usbspk_audio_end;
|
||||
}
|
||||
usb_dma_irq_count = usb_dma_irq_times;
|
||||
usbspk_timeout = 0;
|
||||
}
|
||||
usbspk_timeout++;
|
||||
usbspk_manage = get_usbspk_new_frame(0);
|
||||
if(usbspk_manage) {
|
||||
data_s = recv_real_data(s);
|
||||
g_usbspk_stream_current_data = data_s;
|
||||
if(data_s)
|
||||
{
|
||||
printf("S");
|
||||
buf = get_stream_real_data(data_s);
|
||||
len = get_stream_real_data_len(data_s);
|
||||
audio_addr = get_uac_frame_data(usbspk_manage);
|
||||
os_memcpy((uint8*)audio_addr, buf, len);
|
||||
set_uac_frame_datalen(usbspk_manage, len);
|
||||
set_uac_frame_sta(usbspk_manage, 1);
|
||||
put_usbspk_frame_to_use(usbspk_manage);
|
||||
usbspk_manage = NULL;
|
||||
free_data(data_s);
|
||||
g_usbspk_stream_current_data = NULL;
|
||||
usbspk_timeout = 0;
|
||||
}
|
||||
else {
|
||||
del_usbspk_frame(usbspk_manage);
|
||||
usbspk_manage = NULL;
|
||||
}
|
||||
}
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
send_usbspk_audio_end:
|
||||
usbspk_audio_stream_del();
|
||||
usbspk_room_del();
|
||||
send_usbspk_audio_hd = NULL;
|
||||
}
|
||||
|
||||
void usbspk_audio_stream_init(void)
|
||||
{
|
||||
if(!g_usbspk_s) {
|
||||
os_printf("%s %d\n",__FUNCTION__,__LINE__);
|
||||
g_usbspk_s = open_stream_available(R_USB_SPK,0,8,opcode_func,NULL);
|
||||
// OS_TASK_INIT("send_usbspk_audio", &send_usbspk_audio_task, send_usbspk_audio, g_usbspk_s, OS_TASK_PRIORITY_NORMAL, 512);
|
||||
}
|
||||
if(!g_usbspk_s) {
|
||||
_os_printf("%s open stream err!\n",__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
if(!send_usbspk_audio_hd) {
|
||||
if(csi_kernel_task_new((k_task_entry_t)send_usbspk_audio, "send_usbspk_audio", (void*)g_usbspk_s, 17, 0, NULL, 512, &send_usbspk_audio_handle)==0)
|
||||
send_usbspk_audio_hd = (struct os_task *)&send_usbspk_audio_handle;
|
||||
}
|
||||
}
|
||||
|
||||
void usbspk_audio_stream_del(void)
|
||||
{
|
||||
int ret = 0;
|
||||
if(g_usbspk_s) {
|
||||
ret = close_stream(g_usbspk_s);
|
||||
if(!ret)
|
||||
g_usbspk_s = NULL;
|
||||
os_printf("%s!\n",__FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
void usbspk_audio_stream_deinit(void)
|
||||
{
|
||||
if(send_usbspk_audio_hd) {
|
||||
csi_kernel_task_del(send_usbspk_audio_handle);
|
||||
send_usbspk_audio_hd = NULL;
|
||||
}
|
||||
if(g_usbspk_stream_current_data)
|
||||
free_data(g_usbspk_stream_current_data);
|
||||
|
||||
}
|
||||
void usbspk_enum_finish(void)
|
||||
{
|
||||
usbspk_audio_stream_init();
|
||||
}
|
||||
@@ -0,0 +1,509 @@
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "string.h"
|
||||
#include "osal/task.h"
|
||||
#include "osal/string.h"
|
||||
#include "hal/auadc.h"
|
||||
#include "utlist.h"
|
||||
#include "audio_adc.h"
|
||||
#include "osal_file.h"
|
||||
#include "stream_frame.h"
|
||||
#include "osal_file.h"
|
||||
#include "dev/spi/hgspi_xip.h"
|
||||
#include "webrtc/process/aec_process.h"
|
||||
#include "webrtc/process/agc_process.h"
|
||||
#include "webrtc/process/vad_process.h"
|
||||
#include "webrtc/process/ns_process.h"
|
||||
#include "intercom/intercom.h"
|
||||
#include "dev/audio/components/vad/auvad.h"
|
||||
#include "sonic_process.h"
|
||||
#include "magic_sound.h"
|
||||
|
||||
#define MEDIAN_FILTER 1
|
||||
#define MID(a,b,c) ((a>=b)?((a<=c)?a:((b>=c)?b:c)):((a>=c)?a:((b>=c)?c:b)))
|
||||
|
||||
#if MEDIAN_FILTER == 1
|
||||
#define MEDIAN_FILTER_SAMPLE_LEN 2
|
||||
#else
|
||||
#define MEDIAN_FILTER_SAMPLE_LEN 0
|
||||
#endif
|
||||
|
||||
#define AEC_PROCESS 0
|
||||
#define AGC_PROCESS 0
|
||||
#define VAD_PROCESS 0
|
||||
#define NSX_PROCESS 0
|
||||
#define MAGIC_SOUND 0
|
||||
int aec_flag = -1;
|
||||
int agc_flag = -1;
|
||||
int vad_flag = -1;
|
||||
int nsx_flag = -1;
|
||||
|
||||
#if MAGIC_SOUND
|
||||
magicSound *magic_sound = NULL;
|
||||
#endif
|
||||
|
||||
#define AUDIONUM (4)
|
||||
#define AUDIOLEN (320)
|
||||
#define FILTER_SAMPLE_LEN 0
|
||||
|
||||
#define ENERGY_THRESHOLD 5000
|
||||
#define VAD_WEIGHT 1
|
||||
#define VAD_HOLD_TIME 50
|
||||
|
||||
#if AGC_PROCESS == 1
|
||||
#define SOFT_GAIN (1)
|
||||
#else
|
||||
#define SOFT_GAIN (8)
|
||||
#endif
|
||||
|
||||
static uint8_t g_vad_res = 1;
|
||||
static stream *global_audio_adc_s = NULL;
|
||||
struct audio_ad_config;
|
||||
typedef void *(*set_buf)(void *priv_el,void *el_point);
|
||||
typedef void (*get_buf)(void *priv_el,void *el_point);
|
||||
|
||||
typedef int32 (*audio_ad_read)(struct audio_ad_config *audio, void* buf, uint32 len);
|
||||
|
||||
struct audio_ad_config
|
||||
{
|
||||
int buf_size;
|
||||
struct auadc_device *adc;
|
||||
void *current_node;
|
||||
void *reg_node;
|
||||
//私有结构元素
|
||||
void *priv_el;
|
||||
set_buf set_buf;
|
||||
get_buf get_buf;
|
||||
audio_ad_read irq_func;
|
||||
};
|
||||
|
||||
void audio_adc_irq(uint32 irq, uint32 irq_data)
|
||||
{
|
||||
void *buf;
|
||||
struct audio_ad_config *audio_ad = (struct audio_ad_config *)irq_data;
|
||||
struct audio_ad_config *priv = (struct audio_ad_config*)audio_ad;
|
||||
|
||||
if(irq == AUADC_IRQ_FLAG_HALF)
|
||||
{
|
||||
buf = priv->set_buf(priv->priv_el,&priv->reg_node);
|
||||
if(priv->reg_node)
|
||||
{
|
||||
priv->irq_func(audio_ad , buf, priv->buf_size);
|
||||
}
|
||||
}
|
||||
else if(irq == AUADC_IRQ_FLAG_FULL)
|
||||
{
|
||||
if(priv->reg_node)
|
||||
{
|
||||
priv->get_buf(priv->priv_el,priv->current_node);
|
||||
priv->current_node = priv->reg_node;
|
||||
priv->reg_node = NULL;
|
||||
}
|
||||
encode_sema_up();
|
||||
}
|
||||
}
|
||||
|
||||
void audio_adc_register(void *audio_hdl,void *priv_el,int play_size,set_buf audio_set_buf,get_buf audio_get_buf)
|
||||
{
|
||||
struct audio_ad_config *priv = (struct audio_ad_config*)audio_hdl;
|
||||
priv->buf_size = play_size;
|
||||
priv->set_buf = audio_set_buf;
|
||||
priv->get_buf = audio_get_buf;
|
||||
priv->priv_el = priv_el;
|
||||
}
|
||||
|
||||
static void *audio_set_buf(void *priv_el,void *el_point)
|
||||
{
|
||||
void *buf = NULL;
|
||||
struct data_structure *data = NULL;
|
||||
stream *s = (stream *)priv_el;
|
||||
|
||||
data = get_src_data_f(s);
|
||||
struct data_structure **point = (struct data_structure**)el_point;
|
||||
if(*point)
|
||||
force_del_data(*point);
|
||||
if(data)
|
||||
{
|
||||
buf = get_stream_real_data(data);
|
||||
buf = (uint16_t*)buf+MEDIAN_FILTER_SAMPLE_LEN;
|
||||
}
|
||||
*point = data;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void audio_get_buf(void *priv_el,void *el_point)
|
||||
{
|
||||
int32_t res;
|
||||
stream *s = (stream *)priv_el;
|
||||
struct audio_adc_s *self_priv = (struct audio_adc_s*)s->priv;
|
||||
struct data_structure *data = (struct data_structure*)el_point;
|
||||
|
||||
if(!data)
|
||||
{
|
||||
_os_printf("%s:%d err\n",__FUNCTION__,__LINE__);
|
||||
return;
|
||||
}
|
||||
set_stream_data_time(data,os_jiffies());
|
||||
res = csi_kernel_msgq_put(self_priv->adc_msgq,&data,0,0);
|
||||
//正常应该保证不进这里,如果进来代表任务没有获取队列,直接配置下一个buf导致的
|
||||
if(res)
|
||||
{
|
||||
_os_printf("P");
|
||||
force_del_data(data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static int vad_filter(int16_t *buffer, uint32_t sampleRate, uint32_t samplesCount, int per_ms_frames)
|
||||
{
|
||||
int32_t vad_ret = -1;
|
||||
uint32 vad_result[2] = {0};
|
||||
static uint32 energy_threshold = ENERGY_THRESHOLD;
|
||||
static int32 talking = VAD_HOLD_TIME;
|
||||
|
||||
struct auvad_device *vad_dev = (struct auvad_device*)dev_get(HG_AUVAD_DEVID);
|
||||
if(auvad_calc(vad_dev, buffer, samplesCount*2, AUVAD_CALC_MODE_ENERGY, vad_result) == -1)
|
||||
return 0;
|
||||
if(vad_result[0]>=energy_threshold)
|
||||
{
|
||||
if(vad_flag == 0)
|
||||
vad_ret = vad_process(buffer, sampleRate, samplesCount, per_ms_frames);
|
||||
if((vad_ret == -1) || (vad_ret >= VAD_WEIGHT))
|
||||
talking = VAD_HOLD_TIME;
|
||||
else {
|
||||
talking--;
|
||||
if(talking<=0) {
|
||||
talking = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
talking--;
|
||||
if(talking<=0) {
|
||||
talking = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t auadc_get_vad_res(void)
|
||||
{
|
||||
return g_vad_res;
|
||||
}
|
||||
|
||||
static void audio_deal_task(void *arg)
|
||||
{
|
||||
#if MEDIAN_FILTER == 1
|
||||
int16_t median_filter_prev_buf[MEDIAN_FILTER_SAMPLE_LEN] = {0};
|
||||
#endif
|
||||
int16_t *p_buf = NULL;
|
||||
int32_t res;
|
||||
int32_t temp32 = 0;
|
||||
uint32_t sample_len;
|
||||
struct data_structure *data = NULL ;
|
||||
|
||||
stream *s = (stream *)arg;
|
||||
struct audio_adc_s *self_priv = (struct audio_adc_s*)s->priv;
|
||||
#if MEDIAN_FILTER == 1
|
||||
os_memset(median_filter_prev_buf, 0, MEDIAN_FILTER_SAMPLE_LEN*2);
|
||||
#endif
|
||||
while(1)
|
||||
{
|
||||
res = csi_kernel_msgq_get(self_priv->adc_msgq,&data,-1);
|
||||
if(!res)
|
||||
{
|
||||
p_buf = get_stream_real_data(data);
|
||||
sample_len = get_stream_real_data_len(data)/2;
|
||||
#if MEDIAN_FILTER == 1
|
||||
os_memcpy(p_buf, median_filter_prev_buf, MEDIAN_FILTER_SAMPLE_LEN*2);
|
||||
for(uint32_t i=MEDIAN_FILTER_SAMPLE_LEN; i<(sample_len+MEDIAN_FILTER_SAMPLE_LEN); i++) {
|
||||
p_buf[i-MEDIAN_FILTER_SAMPLE_LEN] = MID(p_buf[i-MEDIAN_FILTER_SAMPLE_LEN],p_buf[i-MEDIAN_FILTER_SAMPLE_LEN+1],p_buf[i]);
|
||||
}
|
||||
os_memcpy(median_filter_prev_buf, p_buf+sample_len, MEDIAN_FILTER_SAMPLE_LEN*2);
|
||||
#endif
|
||||
|
||||
#if AEC_PROCESS == 1
|
||||
if(aec_flag != -1) {
|
||||
aec_process(p_buf, sample_len, 3, 8000);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if VAD_PROCESS
|
||||
int filter = vad_filter(p_buf, 8000, sample_len, sample_len/8);
|
||||
if(filter) {
|
||||
force_del_data(data);
|
||||
g_vad_res = 0;
|
||||
continue;
|
||||
}
|
||||
g_vad_res = 1;
|
||||
#endif
|
||||
|
||||
#if NSX_PROCESS == 1
|
||||
if(nsx_flag != -1) {
|
||||
ns_process(p_buf, 8000, sample_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if AGC_PROCESS
|
||||
if(agc_flag != -1) {
|
||||
agc_process(p_buf, 8000, sample_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
for(uint32_t i=0;i<sample_len;i++) {
|
||||
temp32 = (*p_buf)*SOFT_GAIN;
|
||||
if(temp32>32767)
|
||||
*p_buf = 32767;
|
||||
else if(temp32<-32767)
|
||||
*p_buf = -32767;
|
||||
else
|
||||
*p_buf = temp32;
|
||||
p_buf++;
|
||||
}
|
||||
p_buf -= sample_len;
|
||||
|
||||
#if MAGIC_SOUND
|
||||
if(magic_sound) {
|
||||
magicSound_process(magic_sound, p_buf, sample_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
data->type = SET_DATA_TYPE(SOUND,SOUND_MIC);
|
||||
send_data_to_stream(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
_os_printf("%s:%d err\n",__FUNCTION__,__LINE__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t get_sound_data_len(void *data)
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
return (uint32_t)d->priv;
|
||||
}
|
||||
|
||||
static uint32_t set_sound_data_len(void *data,uint32_t len)
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
d->priv = (void*)AUDIOLEN;
|
||||
return (uint32_t)AUDIOLEN;
|
||||
}
|
||||
|
||||
static uint32_t set_sound_data_time(void *data,uint32_t len)
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
d->timestamp = os_jiffies();
|
||||
return (uint32_t)0;
|
||||
}
|
||||
|
||||
static stream_ops_func stream_sound_ops =
|
||||
{
|
||||
.get_data_len = get_sound_data_len,
|
||||
.set_data_len = set_sound_data_len,
|
||||
};
|
||||
|
||||
static int opcode_func(stream *s,void *priv,int opcode)
|
||||
{
|
||||
static uint8_t *adc_audio_buf = NULL;
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
s->priv = (void*)os_malloc(sizeof(struct audio_adc_s));
|
||||
if(s->priv)
|
||||
{
|
||||
struct audio_adc_s *self_priv = (struct audio_adc_s*)s->priv;
|
||||
self_priv->adc_msgq = (void*)csi_kernel_msgq_new(1,sizeof(uint8_t*));
|
||||
OS_TASK_INIT("adc_audio_deal", &self_priv->thread_hdl, audio_deal_task, s, OS_TASK_PRIORITY_ABOVE_NORMAL, 10240);
|
||||
}
|
||||
adc_audio_buf = os_malloc(AUDIONUM * (AUDIOLEN + MEDIAN_FILTER_SAMPLE_LEN*2));
|
||||
if(adc_audio_buf)
|
||||
{
|
||||
stream_data_dis_mem(s,AUDIONUM);
|
||||
}
|
||||
streamSrc_bind_streamDest(s, R_INTERCOM_AUDIO);
|
||||
streamSrc_bind_streamDest(s, R_SPEECH_RECOGNITION);
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_DIS:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
int data_num = (int)data->priv;
|
||||
data->priv = (void*)AUDIOLEN;
|
||||
data->ops = &stream_sound_ops;
|
||||
data->data = adc_audio_buf + (data_num)*(AUDIOLEN + MEDIAN_FILTER_SAMPLE_LEN*2);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int audio_adc_start(void *audio_hdl)
|
||||
{
|
||||
int ret = 0;
|
||||
int res = 0;
|
||||
void *buf;
|
||||
struct audio_ad_config *priv = (struct audio_ad_config*)audio_hdl;
|
||||
buf = priv->set_buf(priv->priv_el,&priv->current_node);
|
||||
if(!buf)
|
||||
{
|
||||
ret = -1;
|
||||
goto audio_adc_start_err;
|
||||
}
|
||||
priv->irq_func(priv , buf, priv->buf_size);
|
||||
audio_adc_start_err:
|
||||
return res;
|
||||
}
|
||||
|
||||
static int32 global_audio_ad_read(struct audio_ad_config *audio, void* buf, uint32 len)
|
||||
{
|
||||
auadc_read(audio->adc, buf, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
stream *audio_adc_stream_init(const char *name)
|
||||
{
|
||||
stream *s = open_stream_available(name,AUDIONUM,0,opcode_func,NULL);
|
||||
if(s) {
|
||||
global_audio_adc_s = s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void audio_adc_stream_deinit()
|
||||
{
|
||||
int res;
|
||||
if(global_audio_adc_s) {
|
||||
res = close_stream(global_audio_adc_s);
|
||||
if(!res) {
|
||||
global_audio_adc_s = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int audio_adc_init()
|
||||
{
|
||||
int res = 0;
|
||||
stream *s = NULL;
|
||||
|
||||
struct auadc_device *adc = (struct auadc_device *)dev_get(HG_AUADC_DEVID);
|
||||
s = audio_adc_stream_init(S_ADC_AUDIO);
|
||||
if(!s)
|
||||
{
|
||||
res = -1;
|
||||
goto audio_adc_init_err;
|
||||
}
|
||||
|
||||
#if AEC_PROCESS == 1
|
||||
aec_flag = aec_init(8000, 2);
|
||||
if(aec_flag == 0)
|
||||
os_printf("AEC Init success\n");
|
||||
#endif
|
||||
#if NSX_PROCESS == 1
|
||||
nsx_flag = ns_init(8000);
|
||||
if(nsx_flag == 0)
|
||||
os_printf("NSX Init success\n");
|
||||
#endif
|
||||
#if AGC_PROCESS == 1
|
||||
agc_flag = agc_init(kAgcModeAdaptiveDigital, 8000);
|
||||
if(agc_flag == 0)
|
||||
os_printf("AGC Init success\n");
|
||||
#endif
|
||||
#if VAD_PROCESS == 1
|
||||
struct auvad_device *vad_dev = (struct auvad_device*)dev_get(HG_AUVAD_DEVID);
|
||||
auvad_open(vad_dev, AUVAD_CALC_MODE_ENERGY|AUVAD_CALC_MODE_ZCR);
|
||||
vad_flag = vad_init(kVadNormal);
|
||||
if(vad_flag == 0)
|
||||
os_printf("VAD Init success\n");
|
||||
#endif
|
||||
#if MAGIC_SOUND
|
||||
magic_sound = magicSound_init(8000,1,AUDIOLEN);
|
||||
#endif
|
||||
struct audio_adc_s *audio_priv = (struct audio_adc_s*)s->priv;
|
||||
if(audio_priv)
|
||||
{
|
||||
struct audio_ad_config *ad_config = (struct audio_ad_config*)os_malloc(sizeof(struct audio_ad_config));
|
||||
memset(ad_config,0,sizeof(struct audio_ad_config));
|
||||
ad_config->adc = adc;
|
||||
ad_config->priv_el = s;
|
||||
audio_priv->audio_hardware_hdl = ad_config;
|
||||
audio_adc_register(ad_config,s,AUDIOLEN,audio_set_buf,audio_get_buf);
|
||||
ad_config->irq_func = global_audio_ad_read;
|
||||
auadc_open(adc, AUADC_SAMPLE_RATE_8K);
|
||||
auadc_request_irq(adc, AUADC_IRQ_FLAG_HALF | AUADC_IRQ_FLAG_FULL, (auadc_irq_hdl)audio_adc_irq, (uint32)ad_config);
|
||||
audio_adc_start(ad_config);
|
||||
}
|
||||
|
||||
audio_adc_init_err:
|
||||
return res;
|
||||
}
|
||||
|
||||
int audio_adc_deinit()
|
||||
{
|
||||
#if VAD_PROCESS == 1
|
||||
struct auvad_device *vad_dev = (struct auvad_device*)dev_get(HG_AUVAD_DEVID);
|
||||
auvad_close(vad_dev);
|
||||
#endif
|
||||
|
||||
struct auadc_device *adc = (struct auadc_device *)dev_get(HG_AUADC_DEVID);
|
||||
auadc_close(adc);
|
||||
stream *s = NULL;
|
||||
s = audio_adc_stream_init(S_ADC_AUDIO);
|
||||
struct audio_adc_s *audio_priv = (struct audio_adc_s*)s->priv;
|
||||
struct audio_ad_config *ad_config = audio_priv->audio_hardware_hdl;
|
||||
if(ad_config->current_node) {
|
||||
os_printf("adc force current data:%X\n",ad_config->current_node);
|
||||
force_del_data(ad_config->current_node);
|
||||
ad_config->current_node = NULL;
|
||||
}
|
||||
|
||||
if(ad_config->reg_node) {
|
||||
os_printf("adc force reg_node data:%X\n",ad_config->reg_node);
|
||||
force_del_data(ad_config->reg_node);
|
||||
ad_config->reg_node = NULL;
|
||||
}
|
||||
|
||||
audio_adc_stream_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_adc_reinit()
|
||||
{
|
||||
stream *s = NULL;
|
||||
struct auadc_device *adc = (struct auadc_device *)dev_get(HG_AUADC_DEVID);
|
||||
s = audio_adc_stream_init(S_ADC_AUDIO);
|
||||
struct audio_adc_s *audio_priv = (struct audio_adc_s*)s->priv;
|
||||
if(s && audio_priv) {
|
||||
struct audio_ad_config *ad_config = audio_priv->audio_hardware_hdl;
|
||||
memset(ad_config,0,sizeof(struct audio_ad_config));
|
||||
ad_config->adc = adc;
|
||||
ad_config->priv_el = s;
|
||||
audio_priv->audio_hardware_hdl = ad_config;
|
||||
audio_adc_register(ad_config,s,AUDIOLEN,audio_set_buf,audio_get_buf);
|
||||
ad_config->irq_func = global_audio_ad_read;
|
||||
|
||||
#if VAD_PROCESS == 1
|
||||
struct auvad_device *vad_dev = (struct auvad_device*)dev_get(HG_AUVAD_DEVID);
|
||||
auvad_open(vad_dev, AUVAD_CALC_MODE_ENERGY|AUVAD_CALC_MODE_ZCR);
|
||||
#endif
|
||||
|
||||
auadc_open(adc, AUADC_SAMPLE_RATE_8K);
|
||||
auadc_request_irq(adc, AUADC_IRQ_FLAG_HALF | AUADC_IRQ_FLAG_FULL, (auadc_irq_hdl)audio_adc_irq, (uint32)ad_config);
|
||||
audio_adc_start(ad_config);
|
||||
}
|
||||
audio_adc_stream_deinit();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,897 @@
|
||||
#include "sys_config.h"
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "string.h"
|
||||
#include "osal/task.h"
|
||||
#include "osal/semaphore.h"
|
||||
#include "osal/msgqueue.h"
|
||||
#include "osal/string.h"
|
||||
#include "hal/audac.h"
|
||||
#include "stream_frame.h"
|
||||
#include "osal_file.h"
|
||||
#include "stream_frame.h"
|
||||
#include "dev/audio/components/fade/aufade.h"
|
||||
#include "sonic_process.h"
|
||||
|
||||
#ifdef PSRAM_HEAP
|
||||
#define ADUIO_MALLOC os_malloc_psram
|
||||
#define ADUIO_FREE os_free_psram
|
||||
#define ADUIO_ZALLOC os_zalloc_psram
|
||||
#define AUDIONUM (16)
|
||||
#else
|
||||
#define ADUIO_MALLOC os_malloc
|
||||
#define ADUIO_FREE os_free
|
||||
#define ADUIO_ZALLOC os_zalloc
|
||||
#define AUDIONUM (8)
|
||||
#endif
|
||||
|
||||
#define SONIC_PROCESS 1
|
||||
#define FADE_PROCESS 0
|
||||
|
||||
#define AUDIOLEN 320
|
||||
#define CACHE_BUF_LEN 320
|
||||
|
||||
#define AEC_PROCESS 0
|
||||
|
||||
static int prev_filter_type = 0;
|
||||
static stream *global_audio_dac_s = NULL;
|
||||
struct audio_da_config;
|
||||
typedef int32 (*audio_da_write)(struct audio_da_config *audio, void* buf, uint32 len);
|
||||
|
||||
#if AEC_PROCESS == 1
|
||||
int16 aecm_buf[CACHE_BUF_LEN/2] = {0};
|
||||
#endif
|
||||
|
||||
static uint32_t empty_buf[AUDIOLEN/4];
|
||||
|
||||
struct sonic_process_priv {
|
||||
sonicStream sonic_s;
|
||||
int samplingRate;
|
||||
int channel;
|
||||
float pitch;
|
||||
float speed;
|
||||
struct os_task task_hdl;
|
||||
struct os_semaphore sema;
|
||||
struct data_structure *r_current_data;
|
||||
struct data_structure *s_current_data;
|
||||
};
|
||||
struct sonic_process_priv *sonic_priv = NULL;
|
||||
|
||||
struct audio_dac_priv {
|
||||
struct os_semaphore cache_sema;
|
||||
struct os_task cache_task_hdl;
|
||||
uint32_t s_offset;
|
||||
uint32_t d_offset;
|
||||
uint32_t res_len;
|
||||
uint32_t buf_len;
|
||||
uint32_t buf_index;
|
||||
int8_t status;
|
||||
int16_t *buf[4];
|
||||
struct data_structure *current_data;
|
||||
#if FADE_PROCESS
|
||||
struct os_msgqueue fade_msg;
|
||||
struct os_task fade_task_hdl;
|
||||
uint8_t fade_mode;
|
||||
#endif
|
||||
};
|
||||
static struct audio_dac_priv *audac_priv = NULL;
|
||||
|
||||
typedef struct audio_da_config
|
||||
{
|
||||
struct audac_device *dac;
|
||||
void *current_node;
|
||||
void *reg_node;
|
||||
audio_da_write irq_func;
|
||||
void *play_empty_buf; //作为喇叭的时候,需要配置,size与buf_size一致,可以是malloc也可以是固定,如果是malloc,需要自己去free
|
||||
int buf_size;
|
||||
uint8_t audio_hz;
|
||||
uint8_t is_empty;
|
||||
}audio_da_config;
|
||||
|
||||
audio_da_config global_audio_da;
|
||||
|
||||
int get_audio_dac_set_filter_type(void);
|
||||
void audio_dac_set_filter_type(int filter_type);
|
||||
int audio_dac_get_samplingrate(void);
|
||||
|
||||
#ifndef PSRAM_HEAP
|
||||
static void *audio_dac_get_buf(void *priv_el,void *el_point,int *buf_size)
|
||||
{
|
||||
stream *dest = (stream *)priv_el;
|
||||
struct data_structure *data_s = recv_real_data(dest);
|
||||
void *buf = NULL;
|
||||
void **point = (void**)el_point;
|
||||
if(data_s) {
|
||||
buf = get_stream_real_data(data_s);
|
||||
*buf_size = get_stream_real_data_len(data_s);
|
||||
*point = (void*)data_s;
|
||||
}
|
||||
else {
|
||||
*point = NULL;
|
||||
return NULL;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void audio_dac_free_buf(void *el_point)
|
||||
{
|
||||
struct data_structure *data_s = (struct data_structure *)el_point;
|
||||
if(!data_s) {
|
||||
return;
|
||||
}
|
||||
free_data(data_s);
|
||||
data_s = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
void audio_dac_irq(uint32 irq, uint32 irq_data)
|
||||
{
|
||||
audio_da_config *audio_da_cfg = (audio_da_config *)irq_data;
|
||||
#ifndef PSRAM_HEAP
|
||||
void *buf = NULL;
|
||||
int32_t buf_size = 0;
|
||||
#endif
|
||||
//满
|
||||
if (irq & AUDAC_IRQ_FLAG_FULL) {
|
||||
if(audio_da_cfg->current_node) {
|
||||
#ifdef PSRAM_HEAP
|
||||
os_sema_up(&audac_priv->cache_sema);
|
||||
#else
|
||||
audio_dac_free_buf(audio_da_cfg->current_node);
|
||||
#endif
|
||||
audio_da_cfg->current_node = NULL;
|
||||
}
|
||||
else {
|
||||
audio_da_cfg->is_empty = 1;
|
||||
}
|
||||
if(audio_da_cfg->reg_node) {
|
||||
#if FADE_PROCESS
|
||||
if(audac_priv->fade_mode == 1) {
|
||||
audac_priv->fade_mode = 0;
|
||||
if(os_msgq_put(&audac_priv->fade_msg, audac_priv->fade_mode, 0) < 0) {
|
||||
audac_priv->fade_mode = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
audio_da_cfg->current_node = audio_da_cfg->reg_node;
|
||||
audio_da_cfg->reg_node = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//半
|
||||
if (irq & AUDAC_IRQ_FLAG_HALF) {
|
||||
#ifdef PSRAM_HEAP
|
||||
if(audio_da_cfg->reg_node) {
|
||||
os_sema_up(&audac_priv->cache_sema);
|
||||
}
|
||||
if(audac_priv->status > 0) {
|
||||
audac_priv->status--;
|
||||
audio_da_cfg->reg_node = audac_priv->buf[audac_priv->buf_index%4];
|
||||
audac_priv->buf_index++;
|
||||
audio_da_cfg->irq_func(audio_da_cfg , audio_da_cfg->reg_node, audac_priv->buf_len);
|
||||
audio_da_cfg->is_empty = 0;
|
||||
}
|
||||
#else
|
||||
buf = audio_dac_get_buf(global_audio_dac_s, &audio_da_cfg->reg_node, &buf_size);
|
||||
if(buf) {
|
||||
audio_da_cfg->irq_func(audio_da_cfg, buf, buf_size);
|
||||
audio_da_cfg->is_empty = 0;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
if(audio_da_cfg->play_empty_buf)
|
||||
{
|
||||
#if FADE_PROCESS
|
||||
if(audac_priv->fade_mode == 0) {
|
||||
audac_priv->fade_mode = 1;
|
||||
if(os_msgq_put(&audac_priv->fade_msg, audac_priv->fade_mode, 0) < 0) {
|
||||
audac_priv->fade_mode = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
audio_da_cfg->irq_func(audio_da_cfg , audio_da_cfg->play_empty_buf, audio_da_cfg->buf_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int32 global_audio_da_write(struct audio_da_config *audio, void* buf, uint32 len)
|
||||
{
|
||||
#if AEC_PROCESS == 1
|
||||
push_farbuf(buf, len/2, 8000);
|
||||
#endif
|
||||
audac_write(audio->dac, buf, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if SONIC_PROCESS
|
||||
static int opcode_func_sonic_r(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
enable_stream(s,1);
|
||||
s->priv = (void*)SOUND_ALL;
|
||||
}
|
||||
break;
|
||||
//在发送到这个流的时候,进行数据包过滤
|
||||
case STREAM_FILTER_DATA:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
int filter_type = (int)get_audio_dac_set_filter_type();
|
||||
if(GET_DATA_TYPE1(data->type) != SOUND) {
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
if(!filter_type || GET_DATA_TYPE2(data->type) == SOUND_ALL) {
|
||||
}
|
||||
else {
|
||||
if(!(filter_type && (filter_type == GET_DATA_TYPE2(data->type))))
|
||||
{
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_RECV_FILTER_DATA:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
if(GET_DATA_TYPE1(data->type) != SOUND) {
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
int filter_type = (int)get_audio_dac_set_filter_type();
|
||||
if(!filter_type || GET_DATA_TYPE2(data->type) == SOUND_ALL) {
|
||||
}
|
||||
else {
|
||||
if(!(filter_type && (GET_DATA_TYPE2(filter_type)== GET_DATA_TYPE2(data->type)))) {
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_SEND_CMD:
|
||||
{
|
||||
uint32_t cmd = (uint32_t)priv;
|
||||
if(GET_CMD_TYPE1(cmd) == CMD_AUDIO_DAC) {
|
||||
os_printf("!!!!!!!!!cmd:%X\n",cmd);
|
||||
s->priv = (void*)GET_CMD_TYPE2(cmd);
|
||||
}
|
||||
else if(GET_CMD_TYPE1(cmd) == CMD_AUDIO_DAC_MODIFY_HZ) {
|
||||
extern void audio_da_recfg(uint32_t hz);
|
||||
audio_da_recfg(GET_CMD_TYPE2(cmd));
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
static uint32_t get_sonic_data_len(void *data)
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
return (uint32_t)d->priv;
|
||||
}
|
||||
static uint32_t set_sonic_data_len(void *data,uint32_t len)
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
d->priv = (void*)len;
|
||||
return (uint32_t)len;
|
||||
}
|
||||
static stream_ops_func stream_sonic_ops =
|
||||
{
|
||||
.get_data_len = get_sonic_data_len,
|
||||
.set_data_len = set_sonic_data_len,
|
||||
};
|
||||
static int opcode_func_sonic_s(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
stream_data_dis_mem_custom(s);
|
||||
streamSrc_bind_streamDest(s,R_AUDIO_TEST);
|
||||
streamSrc_bind_streamDest(s,R_SPEAKER);
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_DIS:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
data->ops = &stream_sonic_ops;
|
||||
data->data = (void*)ADUIO_MALLOC(AUDIOLEN);
|
||||
}
|
||||
break;
|
||||
|
||||
case STREAM_DATA_DESTORY:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
if(data->data)
|
||||
{
|
||||
ADUIO_FREE(data->data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
//默认都返回成功
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void set_sonic_speed(struct sonic_process_priv *sonic_priv, float speed)
|
||||
{
|
||||
if(!sonic_priv)
|
||||
return;
|
||||
sonic_priv->speed = speed;
|
||||
os_sema_up(&sonic_priv->sema);
|
||||
}
|
||||
void set_sonic_pitch(struct sonic_process_priv *sonic_priv, float pitch)
|
||||
{
|
||||
sonic_priv->pitch = pitch;
|
||||
os_sema_up(&sonic_priv->sema);
|
||||
}
|
||||
void set_sonic_samplingRate(struct sonic_process_priv *sonic_priv, int samplingRate)
|
||||
{
|
||||
if(!sonic_priv)
|
||||
return;
|
||||
sonic_priv->samplingRate = samplingRate;
|
||||
os_sema_up(&sonic_priv->sema);
|
||||
}
|
||||
|
||||
static void audac_sonic_process(void *d)
|
||||
{
|
||||
sonicStream sonic_s = (sonicStream)d;
|
||||
int16_t *sonic_stream_inbuf = NULL;
|
||||
int16_t *sonic_stream_outbuf = NULL;
|
||||
struct data_structure *sonic_data_r = NULL;
|
||||
struct data_structure *sonic_data_s = NULL;
|
||||
stream* sonic_stream_s = NULL;
|
||||
stream* sonic_stream_r = NULL;
|
||||
int sonicstream_cache = 0;
|
||||
volatile int sonicstream_input_len = 0;
|
||||
int sonicstream_output_len = 0;
|
||||
|
||||
sonic_stream_s = open_stream_available(S_SONIC_PROCESS,AUDIONUM,0,opcode_func_sonic_s,NULL);
|
||||
sonic_stream_r = open_stream_available(R_SONIC_PROCESS,0,AUDIONUM,opcode_func_sonic_r,NULL);
|
||||
if(!sonic_stream_s || !sonic_stream_r)
|
||||
{
|
||||
os_printf("open sonic process stream err\n");
|
||||
goto audac_sonic_process_end;
|
||||
}
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(os_sema_down(&sonic_priv->sema,0) == 1) {
|
||||
sonicStream_set_speed(sonic_s, sonic_priv->speed);
|
||||
}
|
||||
|
||||
sonic_data_r = recv_real_data(sonic_stream_r);
|
||||
sonic_priv->r_current_data = sonic_data_r;
|
||||
if(sonic_data_r)
|
||||
{
|
||||
sonic_stream_inbuf = get_stream_real_data(sonic_data_r);
|
||||
sonicstream_input_len = get_stream_real_data_len(sonic_data_r);
|
||||
sonicStream_input_data(sonic_s, sonic_stream_inbuf, sonicstream_input_len/2);
|
||||
sonicstream_cache = sonicStream_output_available(sonic_s);
|
||||
while(sonicstream_cache >= (AUDIOLEN>>1)) {
|
||||
sonic_data_s = get_src_data_f(sonic_stream_s);
|
||||
sonic_priv->s_current_data = sonic_data_s;
|
||||
if(sonic_data_s) {
|
||||
sonic_stream_outbuf = get_stream_real_data(sonic_data_s);
|
||||
sonicstream_output_len = sonicStream_output_data(sonic_s, sonic_stream_outbuf, (AUDIOLEN>>1));
|
||||
if(sonicstream_output_len > 0) {
|
||||
sonic_data_s->type = SET_DATA_TYPE(SOUND, GET_DATA_TYPE2(sonic_data_r->type));
|
||||
set_stream_real_data_len(sonic_data_s,(sonicstream_output_len<<1));
|
||||
send_data_to_stream(sonic_data_s);
|
||||
sonic_priv->s_current_data = NULL;
|
||||
sonicstream_cache -= sonicstream_output_len;
|
||||
}
|
||||
}
|
||||
else
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
free_data(sonic_data_r);
|
||||
sonic_priv->r_current_data = NULL;
|
||||
}
|
||||
else {
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
audac_sonic_process_end:
|
||||
if(sonic_stream_s)
|
||||
{
|
||||
close_stream(sonic_stream_s);
|
||||
}
|
||||
|
||||
if(sonic_stream_r)
|
||||
{
|
||||
close_stream(sonic_stream_r);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FADE_PROCESS
|
||||
static void audio_dac_fade(void *d)
|
||||
{
|
||||
uint32_t fade_mode = 0;
|
||||
struct aufade_device *fade = (struct aufade_device *)dev_get(HG_AUFADE_DEVID);
|
||||
|
||||
while(1) {
|
||||
fade_mode = os_msgq_get(&audac_priv->fade_msg,-1);
|
||||
//fade out
|
||||
if(fade_mode == 1) {
|
||||
os_printf("\n*********fade mode:%d*********\n",fade_mode);
|
||||
aufade_ioctl(fade, AUFADE_IOCTL_CMD_SET_STEP, AUFADE_STEP_4, 0);
|
||||
aufade_ioctl(fade, AUFADE_IOCTL_CMD_SET_SAMPLE, AUFADE_SAMPLE_1, 0);
|
||||
aufade_start(fade, AUFADE_OUT);
|
||||
}
|
||||
else if(fade_mode == 0) {
|
||||
os_printf("\n*********fade mode:%d*********\n",fade_mode);
|
||||
aufade_ioctl(fade, AUFADE_IOCTL_CMD_SET_STEP, AUFADE_STEP_4, 0);
|
||||
aufade_ioctl(fade, AUFADE_IOCTL_CMD_SET_SAMPLE, AUFADE_SAMPLE_1, 0);
|
||||
aufade_start(fade, AUFADE_IN);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
void audac_priv_clear()
|
||||
{
|
||||
audac_priv->res_len = CACHE_BUF_LEN;
|
||||
audac_priv->d_offset = 0;
|
||||
audac_priv->s_offset = 0;
|
||||
}
|
||||
|
||||
void audio_dac_cache(void *d)
|
||||
{
|
||||
stream *s = (stream *)d;
|
||||
struct data_structure *data = NULL;
|
||||
int16_t *s_buf = NULL;
|
||||
uint32_t get_buf_len = 0;
|
||||
uint8_t buf_index = 0;
|
||||
|
||||
audac_priv_clear();
|
||||
audac_priv->status = 0;
|
||||
audac_priv->buf_index = 0;
|
||||
|
||||
while(1) {
|
||||
data = recv_real_data(s);
|
||||
if(data)
|
||||
{
|
||||
audac_priv->current_data = data;
|
||||
s_buf = get_stream_real_data(data);
|
||||
get_buf_len = get_stream_real_data_len(data);
|
||||
audac_priv->s_offset = 0;
|
||||
while(get_buf_len >= audac_priv->res_len) {
|
||||
hw_memcpy(audac_priv->buf[buf_index%4]+(audac_priv->d_offset/2), s_buf+(audac_priv->s_offset/2), audac_priv->res_len);
|
||||
get_buf_len -= audac_priv->res_len;
|
||||
audac_priv->buf_len = CACHE_BUF_LEN;
|
||||
audac_priv->s_offset += audac_priv->res_len;
|
||||
audac_priv->status++;
|
||||
os_sema_down(&audac_priv->cache_sema, -1);
|
||||
audac_priv->res_len = CACHE_BUF_LEN;
|
||||
audac_priv->d_offset = 0;
|
||||
buf_index++;
|
||||
}
|
||||
if(get_buf_len) {
|
||||
hw_memcpy(audac_priv->buf[buf_index%4]+(audac_priv->d_offset/2), s_buf+(audac_priv->s_offset/2), get_buf_len);
|
||||
audac_priv->res_len = CACHE_BUF_LEN - get_buf_len;
|
||||
audac_priv->d_offset = get_buf_len;
|
||||
audac_priv->s_offset = 0;
|
||||
get_buf_len = 0;
|
||||
}
|
||||
free_data(data);
|
||||
audac_priv->current_data = NULL;
|
||||
}
|
||||
else {
|
||||
if(audac_priv->status == 0) {
|
||||
if(audac_priv->d_offset > 0) {
|
||||
hw_memset(audac_priv->buf[buf_index%4]+(audac_priv->d_offset/2), 0, (CACHE_BUF_LEN-audac_priv->d_offset));
|
||||
audac_priv->buf_len = CACHE_BUF_LEN;
|
||||
audac_priv->status++;
|
||||
os_sema_down(&audac_priv->cache_sema, -1);
|
||||
buf_index++;
|
||||
audac_priv_clear();
|
||||
get_buf_len = 0;
|
||||
}
|
||||
else
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
else
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int opcode_func(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
enable_stream(s,1);
|
||||
s->priv = (void*)SOUND_ALL;
|
||||
audac_priv = (struct audio_dac_priv*)ADUIO_ZALLOC(sizeof(struct audio_dac_priv));
|
||||
if(audac_priv) {
|
||||
#ifdef PSRAM_HEAP
|
||||
audac_priv->buf[0] = (int16_t *)custom_malloc(CACHE_BUF_LEN);
|
||||
audac_priv->buf[1] = (int16_t *)custom_malloc(CACHE_BUF_LEN);
|
||||
audac_priv->buf[2] = (int16_t *)custom_malloc(CACHE_BUF_LEN);
|
||||
audac_priv->buf[3] = (int16_t *)custom_malloc(CACHE_BUF_LEN);
|
||||
os_sema_init(&audac_priv->cache_sema,3);
|
||||
OS_TASK_INIT("audio_dac_cache", &audac_priv->cache_task_hdl, audio_dac_cache, s, OS_TASK_PRIORITY_ABOVE_NORMAL, 1024);
|
||||
#endif
|
||||
#if FADE_PROCESS
|
||||
os_msgq_init(&audac_priv->fade_msg, 1);
|
||||
OS_TASK_INIT("audio_dac_fade", &audac_priv->fade_task_hdl, audio_dac_fade, NULL, OS_TASK_PRIORITY_ABOVE_NORMAL, 1024);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SONIC_PROCESS
|
||||
sonic_priv = (struct sonic_process_priv*)ADUIO_ZALLOC(sizeof(struct sonic_process_priv));
|
||||
if(sonic_priv) {
|
||||
sonic_priv->samplingRate = audio_dac_get_samplingrate();
|
||||
sonic_priv->channel = 1;
|
||||
sonic_priv->pitch = 1.0;
|
||||
sonic_priv->speed = 1.0;
|
||||
sonic_priv->sonic_s = sonicStream_init(sonic_priv->samplingRate,sonic_priv->channel,sonic_priv->speed,sonic_priv->pitch);
|
||||
os_sema_init(&sonic_priv->sema,0);
|
||||
OS_TASK_INIT("audac_sonic_process", &sonic_priv->task_hdl, audac_sonic_process, sonic_priv->sonic_s, OS_TASK_PRIORITY_ABOVE_NORMAL-1, 1024);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
//在发送到这个流的时候,进行数据包过滤
|
||||
case STREAM_FILTER_DATA:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
int filter_type = (int)s->priv;
|
||||
if(GET_DATA_TYPE1(data->type) != SOUND)
|
||||
{
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
//永远不过滤
|
||||
if(!filter_type || GET_DATA_TYPE2(data->type) == SOUND_ALL)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
//过滤不匹配的数据包
|
||||
if(!(filter_type && (filter_type == GET_DATA_TYPE2(data->type))))
|
||||
{
|
||||
//os_printf("filter_type:%d\tdata_type:%d\t%X\n",filter_type,GET_DATA_TYPE2(data->type),s);
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
//流接收后,数据包也要检查是否需要过滤或者是不是因为逻辑条件符合需要过滤
|
||||
case STREAM_RECV_FILTER_DATA:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
if(GET_DATA_TYPE1(data->type) != SOUND)
|
||||
{
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
int filter_type = (int)s->priv;
|
||||
//永远不过滤
|
||||
if(!filter_type || GET_DATA_TYPE2(data->type) == SOUND_ALL)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
//过滤不匹配的数据包
|
||||
if(!(filter_type && (GET_DATA_TYPE2(filter_type)== GET_DATA_TYPE2(data->type))))
|
||||
{
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
//接收到命令,可以尝试执行命令的接口
|
||||
case STREAM_SEND_CMD:
|
||||
{
|
||||
uint32_t cmd = (uint32_t)priv;
|
||||
//只是接受支持的命令
|
||||
if(GET_CMD_TYPE1(cmd) == CMD_AUDIO_DAC)
|
||||
{
|
||||
os_printf("!!!!!!!!!cmd:%X\n",cmd);
|
||||
s->priv = (void*)GET_CMD_TYPE2(cmd);
|
||||
}
|
||||
else if(GET_CMD_TYPE1(cmd) == CMD_AUDIO_DAC_MODIFY_HZ)
|
||||
{
|
||||
extern void audio_da_recfg(uint32_t hz);
|
||||
audio_da_recfg(GET_CMD_TYPE2(cmd));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
//优先创建音频的流
|
||||
stream *audio_dac_stream_init(const char *name)
|
||||
{
|
||||
stream *s = open_stream_available(name,0,AUDIONUM,opcode_func,NULL);
|
||||
if(s)
|
||||
{
|
||||
global_audio_dac_s = s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
//关闭音频流
|
||||
void audio_dac_stream_deinit()
|
||||
{
|
||||
int res;
|
||||
if(global_audio_dac_s)
|
||||
{
|
||||
res = close_stream(global_audio_dac_s);
|
||||
if(!res)
|
||||
{
|
||||
global_audio_dac_s = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void audio_da_init()
|
||||
{
|
||||
struct aufade_device *fade = (struct aufade_device *)dev_get(HG_AUFADE_DEVID);
|
||||
aufade_open(fade);
|
||||
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
|
||||
|
||||
struct audac_device *audio_da = (struct audac_device *)dev_get(HG_AUDAC_DEVID);
|
||||
|
||||
memset(&global_audio_da,0,sizeof(global_audio_da));
|
||||
audio_da_config *audio_da_cfg = &global_audio_da;
|
||||
audio_da_cfg->dac = audio_da;
|
||||
|
||||
audio_da_cfg->buf_size = AUDIOLEN;
|
||||
audio_da_cfg->play_empty_buf = empty_buf;
|
||||
audio_da_cfg->irq_func = global_audio_da_write;
|
||||
audio_da_cfg->audio_hz = AUDAC_SAMPLE_RATE_8K;
|
||||
|
||||
stream *dest = audio_dac_stream_init(R_SPEAKER);
|
||||
*((uint32_t*)0x4000802c) |= 0x690000;
|
||||
audac_open(audio_da, audio_da_cfg->audio_hz );
|
||||
audac_request_irq(audio_da, AUDAC_IRQ_FLAG_HALF | AUDAC_IRQ_FLAG_FULL, (audac_irq_hdl)audio_dac_irq, (uint32_t)audio_da_cfg);
|
||||
audio_da_cfg->irq_func(audio_da_cfg , audio_da_cfg->play_empty_buf, audio_da_cfg->buf_size);
|
||||
global_audio_dac_s = dest;
|
||||
return;
|
||||
}
|
||||
|
||||
void audio_da_deinit()
|
||||
{
|
||||
struct audac_device *audio_da = (struct audac_device *)dev_get(HG_AUDAC_DEVID);
|
||||
audio_da_config *audio_da_cfg = &global_audio_da;
|
||||
struct aufade_device *fade = (struct aufade_device *)dev_get(HG_AUFADE_DEVID);
|
||||
aufade_close(fade);
|
||||
audac_close(audio_da);
|
||||
prev_filter_type = get_audio_dac_set_filter_type();
|
||||
audio_dac_set_filter_type(SOUND_NONE);
|
||||
//清除中断没有处理完的数据
|
||||
#ifdef PSRAM_HEAP
|
||||
if(audac_priv->current_data)
|
||||
{
|
||||
free_data(audac_priv->current_data);
|
||||
audac_priv->current_data = NULL;
|
||||
}
|
||||
if(audio_da_cfg->reg_node) {
|
||||
os_sema_up(&audac_priv->cache_sema);
|
||||
}
|
||||
if(audio_da_cfg->current_node) {
|
||||
os_sema_up(&audac_priv->cache_sema);
|
||||
}
|
||||
#else
|
||||
if(audio_da_cfg->reg_node) {
|
||||
free_data(audio_da_cfg->reg_node);
|
||||
audio_da_cfg->reg_node = NULL;
|
||||
}
|
||||
if(audio_da_cfg->reg_node) {
|
||||
free_data(audio_da_cfg->reg_node);
|
||||
audio_da_cfg->reg_node = NULL;
|
||||
}
|
||||
#endif
|
||||
#ifdef SONIC_PRIV
|
||||
if(sonic_priv->r_current_data)
|
||||
{
|
||||
free_data(sonic_priv->r_current_data);
|
||||
sonic_priv->r_current_data = NULL;
|
||||
}
|
||||
if(sonic_priv->s_current_data)
|
||||
{
|
||||
force_del_data(sonic_priv->s_current_data);
|
||||
sonic_priv->s_current_data = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void audio_da_reinit()
|
||||
{
|
||||
struct audac_device *audio_da = (struct audac_device *)dev_get(HG_AUDAC_DEVID);
|
||||
struct aufade_device *fade = (struct aufade_device *)dev_get(HG_AUFADE_DEVID);
|
||||
aufade_open(fade);
|
||||
//这里成立的前提是原来stream已经创建过,否则可能有问题
|
||||
stream *dest = audio_dac_stream_init(R_SPEAKER);
|
||||
memset(&global_audio_da,0,sizeof(global_audio_da));
|
||||
audio_da_config *audio_da_cfg = &global_audio_da;
|
||||
audio_da_cfg->dac = audio_da;
|
||||
|
||||
audio_da_cfg->buf_size = AUDIOLEN;
|
||||
audio_da_cfg->play_empty_buf = empty_buf;
|
||||
audio_da_cfg->irq_func = global_audio_da_write;
|
||||
audio_da_cfg->audio_hz = AUDAC_SAMPLE_RATE_8K;
|
||||
*((uint32_t*)0x4000802c) |= 0x690000;
|
||||
audac_open(audio_da, audio_da_cfg->audio_hz);
|
||||
os_printf("!!!!audio_da_cfg:%X\n",audio_da_cfg);
|
||||
audac_request_irq(audio_da, AUDAC_IRQ_FLAG_HALF | AUDAC_IRQ_FLAG_FULL, (audac_irq_hdl)audio_dac_irq, (uint32_t)audio_da_cfg);
|
||||
audio_da_cfg->irq_func(audio_da_cfg , audio_da_cfg->play_empty_buf, audio_da_cfg->buf_size);
|
||||
global_audio_dac_s = dest;
|
||||
//这个函数只是重新初始化dac硬件,所以流与init的时候有区别,这里需要关闭一次(实际内部没有关闭,与audio_dac_stream_init成对使用)
|
||||
audio_dac_stream_deinit();
|
||||
audio_dac_set_filter_type(prev_filter_type);
|
||||
}
|
||||
|
||||
//音频采样率重新修改
|
||||
void audio_da_recfg(uint32_t hz)
|
||||
{
|
||||
os_printf("%s hz:%d\n",__FUNCTION__,hz);
|
||||
//识别采样率,如果一样,则直接退出
|
||||
int8_t now_hz_enum = -1;
|
||||
switch(hz)
|
||||
{
|
||||
case 8000:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_8K;
|
||||
break;
|
||||
case 11025:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_11_025K;
|
||||
break;
|
||||
case 16000:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_16K;
|
||||
break;
|
||||
case 22050:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_22_05K;
|
||||
break;
|
||||
case 32000:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_32K;
|
||||
break;
|
||||
case 44100:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_44_1K;
|
||||
break;
|
||||
case 48000:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_48K;
|
||||
break;
|
||||
case 24000:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_24K;
|
||||
break;
|
||||
case 12000:
|
||||
now_hz_enum = AUDAC_SAMPLE_RATE_12K;
|
||||
break;
|
||||
default:
|
||||
now_hz_enum = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
audio_da_config *audio_da_cfg = &global_audio_da;
|
||||
os_printf("now_hz_enum:%d\tlast now_hz_enum:%d\n",now_hz_enum,audio_da_cfg->audio_hz);
|
||||
|
||||
//采样率不需要修改或者采样率设置错误
|
||||
if(audio_da_cfg->audio_hz == now_hz_enum || now_hz_enum == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
struct audac_device *audac_dev = (struct audac_device *)dev_get(HG_AUDAC_DEVID);
|
||||
|
||||
//将当前流的数据也删除,然后才可以接收其他正确采样率的数据
|
||||
int last_type = get_audio_dac_set_filter_type();
|
||||
|
||||
audio_dac_set_filter_type(SOUND_NONE);
|
||||
#if SONIC_PROCESS
|
||||
set_sonic_samplingRate(sonic_priv, hz);
|
||||
#endif
|
||||
//等待播放数据完毕,然后切换采样率
|
||||
uint32_t count = 0;
|
||||
//等待中断数据播放完毕
|
||||
while( !(audio_da_cfg->is_empty) && count++<1000)
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
|
||||
audac_ioctl(audac_dev,AUDAC_IOCTL_CMD_CHANGE_SAMPLE_RATE,now_hz_enum,0);
|
||||
audio_dac_set_filter_type(last_type);
|
||||
|
||||
audio_da_cfg->audio_hz = now_hz_enum;
|
||||
os_printf("audio_da_cfg:%X\tnow_hz_enum:%d\n",audio_da_cfg,now_hz_enum);
|
||||
audio_da_cfg->irq_func(audio_da_cfg , audio_da_cfg->play_empty_buf, audio_da_cfg->buf_size);
|
||||
}
|
||||
|
||||
void audio_dac_set_filter_type(int filter_type)
|
||||
{
|
||||
if(global_audio_dac_s)
|
||||
{
|
||||
os_printf("filter_type:%d\t%X\n",filter_type,global_audio_dac_s);
|
||||
global_audio_dac_s->priv = (void*)filter_type;
|
||||
}
|
||||
}
|
||||
|
||||
void print_audio_dac_set_filter_type()
|
||||
{
|
||||
if(global_audio_dac_s)
|
||||
{
|
||||
os_printf("type:%X\n",global_audio_dac_s->priv);
|
||||
}
|
||||
}
|
||||
|
||||
int get_audio_dac_set_filter_type(void)
|
||||
{
|
||||
if(global_audio_dac_s)
|
||||
{
|
||||
return (int)global_audio_dac_s->priv;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int audio_dac_get_samplingrate(void)
|
||||
{
|
||||
audio_da_config *play = &global_audio_da;
|
||||
int32_t samplingrate = -1;
|
||||
|
||||
switch(play->audio_hz)
|
||||
{
|
||||
case AUDAC_SAMPLE_RATE_8K:
|
||||
samplingrate = 8000;
|
||||
break;
|
||||
case AUDAC_SAMPLE_RATE_11_025K:
|
||||
samplingrate = 11025;
|
||||
break;
|
||||
case AUDAC_SAMPLE_RATE_12K:
|
||||
samplingrate = 12000;
|
||||
break;
|
||||
case AUDAC_SAMPLE_RATE_16K:
|
||||
samplingrate = 16000;
|
||||
break;
|
||||
case AUDAC_SAMPLE_RATE_22_05K:
|
||||
samplingrate = 22050;
|
||||
break;
|
||||
case AUDAC_SAMPLE_RATE_24K:
|
||||
samplingrate = 24000;
|
||||
break;
|
||||
case AUDAC_SAMPLE_RATE_32K:
|
||||
samplingrate = 32000;
|
||||
break;
|
||||
case AUDAC_SAMPLE_RATE_44_1K:
|
||||
samplingrate = 44100;
|
||||
break;
|
||||
case AUDAC_SAMPLE_RATE_48K:
|
||||
samplingrate = 48000;
|
||||
break;
|
||||
|
||||
}
|
||||
printf("now DAC samplingrate:%d\n",samplingrate);
|
||||
return samplingrate;
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
#include "hal/i2s.h"
|
||||
#include "hal/i2c.h"
|
||||
#include "osal/sleep.h"
|
||||
#include "hal_i2s_audio.h"
|
||||
#include "osal/string.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define __iis_sram_acton __at_section(".iiscode")
|
||||
|
||||
__iis_sram_acton static void demo_sram(uint32 sys_con,uint32 con)
|
||||
{
|
||||
/* 下面三句要放在SRAM上跑 */
|
||||
//enable iis0
|
||||
(*((volatile uint32 *)0x40004900)) |= BIT(0);
|
||||
|
||||
|
||||
SYSCTRL_REG_OPT(
|
||||
SYSCTRL->SYS_CON2 = sys_con;
|
||||
);
|
||||
|
||||
//iis 1 set rx
|
||||
(*((volatile uint32 *)0x40004A00)) = con;
|
||||
}
|
||||
|
||||
|
||||
static void audio_8311_irq_handle(uint32 irq, uint32 irq_data)
|
||||
{
|
||||
audio_i2s_config *priv = (audio_i2s_config*)irq_data;
|
||||
void *buf;
|
||||
int buf_size;
|
||||
//speaker_user_action* speaker_act = (speaker_user_action*)priv->speaker_management->app_action;
|
||||
if (I2S_IRQ_FLAG_HALF == irq)
|
||||
{
|
||||
buf = priv->set_buf(priv->priv_el,&priv->reg_node,&buf_size);
|
||||
|
||||
if(buf)
|
||||
{
|
||||
priv->irq_func(priv->i2s_dev , buf, buf_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(priv->play_empty_buf)
|
||||
{
|
||||
priv->irq_func(priv->i2s_dev , priv->play_empty_buf, priv->buf_size);
|
||||
}
|
||||
}
|
||||
|
||||
// _os_printf("A");
|
||||
}
|
||||
else if (I2S_IRQ_FLAG_FULL == irq)
|
||||
{
|
||||
|
||||
//半中断有配置新的buf,则将完成的录音帧通知应用层,如果为NULL,则代表没有配置新的buf,只能使用旧的buf
|
||||
if(priv->reg_node)
|
||||
{
|
||||
//buf_size大部分是无效值,如果是喇叭,get_buf则基本是空函数,如果是mic,get_buf则是返回已经录音完成的buf
|
||||
priv->get_buf(priv->priv_el,priv->current_node,&buf_size);
|
||||
priv->current_node = priv->reg_node;
|
||||
priv->reg_node = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//play_config是喇叭配置,mic_config麦克风配置,只要是非NULL,默认传入的参数是对的
|
||||
int audio_i2s_install(audio_i2s_config *play_config,audio_i2s_config *mic_config)
|
||||
{
|
||||
int res = RET_ERR;
|
||||
int duplex_en = 0;
|
||||
struct i2s_device *i2s_dev;
|
||||
audio_i2s_config *config;
|
||||
int i2s_devid;
|
||||
int sample_freq = ~0;
|
||||
int sample_bit = ~0;
|
||||
int data_format = ~0;
|
||||
void *buf;
|
||||
int buf_size;
|
||||
if(!play_config && !mic_config)
|
||||
{
|
||||
goto audio_i2s_install_end;
|
||||
}
|
||||
//需要同步
|
||||
if(play_config && mic_config)
|
||||
{
|
||||
duplex_en = 1;
|
||||
*(unsigned int *)0x40020000=0x3fac87e4;
|
||||
SYSCTRL_REG_OPT(
|
||||
SYSCTRL->SYS_CON3 = (SYSCTRL->SYS_CON3 & ~(0x01 << 27)) | (1 << 27);
|
||||
);
|
||||
extern unsigned int _iis_start;
|
||||
extern unsigned int _iis_end;
|
||||
unsigned int iis_start = (unsigned int)&_iis_start;
|
||||
unsigned int iis_end = (unsigned int)&_iis_end;
|
||||
unsigned int iis_sram_start = (unsigned int)demo_sram;
|
||||
os_memcpy((void*)iis_sram_start,(void*)iis_start,iis_end-iis_start);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
*(unsigned int *)0x40020000=0x3fac87e4;
|
||||
SYSCTRL_REG_OPT(
|
||||
SYSCTRL->SYS_CON3 = (SYSCTRL->SYS_CON3 & ~(0x01 << 27));
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
//打开对应i2s,前提是i2s的id要设置对,否则就会出现异常,后续只是获取id设备,不验证是否为i2s设备,强行转换
|
||||
if(play_config && play_config->i2s_devid != ~0)
|
||||
{
|
||||
config = play_config;
|
||||
config->irq_func = (i2s_irq_func)i2s_write;
|
||||
i2s_devid = config->i2s_devid;
|
||||
i2s_dev = (struct i2s_device *)dev_get(i2s_devid);
|
||||
if(!i2s_dev)
|
||||
{
|
||||
res = I2S_DEV_NULL;
|
||||
goto audio_i2s_install_end;
|
||||
}
|
||||
|
||||
if(!config->play_empty_buf)
|
||||
{
|
||||
res = I2S_PLAY_EMPTY_BUF_NULL;
|
||||
goto audio_i2s_install_end;
|
||||
}
|
||||
|
||||
if(!config->set_buf && !config->get_buf)
|
||||
{
|
||||
res = I2S_REGISTER_FUNC_NULL;
|
||||
goto audio_i2s_install_end;
|
||||
}
|
||||
|
||||
|
||||
config->i2s_dev = i2s_dev;
|
||||
sample_freq = config->sample_freq;
|
||||
sample_bit = config->sample_bit;
|
||||
data_format = config->data_fmt;
|
||||
i2s_open(i2s_dev , I2S_MODE_MASTER, sample_freq, sample_bit);
|
||||
//设置duplex_en
|
||||
i2s_ioctl(i2s_dev,I2S_IOCTL_CMD_SET_DUPLEX,duplex_en);
|
||||
i2s_ioctl(i2s_dev, I2S_IOCTL_CMD_SET_DATA_FMT, data_format);
|
||||
i2s_request_irq(i2s_dev , I2S_IRQ_FLAG_HALF | I2S_IRQ_FLAG_FULL, (i2s_irq_hdl)audio_8311_irq_handle, (uint32)config);
|
||||
config->irq_func(i2s_dev , config->play_empty_buf, config->buf_size);
|
||||
|
||||
|
||||
}
|
||||
|
||||
if(mic_config && mic_config->i2s_devid != ~0)
|
||||
{
|
||||
|
||||
|
||||
config = mic_config;
|
||||
config->irq_func = i2s_read;
|
||||
i2s_devid = config->i2s_devid;
|
||||
i2s_dev = (struct i2s_device *)dev_get(i2s_devid);
|
||||
|
||||
if(!config->set_buf && !config->get_buf)
|
||||
{
|
||||
res = I2S_REGISTER_FUNC_NULL;
|
||||
goto audio_i2s_install_end;
|
||||
}
|
||||
|
||||
if(!i2s_dev)
|
||||
{
|
||||
res = I2S_DEV_NULL;
|
||||
goto audio_i2s_install_end;
|
||||
}
|
||||
config->i2s_dev = i2s_dev;
|
||||
data_format = config->data_fmt;
|
||||
if(duplex_en == 1)
|
||||
{
|
||||
i2s_open(i2s_dev , I2S_MODE_MASTER, sample_freq, sample_bit);
|
||||
}
|
||||
else
|
||||
{
|
||||
i2s_open(i2s_dev , I2S_MODE_MASTER, config->sample_freq, config->sample_bit);
|
||||
}
|
||||
|
||||
//设置duplex_en
|
||||
i2s_ioctl(i2s_dev,I2S_IOCTL_CMD_SET_DUPLEX,duplex_en);
|
||||
i2s_ioctl(i2s_dev, I2S_IOCTL_CMD_SET_DATA_FMT, data_format);
|
||||
i2s_request_irq(i2s_dev , I2S_IRQ_FLAG_HALF | I2S_IRQ_FLAG_FULL, (i2s_irq_hdl)audio_8311_irq_handle, (uint32)config);
|
||||
buf = config->set_buf(config->priv_el,&config->current_node,&buf_size);
|
||||
if(!buf)
|
||||
{
|
||||
res = I2S_MIC_FIRST_BUF_NULL;
|
||||
goto audio_i2s_install_end;
|
||||
}
|
||||
config->irq_func(i2s_dev, buf, buf_size);
|
||||
}
|
||||
|
||||
//如果是同步,则运行同步操作
|
||||
if(duplex_en)
|
||||
{
|
||||
uint32 con = 0;
|
||||
uint32 sys_con = 0;
|
||||
|
||||
__disable_irq();
|
||||
con = (*((volatile uint32 *)0x40004900));
|
||||
con &= ~ BIT(8);
|
||||
con |= BIT(0);
|
||||
|
||||
sys_con = SYSCTRL->SYS_CON2;
|
||||
sys_con &= ~ BIT(0);
|
||||
demo_sram(sys_con,con);
|
||||
__enable_irq();
|
||||
|
||||
}
|
||||
|
||||
res = RET_OK;
|
||||
audio_i2s_install_end:
|
||||
return res;
|
||||
}
|
||||
|
||||
int audio_i2s_uninstall(audio_i2s_config *play_config,audio_i2s_config *mic_config)
|
||||
{
|
||||
int res = RET_ERR;
|
||||
int i2s_devid;
|
||||
struct i2s_device *i2s_dev;
|
||||
audio_i2s_config *config;
|
||||
if(play_config && play_config->i2s_devid != ~0)
|
||||
{
|
||||
config = play_config;
|
||||
i2s_devid = config->i2s_devid;
|
||||
i2s_dev = (struct i2s_device *)dev_get(i2s_devid);
|
||||
if(!i2s_dev)
|
||||
{
|
||||
goto audio_i2s_uninstall_end;
|
||||
}
|
||||
i2s_close(i2s_dev);
|
||||
}
|
||||
|
||||
if(mic_config && mic_config->i2s_devid != ~0)
|
||||
{
|
||||
config = mic_config;
|
||||
i2s_devid = config->i2s_devid;
|
||||
i2s_dev = (struct i2s_device *)dev_get(i2s_devid);
|
||||
if(!i2s_dev)
|
||||
{
|
||||
goto audio_i2s_uninstall_end;
|
||||
}
|
||||
i2s_close(i2s_dev);
|
||||
|
||||
}
|
||||
res = I2S_OK;
|
||||
audio_i2s_uninstall_end:
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
#ifndef __AUDIO_8311_H
|
||||
#define __AUDIO_8311_H
|
||||
#include "hal/i2s.h"
|
||||
|
||||
#define PLAY_MODE 0
|
||||
#define MIC_MODE 1
|
||||
|
||||
|
||||
typedef void *(*audio_i2s_set_buf)(void *priv_el,void *el_point,int *buf_size);
|
||||
typedef void (*audio_i2s_get_buf)(void *priv_el,void *el_point, int *buf_size);
|
||||
typedef int32 (*i2s_irq_func)(struct i2s_device *i2s, void* buf, uint32 len);
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
I2S_OK,
|
||||
I2S_CONFIG_NULL,//
|
||||
I2S_DEV_NULL,//
|
||||
I2S_PLAY_EMPTY_BUF_NULL,
|
||||
I2S_REGISTER_FUNC_NULL,
|
||||
I2S_MIC_FIRST_BUF_NULL,
|
||||
}I2S_ERR;
|
||||
|
||||
|
||||
|
||||
//在有mic和喇叭的时候,sample_freq与sample_bit应该要一致,所以只有一个是有效值,默认是以喇叭的配置为准
|
||||
typedef struct audio_i2s_config
|
||||
{
|
||||
//无需用户配置
|
||||
struct i2s_device *i2s_dev;
|
||||
void *current_node;
|
||||
void *reg_node;
|
||||
i2s_irq_func irq_func;
|
||||
|
||||
//用户配置
|
||||
uint8 type; //0:喇叭 1:麦克风
|
||||
int i2s_devid;
|
||||
int sample_freq;
|
||||
int sample_bit;
|
||||
int data_fmt; //I2S_DATA_FMT_I2S I2S_DATA_FMT_MSB I2S_DATA_FMT_LSB I2S_DATA_FMT_PCM
|
||||
void *play_empty_buf; //作为喇叭的时候,需要配置,size与buf_size一致,可以是malloc也可以是固定,如果是malloc,需要自己去free
|
||||
int buf_size;
|
||||
audio_i2s_set_buf set_buf;
|
||||
audio_i2s_get_buf get_buf;
|
||||
void *priv_el;
|
||||
|
||||
}audio_i2s_config;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int audio_8311_init(int i2c_devid) ;
|
||||
int audio_i2s_install(audio_i2s_config *play_config,audio_i2s_config *mic_config);
|
||||
int audio_i2s_uninstall(audio_i2s_config *play_config,audio_i2s_config *mic_config);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,143 @@
|
||||
#include "typesdef.h"
|
||||
#include "list.h"
|
||||
#include "dev.h"
|
||||
#include "devid.h"
|
||||
|
||||
#include "hal/pdm.h"
|
||||
#include <stdio.h>
|
||||
#include "string.h"
|
||||
#include "pdm_audio.h"
|
||||
|
||||
struct audio_priv
|
||||
{
|
||||
struct hgpdm_v0* pdm_hdl;
|
||||
void *current_node;
|
||||
void *reg_node;
|
||||
//buf暂定open后,就不改变
|
||||
int buf_size;
|
||||
set_buf set_buf;
|
||||
get_buf get_buf;
|
||||
|
||||
//私有结构元素
|
||||
void *priv_el;
|
||||
|
||||
};
|
||||
|
||||
static void audio_irq(uint32 irq, uint32 irq_data)
|
||||
{
|
||||
|
||||
//半中断,切换下一个buf,如果不存在,使用当前的
|
||||
struct audio_priv *priv = (struct audio_priv *)irq_data;
|
||||
void *buf;
|
||||
if(irq == PDM_IRQ_FLAG_DMA_HF)
|
||||
{
|
||||
buf = priv->set_buf(priv->priv_el,&priv->reg_node);
|
||||
//如果reg_node为NULL,则音频录音buf还是原来的buf
|
||||
if(priv->reg_node)
|
||||
{
|
||||
pdm_read((struct pdm_device *)priv->pdm_hdl, buf, priv->buf_size);
|
||||
}
|
||||
}
|
||||
else if(irq == PDM_IRQ_FLAG_DMA_OV)
|
||||
{
|
||||
//半中断有配置新的buf,则将完成的录音帧通知应用层,如果为NULL,则代表没有配置新的buf,只能使用旧的buf
|
||||
if(priv->reg_node)
|
||||
{
|
||||
priv->get_buf(priv->priv_el,priv->current_node);
|
||||
priv->current_node = priv->reg_node;
|
||||
priv->reg_node = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void *pdm_audio_open(enum pdm_sample_freq freq,enum pdm_channel channel)
|
||||
{
|
||||
int ret = 0;
|
||||
int res = RET_OK;
|
||||
struct audio_priv *priv = NULL;
|
||||
|
||||
priv = (struct audio_priv*)malloc(sizeof(struct audio_priv));
|
||||
if(!priv)
|
||||
{
|
||||
ret = -1;
|
||||
goto audio_open_err;
|
||||
}
|
||||
memset(priv,0,sizeof(struct audio_priv));
|
||||
priv->pdm_hdl = (struct hgpdm_v0*)dev_get(HG_PDM0_DEVID);
|
||||
if(!priv->pdm_hdl)
|
||||
{
|
||||
ret = -2;
|
||||
goto audio_open_err;
|
||||
}
|
||||
|
||||
//启动pdm
|
||||
res = pdm_open((struct pdm_device*)priv->pdm_hdl, freq, channel);
|
||||
if(res != RET_OK)
|
||||
{
|
||||
ret = -3;
|
||||
goto audio_open_err;
|
||||
|
||||
}
|
||||
pdm_request_irq((struct pdm_device*)priv->pdm_hdl, PDM_IRQ_FLAG_DMA_OV, (pdm_irq_hdl)audio_irq, (uint32_t)priv);
|
||||
pdm_request_irq((struct pdm_device*)priv->pdm_hdl, PDM_IRQ_FLAG_DMA_HF, (pdm_irq_hdl)audio_irq, (uint32_t)priv);
|
||||
return priv;
|
||||
|
||||
audio_open_err:
|
||||
if(priv)
|
||||
{
|
||||
free(priv);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pdm_audio_register(void *audio_hdl,void *priv_el,int play_size,set_buf audio_set_buf,get_buf audio_get_buf)
|
||||
{
|
||||
struct audio_priv *priv = (struct audio_priv*)audio_hdl;
|
||||
priv->buf_size = play_size;
|
||||
priv->set_buf = audio_set_buf;
|
||||
priv->get_buf = audio_get_buf;
|
||||
priv->priv_el = priv_el;
|
||||
|
||||
}
|
||||
|
||||
int pdm_audio_start(void *audio_hdl)
|
||||
{
|
||||
int ret = 0;
|
||||
int res = 0;
|
||||
void *buf;
|
||||
struct audio_priv *priv = (struct audio_priv*)audio_hdl;
|
||||
buf = priv->set_buf(priv->priv_el,&priv->current_node);
|
||||
|
||||
if(!buf)
|
||||
{
|
||||
ret = -1;
|
||||
goto audio_run_err;
|
||||
}
|
||||
res = pdm_read((struct pdm_device *)priv->pdm_hdl, buf, priv->buf_size);
|
||||
//pdm参数输入错误
|
||||
if(res < 0)
|
||||
{
|
||||
ret = -2;
|
||||
goto audio_run_err;
|
||||
}
|
||||
|
||||
audio_run_err:
|
||||
return res;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void pdm_audio_close(void *audio_hdl)
|
||||
{
|
||||
struct audio_priv *priv;
|
||||
if(audio_hdl)
|
||||
{
|
||||
priv = (struct audio_priv*)audio_hdl;
|
||||
pdm_close((struct pdm_device*)priv->pdm_hdl);
|
||||
free(priv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef __PDM_AUDIO_H
|
||||
#define __PDM_AUDIO_H
|
||||
#include "hal/pdm.h"
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
逻辑:priv_el结构体注册可以是一个函数,然后通过该函数和el_point得到buf
|
||||
******************************************************************************/
|
||||
//返回值是一个buf,录音的buf,priv_el则是应用层的一个结构,el_point则是一个指针地址,audio_set_buf在返回buf前同时要配置el_point的值(最后在audio_get_buf的时候会需要调用)
|
||||
typedef void *(*set_buf)(void *priv_el,void *el_point);
|
||||
//priv_el则是应用层的一个结构,el_point则是可以寻找到buf的一个结构体,el_point的值是audio_set_buf赋值的
|
||||
typedef void (*get_buf)(void *priv_el,void *el_point);
|
||||
|
||||
|
||||
|
||||
|
||||
void pdm_audio_close(void *audio_hdl);
|
||||
int pdm_audio_start(void *audio_hdl);
|
||||
void pdm_audio_register(void *audio_hdl,void *priv_el,int play_size,set_buf set_buf,get_buf get_buf);
|
||||
void *pdm_audio_open(enum pdm_sample_freq freq,enum pdm_channel channel);
|
||||
void *audio_task(const char *name);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user