449 lines
14 KiB
C
449 lines
14 KiB
C
|
#include "mic_stream.h"
|
||
|
#include "app_config.h"
|
||
|
#include "system/includes.h"
|
||
|
#include "audio_splicing.h"
|
||
|
#include "audio_config.h"
|
||
|
#include "asm/dac.h"
|
||
|
#include "audio_enc.h"
|
||
|
#include "audio_dec.h"
|
||
|
#include "media/includes.h"
|
||
|
|
||
|
#include "media/pcm_decoder.h"
|
||
|
|
||
|
|
||
|
#if (TCFG_MIC_EFFECT_ENABLE)
|
||
|
|
||
|
#define MIC_STREAM_TASK_NAME "mic_stream"
|
||
|
|
||
|
|
||
|
struct __mic_stream {
|
||
|
struct adc_mic_ch mic_ch;
|
||
|
struct audio_adc_output_hdl adc_output;
|
||
|
struct __mic_stream_parm *parm;
|
||
|
struct __mic_stream_io out;
|
||
|
u8 *temp_buf;
|
||
|
u8 *adc_buf;
|
||
|
cbuffer_t adc_cbuf;
|
||
|
OS_SEM sem;
|
||
|
struct audio_decoder decoder;
|
||
|
struct audio_mixer_ch mix_ch;
|
||
|
struct audio_res_wait wait;
|
||
|
volatile u8 busy: 1;
|
||
|
volatile u8 release: 1;
|
||
|
volatile u8 revert: 6;
|
||
|
struct pcm_decoder pcm_dec; // pcm解码句柄
|
||
|
struct audio_stream *audio_stream; // 音频流
|
||
|
};
|
||
|
|
||
|
#define MIC_SIZEOF_ALIN(var,al) ((((var)+(al)-1)/(al))*(al))
|
||
|
|
||
|
extern struct audio_dac_hdl dac_hdl;
|
||
|
extern struct audio_mixer mixer;
|
||
|
|
||
|
static int pcm_fread(void *hdl, void *buf, u32 len)
|
||
|
{
|
||
|
len = len / 2;
|
||
|
memset(buf, 0, len);
|
||
|
/* putchar('A'); */
|
||
|
return len;
|
||
|
}
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
/**@brief pcm解码数据输出
|
||
|
@param *entry: 音频流句柄
|
||
|
@param *in: 输入信息
|
||
|
@param *out: 输出信息
|
||
|
@return 输出长度
|
||
|
@note *out未使用
|
||
|
*/
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
static int pcm_dec_data_handler(struct audio_stream_entry *entry,
|
||
|
struct audio_data_frame *in,
|
||
|
struct audio_data_frame *out)
|
||
|
{
|
||
|
struct audio_decoder *decoder = container_of(entry, struct audio_decoder, entry);
|
||
|
struct pcm_decoder *pcm_dec = container_of(decoder, struct pcm_decoder, decoder);
|
||
|
struct __mic_stream *dec = container_of(pcm_dec, struct __mic_stream, pcm_dec);
|
||
|
audio_stream_run(&decoder->entry, in);
|
||
|
/* audio_mixer_ch_pause(&dec->mix_ch, 0); */
|
||
|
return decoder->process_len;
|
||
|
}
|
||
|
static void pcm_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv)
|
||
|
{
|
||
|
}
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
/**@brief pcm解码数据流激活
|
||
|
@param *p: 私有句柄
|
||
|
@return
|
||
|
@note
|
||
|
*/
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
static void dec_out_stream_resume(void *p)
|
||
|
{
|
||
|
struct __mic_stream *dec = (struct __mic_stream *)p;
|
||
|
|
||
|
audio_decoder_resume(&dec->pcm_dec.decoder);
|
||
|
}
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
/**@brief pcm解码启动
|
||
|
@param
|
||
|
@return
|
||
|
@note
|
||
|
*/
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
static int pcm_dec_start(struct __mic_stream *stream)
|
||
|
{
|
||
|
int err = 0;
|
||
|
if (stream == NULL) {
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
err = pcm_decoder_open(&stream->pcm_dec, &decode_task);
|
||
|
if (err) {
|
||
|
return err;
|
||
|
}
|
||
|
pcm_decoder_set_event_handler(&stream->pcm_dec, pcm_dec_event_handler, 0);
|
||
|
pcm_decoder_set_read_data(&stream->pcm_dec, pcm_fread, stream);
|
||
|
pcm_decoder_set_data_handler(&stream->pcm_dec, pcm_dec_data_handler);
|
||
|
|
||
|
audio_mixer_ch_open(&stream->mix_ch, &mixer);
|
||
|
/* audio_mixer_ch_open_head(&stream->mix_ch, &mixer); // 挂载到mixer最前面 */
|
||
|
audio_mixer_ch_set_src(&stream->mix_ch, 0, 0);
|
||
|
/* audio_mixer_ch_set_src(&stream->mix_ch, 1, 1); */
|
||
|
/* audio_mixer_ch_set_no_wait(&stream->mix_ch, 1, 5); // 超时自动丢数 */
|
||
|
/* audio_mixer_ch_pause(&stream->mix_ch, 1); */
|
||
|
// 数据流串联
|
||
|
struct audio_stream_entry *entries[8] = {NULL};
|
||
|
u8 entry_cnt = 0;
|
||
|
entries[entry_cnt++] = &stream->pcm_dec.decoder.entry;
|
||
|
entries[entry_cnt++] = &stream->mix_ch.entry;
|
||
|
stream->audio_stream = audio_stream_open(stream, dec_out_stream_resume);
|
||
|
audio_stream_add_list(stream->audio_stream, entries, entry_cnt);
|
||
|
|
||
|
/* audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC); */
|
||
|
err = audio_decoder_start(&stream->pcm_dec.decoder);
|
||
|
if (err == 0) {
|
||
|
printf("pcm_dec_start ok\n");
|
||
|
}
|
||
|
return err;
|
||
|
}
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
/**@brief pcm解码停止
|
||
|
@param
|
||
|
@return
|
||
|
@note
|
||
|
*/
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
static void pcm_dec_stop(struct __mic_stream *stream)
|
||
|
{
|
||
|
printf("mic stream dec stop \n\n");
|
||
|
if (stream) {
|
||
|
/* audio_decoder_close(&stream->decoder); */
|
||
|
/* audio_mixer_ch_close(&stream->mix_ch); */
|
||
|
pcm_decoder_close(&stream->pcm_dec);
|
||
|
audio_mixer_ch_close(&stream->mix_ch);
|
||
|
if (stream->audio_stream) {
|
||
|
audio_stream_close(stream->audio_stream);
|
||
|
stream->audio_stream = NULL;
|
||
|
}
|
||
|
/* audio_decoder_task_del_wait(&decode_task, &stream->wait); */
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int pcmdec_wait_res_handler(struct audio_res_wait *wait, int event)
|
||
|
{
|
||
|
int err = 0;
|
||
|
struct __mic_stream *stream = container_of(wait, struct __mic_stream, wait);
|
||
|
if (event == AUDIO_RES_GET) {
|
||
|
err = pcm_dec_start(stream);
|
||
|
} else if (event == AUDIO_RES_PUT) {
|
||
|
/* pcm_dec_stop(stream); */
|
||
|
}
|
||
|
|
||
|
return err;
|
||
|
}
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
/**@brief 打开pcm解码
|
||
|
@param
|
||
|
@return
|
||
|
@note
|
||
|
*/
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
static int pcm_dec_open(struct __mic_stream *stream)
|
||
|
{
|
||
|
stream->pcm_dec.ch_num = 2;
|
||
|
stream->pcm_dec.output_ch_num = audio_output_channel_num();
|
||
|
stream->pcm_dec.output_ch_type = audio_output_channel_type();
|
||
|
/* stream->pcm_dec.sample_rate = stream->parm->sample_rate; */
|
||
|
stream->pcm_dec.sample_rate = TCFG_REVERB_SAMPLERATE_DEFUAL;
|
||
|
|
||
|
stream->wait.priority = 0;
|
||
|
stream->wait.preemption = 0;
|
||
|
stream->wait.protect = 1;
|
||
|
stream->wait.handler = pcmdec_wait_res_handler;
|
||
|
return audio_decoder_task_add_wait(&decode_task, &stream->wait);
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
/**@brief 关闭pcm解码
|
||
|
@param
|
||
|
@return
|
||
|
@note
|
||
|
*/
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
static void pcm_dec_close(struct __mic_stream *stream)
|
||
|
{
|
||
|
pcm_dec_stop(stream);
|
||
|
audio_decoder_task_del_wait(&decode_task, &stream->wait);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
/**@brief 唤醒mic数据处理任务
|
||
|
@param
|
||
|
@return
|
||
|
@note
|
||
|
*/
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
void mic_stream_adc_resume(void *priv)
|
||
|
{
|
||
|
struct __mic_stream *stream = (struct __mic_stream *)priv;
|
||
|
if (stream != NULL && (stream->release == 0)) {
|
||
|
os_sem_set(&stream->sem, 0);
|
||
|
os_sem_post(&stream->sem);
|
||
|
}
|
||
|
}
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
/**@brief mic数据处理函数
|
||
|
@param
|
||
|
@return
|
||
|
@note
|
||
|
*/
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
static int mic_stream_effects_run(struct __mic_stream *stream)
|
||
|
{
|
||
|
u32 tmp_len, wlen, data_len;
|
||
|
s16 *read_buf = (s16 *)(stream->temp_buf + stream->parm->point_unit * 2 * 3);
|
||
|
s16 *dual_buf = (s16 *)(stream->temp_buf + stream->parm->point_unit * 2 * 2);
|
||
|
s16 *qual_buf = (s16 *)stream->temp_buf;
|
||
|
|
||
|
u8 dac_chls = audio_dac_get_channel(&dac_hdl);
|
||
|
if (cbuf_get_data_size(&stream->adc_cbuf) < stream->parm->point_unit * 2) {
|
||
|
int res = os_sem_pend(&stream->sem, 0);
|
||
|
if (res) {
|
||
|
return -1;
|
||
|
}
|
||
|
}
|
||
|
if (stream->release) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
wlen = cbuf_read(&stream->adc_cbuf, read_buf, stream->parm->point_unit * 2);
|
||
|
if (wlen) {
|
||
|
if (stream->out.func) {
|
||
|
/* pcm_single_to_dual(dual_buf, read_buf, stream->parm->point_unit * 2); */
|
||
|
/* wlen = stream->out.func(stream->out.priv, dual_buf, dual_buf, stream->parm->point_unit * 2 * 2, stream->parm->point_unit * 2 * 2); */
|
||
|
wlen = stream->out.func(stream->out.priv, read_buf, dual_buf, stream->parm->point_unit * 2, stream->parm->point_unit * 2 * 2);
|
||
|
} else {
|
||
|
if (dac_chls == 1) {
|
||
|
tmp_len = stream->parm->point_unit * 2;
|
||
|
wlen = audio_dac_mix_write(&dac_hdl, read_buf, tmp_len);
|
||
|
}
|
||
|
if (dac_chls == 2) {
|
||
|
pcm_single_to_dual(dual_buf, read_buf, stream->parm->point_unit * 2);
|
||
|
tmp_len = stream->parm->point_unit * 2 * 2;
|
||
|
wlen = audio_dac_mix_write(&dac_hdl, dual_buf, tmp_len);
|
||
|
} else if (dac_chls == 4) {
|
||
|
pcm_single_to_qual(qual_buf, read_buf, stream->parm->point_unit * 2);
|
||
|
tmp_len = stream->parm->point_unit * 2 * 4;
|
||
|
wlen = audio_dac_mix_write(&dac_hdl, qual_buf, tmp_len);
|
||
|
}
|
||
|
if (wlen < tmp_len) {
|
||
|
putchar('D');
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
/* putchar('R'); */
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
/**@brief mic数据处理任务
|
||
|
@param
|
||
|
@return
|
||
|
@note
|
||
|
*/
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
static void mic_stream_task_deal(void *p)
|
||
|
{
|
||
|
int res = 0;
|
||
|
struct __mic_stream *stream = (struct __mic_stream *)p;
|
||
|
stream->busy = 1;
|
||
|
while (1) {
|
||
|
res = mic_stream_effects_run(stream);
|
||
|
if (res) {
|
||
|
///等待删除线程
|
||
|
stream->busy = 0;
|
||
|
while (1) {
|
||
|
os_time_dly(10000);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
/**@brief 创建mic数据流
|
||
|
@param
|
||
|
@return
|
||
|
@note
|
||
|
*/
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
struct __mic_stream *mic_stream_creat(struct __mic_stream_parm *parm)
|
||
|
{
|
||
|
int err = 0;
|
||
|
struct __mic_stream_parm *p = parm;
|
||
|
if (parm == NULL) {
|
||
|
printf("%s parm err\n", __FUNCTION__);
|
||
|
return NULL;
|
||
|
}
|
||
|
printf("p->dac_delay = %d\n", p->dac_delay);
|
||
|
printf("p->point_unit = %d\n", p->point_unit);
|
||
|
printf("p->sample_rate = %d\n", p->sample_rate);
|
||
|
|
||
|
u32 offset = 0;
|
||
|
u32 buf_size = MIC_SIZEOF_ALIN(sizeof(struct __mic_stream), 4)
|
||
|
+ MIC_SIZEOF_ALIN((p->point_unit * 4 * 2), 4)
|
||
|
+ MIC_SIZEOF_ALIN((p->point_unit * 2 * 3), 4);
|
||
|
|
||
|
u8 *buf = zalloc(buf_size);
|
||
|
if (buf == NULL) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
struct __mic_stream *stream = (struct __mic_stream *)buf;
|
||
|
offset += MIC_SIZEOF_ALIN(sizeof(struct __mic_stream), 4);
|
||
|
|
||
|
stream->temp_buf = (u8 *)buf + offset;
|
||
|
offset += MIC_SIZEOF_ALIN((p->point_unit * 4 * 2), 4);
|
||
|
|
||
|
stream->adc_buf = (u8 *)buf + offset;
|
||
|
offset += MIC_SIZEOF_ALIN((p->point_unit * 2 * 3), 4);
|
||
|
|
||
|
stream->parm = p;
|
||
|
|
||
|
os_sem_create(&stream->sem, 0);
|
||
|
cbuf_init(&stream->adc_cbuf, stream->adc_buf, MIC_SIZEOF_ALIN((p->point_unit * 2 * 3), 4));
|
||
|
|
||
|
/* audio_dac_mix_ch_open(&dac_hdl, p->dac_delay);//初始化dac混合通道 */
|
||
|
|
||
|
err = task_create(mic_stream_task_deal, (void *)stream, MIC_STREAM_TASK_NAME);
|
||
|
if (err != OS_NO_ERR) {
|
||
|
printf("%s creat fail %x\n", __FUNCTION__, err);
|
||
|
free(stream);
|
||
|
return NULL;
|
||
|
}
|
||
|
#if 10
|
||
|
err = pcm_dec_open(stream);
|
||
|
if (err) {
|
||
|
mic_stream_destroy(&stream);
|
||
|
return NULL;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
printf("mic stream creat ok\n");
|
||
|
return stream;
|
||
|
}
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
/**@brief 设置mic处理函数的回调处理
|
||
|
@param
|
||
|
@return
|
||
|
@note
|
||
|
*/
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
void mic_stream_set_output(struct __mic_stream *stream, void *priv, u32(*func)(void *priv, void *in, void *out, u32 inlen, u32 outlen))
|
||
|
{
|
||
|
if (stream) {
|
||
|
stream->out.priv = priv;
|
||
|
stream->out.func = func;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
/**@brief mic中断数据输出回调函数
|
||
|
@param
|
||
|
@return
|
||
|
@note
|
||
|
*/
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
static void adc_output_to_buf(void *priv, s16 *data, int len)
|
||
|
{
|
||
|
struct __mic_stream *stream = (struct __mic_stream *)priv;
|
||
|
int wlen = 0;
|
||
|
if (stream != NULL && (stream->release == 0)) {
|
||
|
wlen = cbuf_write(&stream->adc_cbuf, data, len);
|
||
|
os_sem_set(&stream->sem, 0);
|
||
|
os_sem_post(&stream->sem);
|
||
|
}
|
||
|
}
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
/**@brief 打开mic
|
||
|
@param
|
||
|
@return
|
||
|
@note
|
||
|
*/
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
bool mic_stream_start(struct __mic_stream *stream)
|
||
|
{
|
||
|
if (stream) {
|
||
|
if (audio_mic_open(&stream->mic_ch, stream->parm->sample_rate, 2) == 0) {
|
||
|
stream->adc_output.handler = adc_output_to_buf;
|
||
|
stream->adc_output.priv = stream;
|
||
|
audio_mic_add_output(&stream->adc_output);
|
||
|
audio_mic_start(&stream->mic_ch);
|
||
|
log_i("mic_stream_start ok 11\n");
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
/**@brief 关闭mic数据流
|
||
|
@param
|
||
|
@return
|
||
|
@note
|
||
|
*/
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
void mic_stream_destroy(struct __mic_stream **hdl)
|
||
|
{
|
||
|
int err = 0;
|
||
|
if ((hdl == NULL) || (*hdl == NULL)) {
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
struct __mic_stream *stream = *hdl;
|
||
|
stream->release = 1;
|
||
|
audio_mic_close(&stream->mic_ch, &stream->adc_output);
|
||
|
|
||
|
os_sem_set(&stream->sem, 0);
|
||
|
os_sem_post(&stream->sem);
|
||
|
|
||
|
while (stream->busy) {
|
||
|
os_time_dly(5);
|
||
|
}
|
||
|
|
||
|
printf("%s wait busy ok!!!\n", __FUNCTION__);
|
||
|
|
||
|
err = task_kill(MIC_STREAM_TASK_NAME);
|
||
|
os_sem_del(&stream->sem, 0);
|
||
|
|
||
|
pcm_dec_close(stream);
|
||
|
/* audio_dac_mix_ch_close(&dac_hdl); */
|
||
|
|
||
|
local_irq_disable();
|
||
|
free(*hdl);
|
||
|
*hdl = NULL;
|
||
|
/* p_stream = NULL; */
|
||
|
local_irq_enable();
|
||
|
}
|
||
|
|
||
|
#endif//TCFG_MIC_EFFECT_ENABLE
|
||
|
|
||
|
|