first
This commit is contained in:
99
cpu/br28/audio_dec/audio_dec.h
Normal file
99
cpu/br28/audio_dec/audio_dec.h
Normal file
@ -0,0 +1,99 @@
|
||||
|
||||
#ifndef _AUDIO_DEC_H_
|
||||
#define _AUDIO_DEC_H_
|
||||
|
||||
#include "asm/includes.h"
|
||||
#include "media/includes.h"
|
||||
#include "system/includes.h"
|
||||
#include "asm/audio_src.h"
|
||||
// #include "audio_digital_vol.h"
|
||||
/*#include "application/audio_eq_drc_apply.h"*/
|
||||
|
||||
|
||||
#ifndef RB16
|
||||
#define RB16(b) (u16)(((u8 *)b)[0] << 8 | (((u8 *)b))[1])
|
||||
#endif
|
||||
|
||||
extern struct audio_decoder_task decode_task;
|
||||
extern struct audio_mixer mixer;
|
||||
extern struct audio_mixer recorder_mixer;
|
||||
|
||||
u32 audio_output_rate(int input_rate);
|
||||
u32 audio_output_channel_num(void);
|
||||
int audio_output_set_start_volume(u8 state);
|
||||
|
||||
int audio_output_start(u32 sample_rate, u8 reset_rate);
|
||||
void audio_output_stop(void);
|
||||
|
||||
struct audio_src_handle *audio_hw_resample_open(void *priv, int (*output_handler)(void *, void *, int),
|
||||
u8 channel, u16 input_sample_rate, u16 output_sample_rate);
|
||||
void audio_hw_resample_close(struct audio_src_handle *hdl);
|
||||
|
||||
void audio_resume_all_decoder(void);
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void audio_sbc_enc_inbuf_resume(void);
|
||||
|
||||
int audio_dec_init();
|
||||
|
||||
void set_source_sample_rate(u16 sample_rate);
|
||||
u16 get_source_sample_rate();
|
||||
#if USER_DIGITAL_VOLUME_ADJUST_ENABLE != 0
|
||||
void a2dp_user_digital_volume_set(u8 vol);
|
||||
u8 a2dp_user_audio_digital_volume_get();
|
||||
void a2dp_user_digital_volume_tab_set(u16 *user_vol_tab, u8 user_vol_max);
|
||||
|
||||
void linein_user_digital_volume_set(u8 vol);
|
||||
u8 linein_user_audio_digital_volume_get();
|
||||
void linein_user_digital_volume_tab_set(u16 *user_vol_tab, u8 user_vol_max);
|
||||
|
||||
void fm_user_digital_volume_set(u8 vol);
|
||||
u8 fm_user_audio_digital_volume_get();
|
||||
void fm_user_digital_volume_tab_set(u16 *user_vol_tab, u8 user_vol_max);
|
||||
|
||||
void file_user_digital_volume_set(u8 vol);
|
||||
u8 file_user_audio_digital_volume_get();
|
||||
void file_user_digital_volume_tab_set(u16 *user_vol_tab, u8 user_vol_max);
|
||||
|
||||
void pc_user_digital_volume_set(u8 vol);
|
||||
u8 pc_user_audio_digital_volume_get();
|
||||
void pc_user_digital_volume_tab_set(u16 *user_vol_tab, u8 user_vol_max);
|
||||
|
||||
void spdif_user_digital_volume_set(u8 vol);
|
||||
u8 spdif_user_audio_digital_volume_get();
|
||||
void spdif_user_digital_volume_tab_set(u16 *user_vol_tab, u8 user_vol_max);
|
||||
|
||||
|
||||
void reverb_user_digital_volume_set(u8 vol);
|
||||
u8 reverb_user_audio_digital_volume_get();
|
||||
void reverb_user_digital_volume_tab_set(u16 *user_vol_tab, u8 user_vol_max);
|
||||
#endif
|
||||
void reverb_set_dodge_threshold(int threshold_in, int threshold_out, u8 fade_tar, u8 dodge_en);
|
||||
|
||||
|
||||
void a2dp_dec_output_set_start_bt_time(u32 bt_tmr);
|
||||
/*void mix_out_high_bass(u32 cmd, struct high_bass *hb);
|
||||
void mix_out_high_bass_dis(u32 cmd, u8 dis);*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
static inline void audio_pcm_mono_to_dual(s16 *dual_pcm, s16 *mono_pcm, int points)
|
||||
{
|
||||
s16 *mono = mono_pcm;
|
||||
int i = 0;
|
||||
u8 j = 0;
|
||||
|
||||
for (i = 0; i < points; i++, mono++) {
|
||||
*dual_pcm++ = *mono;
|
||||
*dual_pcm++ = *mono;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "audio_dec_file.h"
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
1305
cpu/br28/audio_dec/audio_dec_file.c
Normal file
1305
cpu/br28/audio_dec/audio_dec_file.c
Normal file
File diff suppressed because it is too large
Load Diff
127
cpu/br28/audio_dec/audio_dec_file.h
Normal file
127
cpu/br28/audio_dec/audio_dec_file.h
Normal file
@ -0,0 +1,127 @@
|
||||
|
||||
#ifndef _AUDIO_DEC_FILE_H_
|
||||
#define _AUDIO_DEC_FILE_H_
|
||||
|
||||
#include "asm/includes.h"
|
||||
#include "media/includes.h"
|
||||
#include "media/file_decoder.h"
|
||||
#include "system/includes.h"
|
||||
#include "media/audio_decoder.h"
|
||||
#include "app_config.h"
|
||||
#include "music/music_decrypt.h"
|
||||
#include "music/music_id3.h"
|
||||
|
||||
#include "audio_dec_eff.h"
|
||||
|
||||
|
||||
#define FILE_DEC_REPEAT_EN 0 // 无缝循环播放
|
||||
|
||||
enum {
|
||||
FILE_DEC_STREAM_CLOSE = 0,
|
||||
FILE_DEC_STREAM_OPEN,
|
||||
};
|
||||
|
||||
struct file_dec_hdl {
|
||||
//struct audio_stream *stream; // 音频流
|
||||
struct file_decoder file_dec; // file解码句柄
|
||||
struct audio_res_wait wait; // 资源等待句柄
|
||||
#if TCFG_USER_TWS_ENABLE
|
||||
struct file_decoder trans_dec; // 解码句柄
|
||||
u8 *frame;
|
||||
u16 frame_len;
|
||||
u16 frame_remain_len;
|
||||
u8 trans_dec_end;
|
||||
u8 wait_tws_confirm;
|
||||
u8 tws_channel;
|
||||
u16 seqn;
|
||||
u16 tx_seqn;
|
||||
u32 wait_tws_timeout;
|
||||
void *ts_handle;
|
||||
void *syncts;
|
||||
u32 pcm_num;
|
||||
u32 mix_ch_event_params[3];
|
||||
#endif
|
||||
struct audio_mixer_ch mix_ch; // 叠加句柄
|
||||
|
||||
#if TCFG_EQ_ENABLE&&TCFG_MUSIC_MODE_EQ_ENABLE
|
||||
struct dec_eq_drc *eq_drc;
|
||||
#endif//TCFG_MUSIC_MODE_EQ_ENABLE
|
||||
|
||||
u8 remain;
|
||||
|
||||
struct audio_dec_breakpoint *dec_bp; // 断点
|
||||
u32 id; // 唯一标识符,随机值
|
||||
void *file; // 文件句柄
|
||||
u32 pick_flag : 1; // 挑出数据帧发送(如MP3等)。不是输出pcm,后级不能接任何音效处理等
|
||||
u32 pcm_enc_flag : 1; // pcm压缩成数据帧发送(如WAV等)
|
||||
u32 read_err : 2; // 读数出错 0:no err, 1:fat err, 2:disk err
|
||||
u32 wait_add : 1; // 是否马上得到执行
|
||||
|
||||
#if TCFG_DEC_DECRYPT_ENABLE
|
||||
CIPHER mply_cipher; // 解密播放
|
||||
#endif
|
||||
#if TCFG_DEC_ID3_V1_ENABLE
|
||||
MP3_ID3_OBJ *p_mp3_id3_v1; // id3_v1信息
|
||||
#endif
|
||||
#if TCFG_DEC_ID3_V2_ENABLE
|
||||
MP3_ID3_OBJ *p_mp3_id3_v2; // id3_v2信息
|
||||
#endif
|
||||
|
||||
#if FILE_DEC_REPEAT_EN
|
||||
u8 repeat_num; // 无缝循环次数
|
||||
struct fixphase_repair_obj repair_buf; // 无缝循环句柄
|
||||
#endif
|
||||
|
||||
struct audio_dec_breakpoint *bp; // 断点信息
|
||||
|
||||
void *evt_priv; // 事件回调私有参数
|
||||
void (*evt_cb)(void *, int argc, int *argv); // 事件回调句柄
|
||||
|
||||
void (*stream_handler)(void *priv, int event, struct file_dec_hdl *); // 数据流设置回调
|
||||
void *stream_priv; // 数据流设置回调私有句柄
|
||||
};
|
||||
|
||||
enum {
|
||||
FILE_FROM_LOCAL,
|
||||
FILE_FROM_TWS,
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct file_decoder *file_dec_get_file_decoder_hdl(void);
|
||||
|
||||
#define file_dec_is_stop() file_decoder_is_stop(file_dec_get_file_decoder_hdl())
|
||||
#define file_dec_is_play() file_decoder_is_play(file_dec_get_file_decoder_hdl())
|
||||
#define file_dec_is_pause() file_decoder_is_pause(file_dec_get_file_decoder_hdl())
|
||||
#define file_dec_pp() file_decoder_pp(file_dec_get_file_decoder_hdl())
|
||||
#define file_dec_FF(x) file_decoder_FF(file_dec_get_file_decoder_hdl(),x)
|
||||
#define file_dec_FR(x) file_decoder_FR(file_dec_get_file_decoder_hdl(),x)
|
||||
#define file_dec_get_breakpoint(x) file_decoder_get_breakpoint(file_dec_get_file_decoder_hdl(),x)
|
||||
#define file_dec_get_total_time() file_decoder_get_total_time(file_dec_get_file_decoder_hdl())
|
||||
#define file_dec_get_cur_time() file_decoder_get_cur_time(file_dec_get_file_decoder_hdl())
|
||||
#define file_dec_get_decoder_type() file_decoder_get_decoder_type(file_dec_get_file_decoder_hdl())
|
||||
|
||||
int file_dec_create(void *priv, void (*handler)(void *, int argc, int *argv));
|
||||
int file_dec_open(void *file, struct audio_dec_breakpoint *bp);
|
||||
void file_dec_close();
|
||||
int file_dec_restart(int id);
|
||||
int file_dec_push_restart(void);
|
||||
int file_dec_get_status(void);
|
||||
|
||||
void file_dec_set_stream_set_hdl(struct file_dec_hdl *dec,
|
||||
void (*stream_handler)(void *priv, int event, struct file_dec_hdl *),
|
||||
void *stream_priv);
|
||||
void *get_file_dec_hdl();
|
||||
|
||||
int tws_local_media_dec_open(u8 channel, u8 *arg);
|
||||
|
||||
void tws_local_media_dec_close(u8 channel);
|
||||
|
||||
int tws_local_media_dec_state();
|
||||
|
||||
void send_local_media_dec_open_cmd();
|
||||
|
||||
int file_dec_get_source();
|
||||
|
||||
#endif /*TCFG_APP_MUSIC_EN*/
|
||||
|
||||
391
cpu/br28/audio_dec/audio_dec_iis.c
Normal file
391
cpu/br28/audio_dec/audio_dec_iis.c
Normal file
@ -0,0 +1,391 @@
|
||||
#include "audio_dec_iis.h"
|
||||
#include "app_config.h"
|
||||
#include "audio_decoder.h"
|
||||
#include "media/includes.h"
|
||||
#include "audio_config.h"
|
||||
#include "system/includes.h"
|
||||
#include "audio_enc.h"
|
||||
#include "application/audio_eq.h"
|
||||
#include "application/audio_drc.h"
|
||||
#include "app_config.h"
|
||||
#include "audio_config.h"
|
||||
#include "audio_dec.h"
|
||||
#include "app_main.h"
|
||||
#include "clock_cfg.h"
|
||||
#include "audio_dec_eff.h"
|
||||
#include "audio_codec_clock.h"
|
||||
#include "audio_dvol.h"
|
||||
#include "audio_link.h"
|
||||
#include "circular_buf.h"
|
||||
#include "sound_device.h"
|
||||
|
||||
|
||||
#if (TCFG_AUDIO_INPUT_IIS)
|
||||
|
||||
extern ALINK_PARM alink0_platform_data;
|
||||
extern struct audio_dac_hdl dac_hdl;
|
||||
extern struct audio_decoder_task decode_task;
|
||||
extern struct audio_mixer mixer;
|
||||
/* extern void *hw_alink; //alink初始化句柄 */
|
||||
#define IIS_IN_STORE_PCM_SIZE (4 * 1024)
|
||||
|
||||
//iis 驱动结构体
|
||||
struct iis_in_sample_hdl {
|
||||
OS_SEM sem;
|
||||
s16 *store_pcm_buf;
|
||||
cbuffer_t cbuf;
|
||||
int sample_rate;
|
||||
void *hw_alink;
|
||||
void *alink_ch;
|
||||
};
|
||||
|
||||
// iis 输入解码结构体
|
||||
struct iis_in_dec_hdl {
|
||||
struct audio_decoder decoder;
|
||||
struct audio_res_wait wait;
|
||||
struct audio_mixer_ch mix_ch;
|
||||
u8 channel;
|
||||
u8 start;
|
||||
u8 need_resume;
|
||||
u8 remain;
|
||||
u8 output_ch;
|
||||
int sample_rate;
|
||||
void *iis_in; //驱动句柄
|
||||
};
|
||||
static struct iis_in_dec_hdl *iis_in_dec = NULL;
|
||||
|
||||
// ********************** iis in 驱动 ************************* //
|
||||
static void iis_in_dec_resume(void)
|
||||
{
|
||||
if (iis_in_dec) {
|
||||
audio_decoder_resume(&iis_in_dec->decoder);
|
||||
}
|
||||
}
|
||||
|
||||
static void pcm_LR_to_mono(s16 *pcm_lr, s16 *pcm_mono, int points_len)
|
||||
{
|
||||
s16 pcm_L;
|
||||
s16 pcm_R;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < points_len; i++, pcm_lr += 2) {
|
||||
pcm_L = *pcm_lr;
|
||||
pcm_R = *(pcm_lr + 1);
|
||||
*pcm_mono++ = (s16)(((int)pcm_L + pcm_R) >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void iis_in_data_handler(void *priv, void *_data, int len)
|
||||
{
|
||||
struct iis_in_sample_hdl *iis_in = (struct iis_in_sample_hdl *)priv;
|
||||
s16 *data = (s16 *)_data;
|
||||
u16 temp_len = len;
|
||||
int wlen = 0;
|
||||
|
||||
if (iis_in_dec->start == 0) {
|
||||
goto __exit;
|
||||
}
|
||||
//iis 默认输入的是双声道数据
|
||||
if (iis_in_dec->output_ch == 1) {
|
||||
s16 *mono_data = data;
|
||||
for (int i = 0; i < len / 4; i++) {
|
||||
mono_data[i] = mono_data[i * 2];
|
||||
}
|
||||
len = len / 2;
|
||||
wlen = cbuf_write(&iis_in->cbuf, mono_data, len);
|
||||
if (wlen != len) {
|
||||
putchar('w');
|
||||
}
|
||||
} else if (iis_in_dec->output_ch == 2) {
|
||||
wlen = cbuf_write(&iis_in->cbuf, data, len);
|
||||
/* os_sem_post(&iis_in->sem); */
|
||||
if (wlen != len) {
|
||||
putchar('W');
|
||||
}
|
||||
} else {
|
||||
putchar('e');
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
if (iis_in_dec && iis_in_dec->need_resume) {
|
||||
iis_in_dec->need_resume = 0;
|
||||
iis_in_dec_resume();
|
||||
}
|
||||
__exit:
|
||||
alink_set_shn(&alink0_platform_data.ch_cfg[1], temp_len / 4);
|
||||
}
|
||||
|
||||
static void *iis_in_open(int sr)
|
||||
{
|
||||
struct iis_in_sample_hdl *iis_in = NULL;
|
||||
iis_in = zalloc(sizeof(struct iis_in_sample_hdl));
|
||||
if (!iis_in) {
|
||||
return NULL;
|
||||
}
|
||||
iis_in->store_pcm_buf = malloc(IIS_IN_STORE_PCM_SIZE);
|
||||
if (!iis_in->store_pcm_buf) {
|
||||
free(iis_in);
|
||||
return NULL;
|
||||
}
|
||||
cbuf_init(&iis_in->cbuf, iis_in->store_pcm_buf, IIS_IN_STORE_PCM_SIZE);
|
||||
iis_in->hw_alink = (ALINK_PARM *)get_iis_alink_param();
|
||||
if (iis_in->hw_alink == NULL) {
|
||||
iis_in->hw_alink = alink_init(&alink0_platform_data);
|
||||
}
|
||||
iis_in->alink_ch = alink_channel_init(iis_in->hw_alink, 1, ALINK_DIR_RX, (void *)iis_in, iis_in_data_handler);
|
||||
alink_start(iis_in->hw_alink);
|
||||
iis_in->sample_rate = sr;
|
||||
return iis_in;
|
||||
}
|
||||
|
||||
|
||||
// *********************** iis in dec 解码 ***************************//
|
||||
static int iis_in_stream_read(struct audio_decoder *decoder, void *buf, u32 len)
|
||||
{
|
||||
int rlen = 0;
|
||||
struct iis_in_sample_hdl *iis_in = (struct iis_in_sample_hdl *)iis_in_dec->iis_in;
|
||||
if (!iis_in || iis_in_dec->start == 0) {
|
||||
goto __exit;
|
||||
}
|
||||
if (!iis_in->store_pcm_buf) {
|
||||
goto __exit;
|
||||
}
|
||||
int read_len = cbuf_get_data_size(&iis_in->cbuf);
|
||||
if (read_len) {
|
||||
read_len = read_len > len ? len : read_len;
|
||||
rlen = cbuf_read(&iis_in->cbuf, buf, read_len);
|
||||
/* printf("--- rlen : %d\n", rlen); */
|
||||
}
|
||||
__exit:
|
||||
if (!rlen) {
|
||||
iis_in_dec->need_resume = 1;
|
||||
return -1;
|
||||
}
|
||||
/* y_printf("--- rlen = %d\n",rlen); */
|
||||
return rlen;
|
||||
}
|
||||
|
||||
static int iis_in_dec_probe_handler(struct audio_decoder *decoder)
|
||||
{
|
||||
/* struct pcm_dec_hdl *dec = container_of(decoder, struct pcm_dec_hdl, decoder); */
|
||||
struct iis_in_dec_hdl *dec = container_of(decoder, struct iis_in_dec_hdl, decoder);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iis_in_dec_output_handler(struct audio_decoder *decoder, s16 *data, int len, void *priv)
|
||||
{
|
||||
struct iis_in_dec_hdl *dec = container_of(decoder, struct iis_in_dec_hdl, decoder);
|
||||
|
||||
if (!dec) {
|
||||
return 0;
|
||||
}
|
||||
int rlen = len;
|
||||
int wlen = 0;
|
||||
|
||||
if (!dec->remain) {
|
||||
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
|
||||
audio_digital_vol_run(MUSIC_DVOL, data, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
wlen = audio_mixer_ch_write(&dec->mix_ch, data, rlen);
|
||||
if (!wlen) {
|
||||
putchar('w');
|
||||
}
|
||||
rlen -= wlen;
|
||||
|
||||
if (rlen == 0) {
|
||||
dec->remain = 0;
|
||||
} else {
|
||||
dec->remain = 1;
|
||||
}
|
||||
return len - rlen;
|
||||
}
|
||||
|
||||
static const struct audio_dec_handler iis_in_dec_handler = {
|
||||
.dec_probe = iis_in_dec_probe_handler,
|
||||
.dec_output = iis_in_dec_output_handler,
|
||||
};
|
||||
|
||||
static const struct audio_dec_input iis_input = {
|
||||
.coding_type = AUDIO_CODING_PCM,
|
||||
.data_type = AUDIO_INPUT_FILE,
|
||||
.ops = {
|
||||
.file = {
|
||||
.fread = iis_in_stream_read,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void iis_in_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv)
|
||||
{
|
||||
switch (argv[0]) {
|
||||
case AUDIO_DEC_EVENT_END:
|
||||
/*pcm_audio_close();*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//开始 iis dec 解码
|
||||
static int iis_in_dec_start(void)
|
||||
{
|
||||
int err;
|
||||
y_printf(">>>>>>>> Enter Func: %s \n", __func__);
|
||||
struct audio_fmt f = {0};
|
||||
struct iis_in_dec_hdl *dec = iis_in_dec;
|
||||
|
||||
if (!iis_in_dec && iis_in_dec->start == 1) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = audio_decoder_open(&dec->decoder, &iis_input, &decode_task);
|
||||
if (err) {
|
||||
goto __err;
|
||||
}
|
||||
if (dec->iis_in == NULL) {
|
||||
y_printf("--> %s, %d, Init iis_in!\n", __func__, __LINE__);
|
||||
dec->iis_in = iis_in_open(dec->sample_rate);
|
||||
if (!dec->iis_in) {
|
||||
goto __err;
|
||||
}
|
||||
}
|
||||
|
||||
audio_decoder_set_handler(&dec->decoder, &iis_in_dec_handler);
|
||||
audio_decoder_set_event_handler(&dec->decoder, iis_in_dec_event_handler, 0);
|
||||
u8 dac_conn = audio_dac_get_channel(&dac_hdl);
|
||||
if (dac_conn == DAC_OUTPUT_LR) {
|
||||
dec->output_ch = 2;
|
||||
} else {
|
||||
dec->output_ch = 1;
|
||||
}
|
||||
|
||||
f.coding_type = AUDIO_CODING_PCM;
|
||||
f.sample_rate = dec->sample_rate;
|
||||
f.channel = dec->output_ch;
|
||||
|
||||
sound_pcm_dev_channel_mapping(dec->output_ch);
|
||||
|
||||
err = audio_decoder_set_fmt(&dec->decoder, &f);
|
||||
if (err) {
|
||||
goto __err;
|
||||
}
|
||||
|
||||
|
||||
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
|
||||
audio_digital_vol_open(MUSIC_DVOL, app_audio_get_volume(APP_AUDIO_STATE_MUSIC), MUSIC_DVOL_MAX, MUSIC_DVOL_FS, -1);
|
||||
#endif
|
||||
|
||||
// 设置叠加功能
|
||||
audio_mixer_ch_open(&dec->mix_ch, &mixer);
|
||||
audio_mixer_ch_set_sample_rate(&dec->mix_ch, audio_output_rate(f.sample_rate));
|
||||
app_audio_state_switch(APP_AUDIO_STATE_MUSIC, get_max_sys_vol());
|
||||
|
||||
int vol = app_audio_get_volume(APP_AUDIO_STATE_MUSIC);
|
||||
app_audio_set_volume(APP_AUDIO_STATE_MUSIC, vol, 1);
|
||||
|
||||
err = audio_decoder_start(&dec->decoder);
|
||||
if (err) {
|
||||
goto __err;
|
||||
}
|
||||
/* audio_codec_clock_set(AUDIO_PC_MODE, AUDIO_CODING_PCM, dec->wait.preemption); */
|
||||
dec->start = 1;
|
||||
return 0;
|
||||
|
||||
__err:
|
||||
return err;
|
||||
}
|
||||
|
||||
// iis in 解码资源等待
|
||||
void iis_in_dec_stop(void);
|
||||
|
||||
static int iis_in_wait_res_handler(struct audio_res_wait *wait, int event)
|
||||
{
|
||||
int err = 0;
|
||||
if (event == AUDIO_RES_GET) {
|
||||
// 启动解码
|
||||
err = iis_in_dec_start();
|
||||
} else if (event == AUDIO_RES_PUT) {
|
||||
// 被打断
|
||||
iis_in_dec_stop();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int iis_in_dec_open(void)
|
||||
{
|
||||
int err;
|
||||
struct iis_in_dec_hdl *dec = NULL;;
|
||||
dec = zalloc(sizeof(*dec));
|
||||
if (!dec) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
iis_in_dec = dec;
|
||||
dec->sample_rate = TCFG_IIS_SR;
|
||||
dec->channel = 2; //iis 是双声道数据
|
||||
dec->wait.priority = 2;
|
||||
dec->wait.preemption = 1;
|
||||
dec->wait.handler = iis_in_wait_res_handler;
|
||||
|
||||
err = audio_decoder_task_add_wait(&decode_task, &dec->wait);
|
||||
clock_add(DEC_PCM_CLK);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
void iis_in_dec_stop(void)
|
||||
{
|
||||
if (iis_in_dec && iis_in_dec->start == 1) {
|
||||
struct iis_in_sample_hdl *iis_in = (struct iis_in_sample_hdl *)iis_in_dec->iis_in;
|
||||
iis_in_dec->start = 0;
|
||||
audio_decoder_close(&iis_in_dec->decoder);
|
||||
audio_mixer_ch_close(&iis_in_dec->mix_ch);
|
||||
app_audio_state_exit(APP_AUDIO_STATE_MUSIC);
|
||||
|
||||
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
|
||||
audio_digital_vol_close(MUSIC_DVOL);
|
||||
#endif/*SYS_VOL_TYPE == VOL_TYPE_DIGITAL*/
|
||||
|
||||
local_irq_disable();
|
||||
#if 1
|
||||
if (iis_in) {
|
||||
void *alink_p = (ALINK_PARM *)get_iis_alink_param();
|
||||
if (iis_in->hw_alink && !alink_p) {
|
||||
alink_uninit(iis_in->hw_alink);
|
||||
iis_in->hw_alink = NULL;
|
||||
} else {
|
||||
/* alink_uninit(iis_in->hw_alink); */
|
||||
alink_channel_close(iis_in->alink_ch);
|
||||
}
|
||||
if (iis_in->store_pcm_buf) {
|
||||
free(iis_in->store_pcm_buf);
|
||||
iis_in->store_pcm_buf = NULL;
|
||||
}
|
||||
free(iis_in);
|
||||
iis_in = NULL;
|
||||
iis_in_dec->iis_in = NULL;
|
||||
}
|
||||
#endif
|
||||
local_irq_enable();
|
||||
}
|
||||
}
|
||||
|
||||
void iis_in_dec_close(void)
|
||||
{
|
||||
if (!iis_in_dec) {
|
||||
return;
|
||||
}
|
||||
iis_in_dec_stop();
|
||||
audio_decoder_task_del_wait(&decode_task, &iis_in_dec->wait);
|
||||
clock_remove(DEC_PCM_CLK);
|
||||
local_irq_disable();
|
||||
free(iis_in_dec);
|
||||
iis_in_dec = NULL;
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
9
cpu/br28/audio_dec/audio_dec_iis.h
Normal file
9
cpu/br28/audio_dec/audio_dec_iis.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef __AUDIO_DEC_IIS_H
|
||||
#define __AUDIO_DEC_IIS_H
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
921
cpu/br28/audio_dec/audio_dec_pc.c
Normal file
921
cpu/br28/audio_dec/audio_dec_pc.c
Normal file
@ -0,0 +1,921 @@
|
||||
#include "uac_stream.h"
|
||||
#include "app_config.h"
|
||||
#include "audio_decoder.h"
|
||||
#include "media/includes.h"
|
||||
#include "audio_config.h"
|
||||
#include "system/includes.h"
|
||||
#include "audio_enc.h"
|
||||
#include "application/audio_eq.h"
|
||||
#include "application/audio_drc.h"
|
||||
#include "app_config.h"
|
||||
#include "audio_config.h"
|
||||
#include "audio_dec.h"
|
||||
#include "app_main.h"
|
||||
#include "clock_cfg.h"
|
||||
#include "audio_dec_eff.h"
|
||||
#include "audio_codec_clock.h"
|
||||
#include "audio_dvol.h"
|
||||
#include "sound_device.h"
|
||||
|
||||
#if TCFG_UI_ENABLE
|
||||
#include "ui/ui_api.h"
|
||||
#endif
|
||||
|
||||
|
||||
#if TCFG_PC_ENABLE//TCFG_APP_PC_EN
|
||||
#if (defined(TCFG_PCM2TWS_SBC_ENABLE) && (TCFG_PCM2TWS_SBC_ENABLE))
|
||||
#define UAC_DEC_PCM_ENC_TYPE AUDIO_CODING_SBC
|
||||
#define UAC_DEC_PCM_ENC_CHANNEL AUDIO_CH_LR
|
||||
#else
|
||||
#define UAC_DEC_PCM_ENC_TYPE AUDIO_CODING_MP3
|
||||
#define UAC_DEC_PCM_ENC_CHANNEL AUDIO_CH_LR
|
||||
#endif
|
||||
|
||||
struct usb_audio_handle {
|
||||
int top_size;
|
||||
int bottom_size;
|
||||
int begin_size;
|
||||
};
|
||||
|
||||
#define RATE_INC_STEP 2
|
||||
#define RATE_DEC_STEP 2
|
||||
|
||||
|
||||
struct uac_dec_hdl {
|
||||
struct audio_decoder decoder;
|
||||
struct audio_res_wait wait;
|
||||
struct audio_mixer_ch mix_ch;
|
||||
int begin_size;
|
||||
int top_size;
|
||||
int bottom_size;
|
||||
u8 start;
|
||||
u8 channel;
|
||||
u8 output_ch;
|
||||
u8 sync_start;
|
||||
u32 src_out_sr;
|
||||
u32 dec_no_out_sound : 1; // 解码不直接输出声音(用于TWS转发)
|
||||
u32 sample_rate;
|
||||
u32 audio_new_rate;
|
||||
u32 usb_audio_max_speed;
|
||||
u32 usb_audio_min_speed;
|
||||
struct audio_src_handle *src_sync;
|
||||
u8 remain;
|
||||
#if TCFG_EQ_ENABLE&&TCFG_PC_MODE_EQ_ENABLE
|
||||
struct dec_eq_drc *eq_drc;
|
||||
#endif
|
||||
|
||||
|
||||
struct user_audio_parm *user_hdl;
|
||||
|
||||
|
||||
u32 cnt: 8;
|
||||
|
||||
u32 state: 1;
|
||||
|
||||
int check_data_timer;
|
||||
|
||||
|
||||
};
|
||||
|
||||
extern struct audio_dac_hdl dac_hdl;
|
||||
extern struct audio_decoder_task decode_task;
|
||||
extern struct audio_mixer mixer;
|
||||
|
||||
static u16 sys_event_id = 0;
|
||||
static struct uac_dec_hdl *uac_dec = NULL;
|
||||
|
||||
static u8 uac_dec_maigc = 0;
|
||||
|
||||
|
||||
extern void uac_get_cur_vol(const u8 id, u16 *l_vol, u16 *r_vol);
|
||||
extern u8 uac_get_mute(void);
|
||||
extern void bt_tws_sync_volume();
|
||||
|
||||
void pc_eq_drc_open(struct uac_dec_hdl *dec, struct audio_fmt *fmt);
|
||||
void pc_eq_drc_close(struct uac_dec_hdl *dec);
|
||||
|
||||
int uac_vol_switch(int vol)
|
||||
{
|
||||
u16 valsum = vol * (SYS_MAX_VOL + 1) / 100;
|
||||
|
||||
if (valsum > SYS_MAX_VOL) {
|
||||
valsum = SYS_MAX_VOL;
|
||||
}
|
||||
return valsum;
|
||||
}
|
||||
|
||||
static void uac_dec_set_output_channel(struct uac_dec_hdl *dec)
|
||||
{
|
||||
u8 dac_conn = audio_dac_get_channel(&dac_hdl);
|
||||
|
||||
if (dac_conn == DAC_OUTPUT_LR) {
|
||||
dec->output_ch = 2;
|
||||
} else {
|
||||
|
||||
dec->output_ch = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int uac_sync_output_handler(void *priv, void *buf, int len)
|
||||
{
|
||||
struct uac_dec_hdl *dec = (struct uac_dec_hdl *)priv;
|
||||
int remain_len = len;
|
||||
int wlen = 0;
|
||||
s16 *data = (s16 *)buf;
|
||||
|
||||
#if (defined(TCFG_PCM_ENC2TWS_ENABLE) && (TCFG_PCM_ENC2TWS_ENABLE))
|
||||
if (dec->dec_no_out_sound) {
|
||||
return pcm2tws_enc_output(NULL, data, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
wlen = audio_mixer_ch_write(&dec->mix_ch, data, len);
|
||||
return wlen;
|
||||
}
|
||||
|
||||
|
||||
static void pcm_LR_to_mono(s16 *pcm_lr, s16 *pcm_mono, int points_len)
|
||||
{
|
||||
s16 pcm_L;
|
||||
s16 pcm_R;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < points_len; i++, pcm_lr += 2) {
|
||||
pcm_L = *pcm_lr;
|
||||
pcm_R = *(pcm_lr + 1);
|
||||
*pcm_mono++ = (s16)(((int)pcm_L + pcm_R) >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int uac_dec_output_handler(struct audio_decoder *decoder, s16 *data, int len, void *priv)
|
||||
{
|
||||
struct uac_dec_hdl *dec = container_of(decoder, struct uac_dec_hdl, decoder);
|
||||
int rlen = len;
|
||||
int wlen = 0;
|
||||
|
||||
|
||||
/* if (dec->channel == 2 && dec->output_ch == 1) { //这里 */
|
||||
|
||||
/* pcm_LR_to_mono((s16 *)data, (s16 *)data, len >> 2); //这里有双声道转单声道 */
|
||||
/* len >>= 1; */
|
||||
/* } */
|
||||
|
||||
|
||||
if (!dec->remain) {
|
||||
#if (defined(USER_AUDIO_PROCESS_ENABLE) && (USER_AUDIO_PROCESS_ENABLE != 0))
|
||||
if (dec->user_hdl) {
|
||||
u8 ch_num = dec->output_ch;
|
||||
user_audio_process_handler_run(dec->user_hdl, data, len, ch_num);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
|
||||
audio_digital_vol_run(MUSIC_DVOL, data, len);
|
||||
#endif/*SYS_VOL_TYPE == VOL_TYPE_DIGITAL*/
|
||||
}
|
||||
#if TCFG_EQ_ENABLE&&TCFG_PC_MODE_EQ_ENABLE
|
||||
if (dec->eq_drc && dec->eq_drc->async) {
|
||||
int eqlen = eq_drc_run(dec->eq_drc, data, len);
|
||||
len -= eqlen;
|
||||
if (len == 0) {
|
||||
dec->remain = 0;
|
||||
} else {
|
||||
dec->remain = 1;
|
||||
}
|
||||
return eqlen;
|
||||
}
|
||||
|
||||
if (!dec->remain) {
|
||||
eq_drc_run(dec->eq_drc, data, len);
|
||||
}
|
||||
#endif//TCFG_PC_MODE_EQ_ENABLE
|
||||
|
||||
if (dec->src_sync) {
|
||||
wlen = audio_src_resample_write(dec->src_sync, data, rlen);
|
||||
/*printf("%d - %d\n", len, wlen);*/
|
||||
/* return wlen; */
|
||||
#if (defined(TCFG_PCM_ENC2TWS_ENABLE) && (TCFG_PCM_ENC2TWS_ENABLE))
|
||||
} else if (dec->dec_no_out_sound) {
|
||||
wlen = pcm2tws_enc_output(NULL, data, rlen);
|
||||
#endif
|
||||
} else {
|
||||
wlen = audio_mixer_ch_write(&dec->mix_ch, data, rlen);
|
||||
}
|
||||
|
||||
rlen -= wlen;
|
||||
|
||||
if (rlen == 0) {
|
||||
dec->remain = 0;
|
||||
} else {
|
||||
dec->remain = 1;
|
||||
}
|
||||
|
||||
|
||||
return len - rlen;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 检测uac是否收到数据,没数据时暂停mix_ch
|
||||
@param *priv: 私有参数
|
||||
@return
|
||||
@note
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static void audio_pc_check_timer(void *priv)
|
||||
{
|
||||
#if 1
|
||||
u8 alive = uac_speaker_get_alive();
|
||||
if (alive) {
|
||||
uac_dec->cnt++;
|
||||
if (uac_dec->cnt > 5) {
|
||||
if (!uac_dec->state) {
|
||||
#if TCFG_DEC2TWS_ENABLE
|
||||
if (uac_dec->pcm_dec.dec_no_out_sound) {
|
||||
localtws_decoder_pause(1);
|
||||
}
|
||||
#endif
|
||||
audio_mixer_ch_pause(&uac_dec->mix_ch, 1);
|
||||
audio_decoder_resume_all(&decode_task);
|
||||
uac_dec->state = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (uac_dec->cnt) {
|
||||
uac_dec->cnt--;
|
||||
}
|
||||
if (uac_dec->state) {
|
||||
uac_dec->state = 0;
|
||||
uac_dec->cnt = 0;
|
||||
#if TCFG_DEC2TWS_ENABLE
|
||||
if (uac_dec->pcm_dec.dec_no_out_sound) {
|
||||
localtws_decoder_pause(0);
|
||||
}
|
||||
#endif
|
||||
audio_mixer_ch_pause(&uac_dec->mix_ch, 0);
|
||||
audio_decoder_resume_all(&decode_task);
|
||||
}
|
||||
}
|
||||
uac_speaker_set_alive(1);
|
||||
#else
|
||||
static u8 cnt = 0;
|
||||
if (uac_speaker_stream_size(NULL) == 0) {
|
||||
if (cnt < 20) {
|
||||
cnt++;
|
||||
}
|
||||
if (cnt == 15) {
|
||||
#if TCFG_DEC2TWS_ENABLE
|
||||
if (uac_dec->pcm_dec.dec_no_out_sound) {
|
||||
localtws_decoder_pause(1);
|
||||
}
|
||||
#endif
|
||||
audio_mixer_ch_pause(&uac_dec->mix_ch, 1);
|
||||
audio_decoder_resume_all(&decode_task);
|
||||
}
|
||||
} else {
|
||||
if (cnt > 14) {
|
||||
#if TCFG_DEC2TWS_ENABLE
|
||||
if (uac_dec->pcm_dec.dec_no_out_sound) {
|
||||
localtws_decoder_pause(0);
|
||||
}
|
||||
#endif
|
||||
audio_mixer_ch_pause(&uac_dec->mix_ch, 0);
|
||||
audio_decoder_resume_all(&decode_task);
|
||||
}
|
||||
cnt = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int uac_stream_read(struct audio_decoder *decoder, void *buf, u32 len)
|
||||
{
|
||||
int rlen = 0;
|
||||
struct uac_dec_hdl *dec = container_of(decoder, struct uac_dec_hdl, decoder);
|
||||
|
||||
if (!dec->sync_start) {
|
||||
if (uac_speaker_stream_size() < dec->begin_size) {
|
||||
return -1;
|
||||
}
|
||||
dec->sync_start = 1;
|
||||
}
|
||||
|
||||
|
||||
rlen = uac_speaker_read(NULL, (void *)buf, len);
|
||||
|
||||
if (dec->channel == 2 && dec->output_ch == 1) {
|
||||
pcm_LR_to_mono((s16 *)buf, (s16 *)buf, rlen >> 2);
|
||||
rlen >>= 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!rlen) {
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
return rlen;
|
||||
}
|
||||
|
||||
static const struct audio_dec_input uac_input = {
|
||||
.coding_type = AUDIO_CODING_PCM,
|
||||
.data_type = AUDIO_INPUT_FILE,
|
||||
.ops = {
|
||||
.file = {
|
||||
.fread = uac_stream_read,
|
||||
/*.fseek = uac_stream_seek,*/
|
||||
/*.flen = uac_stream_len,*/
|
||||
}
|
||||
}
|
||||
};
|
||||
int uac_speaker_stream_sample_rate(void);
|
||||
static int usb_audio_stream_sync(struct uac_dec_hdl *dec, int data_size)
|
||||
{
|
||||
if (!dec->src_sync) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 1
|
||||
//优化下行播放同步得调节步进
|
||||
|
||||
u32 in_sr = uac_speaker_stream_sample_rate();
|
||||
|
||||
u32 out_sr = (long long)dec->audio_new_rate * (long long)in_sr / dec->sample_rate; //统计得输入采样率,转换成输出采样率
|
||||
|
||||
|
||||
if (data_size < dec->bottom_size) {
|
||||
out_sr += out_sr * 5 / 10000;
|
||||
/* putchar('+'); */
|
||||
}
|
||||
|
||||
if (data_size > dec->top_size) {
|
||||
out_sr -= out_sr * 5 / 10000;
|
||||
/* putchar('-'); */
|
||||
}
|
||||
|
||||
if (out_sr != dec->audio_new_rate) {
|
||||
audio_hw_src_set_rate(dec->src_sync, dec->sample_rate, out_sr);
|
||||
}
|
||||
#else
|
||||
|
||||
|
||||
u32 sr = dec->audio_new_rate;
|
||||
|
||||
if (data_size < dec->bottom_size) {
|
||||
dec->audio_new_rate += RATE_INC_STEP;
|
||||
/*printf("rate inc\n");*/
|
||||
}
|
||||
|
||||
if (data_size > dec->top_size) {
|
||||
dec->audio_new_rate -= RATE_DEC_STEP;
|
||||
/*printf("rate dec : %d\n", __this->audio_new_rate);*/
|
||||
}
|
||||
|
||||
if (dec->audio_new_rate < dec->usb_audio_min_speed) {
|
||||
dec->audio_new_rate = dec->usb_audio_min_speed;
|
||||
} else if (dec->audio_new_rate > dec->usb_audio_max_speed) {
|
||||
dec->audio_new_rate = dec->usb_audio_max_speed;
|
||||
}
|
||||
|
||||
if (sr != dec->audio_new_rate) {
|
||||
audio_hw_src_set_rate(dec->src_sync, dec->sample_rate, dec->audio_new_rate);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uac_dec_probe_handler(struct audio_decoder *decoder)
|
||||
{
|
||||
struct uac_dec_hdl *dec = container_of(decoder, struct uac_dec_hdl, decoder);
|
||||
int err = 0;
|
||||
|
||||
#if 0
|
||||
if (!dec->sync_start) {
|
||||
if (uac_speaker_stream_size() > dec->begin_size) {
|
||||
dec->sync_start = 1;
|
||||
return 0;
|
||||
} else {
|
||||
os_time_dly(2);
|
||||
audio_decoder_suspend(&dec->decoder, 0);
|
||||
/* audio_decoder_resume(&dec->decoder); */
|
||||
/* return 0;//临时 */
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (!dec->sync_start) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(TCFG_PCM_ENC2TWS_ENABLE) && (TCFG_PCM_ENC2TWS_ENABLE))
|
||||
if (dec->dec_no_out_sound) {
|
||||
// localtws同步有微调处理
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
usb_audio_stream_sync(dec, uac_speaker_stream_size());
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct audio_dec_handler uac_dec_handler = {
|
||||
.dec_probe = uac_dec_probe_handler,
|
||||
.dec_output = uac_dec_output_handler,
|
||||
};
|
||||
|
||||
static int uac_audio_sync_init(struct uac_dec_hdl *dec)
|
||||
{
|
||||
dec->sync_start = 0;
|
||||
dec->begin_size = uac_speaker_stream_length() * 60 / 100;
|
||||
dec->top_size = uac_speaker_stream_length() * 70 / 100;
|
||||
dec->bottom_size = uac_speaker_stream_length() * 40 / 100;
|
||||
|
||||
dec->audio_new_rate = dec->src_out_sr;//audio_output_rate(dec->sample_rate);
|
||||
printf("out_sr:%d, dsr:%d, \n", dec->audio_new_rate, dec->sample_rate);
|
||||
dec->usb_audio_max_speed = dec->audio_new_rate + 50;
|
||||
dec->usb_audio_min_speed = dec->audio_new_rate - 50;
|
||||
|
||||
#if (defined(TCFG_PCM_ENC2TWS_ENABLE) && (TCFG_PCM_ENC2TWS_ENABLE))
|
||||
if (dec->dec_no_out_sound) {
|
||||
if (dec->audio_new_rate == dec->sample_rate) {
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
dec->src_sync = zalloc(sizeof(struct audio_src_handle));
|
||||
if (!dec->src_sync) {
|
||||
return -ENODEV;
|
||||
}
|
||||
audio_hw_src_open(dec->src_sync, dec->output_ch, SRC_TYPE_RESAMPLE);
|
||||
|
||||
audio_hw_src_set_rate(dec->src_sync, dec->sample_rate, dec->audio_new_rate);
|
||||
|
||||
audio_src_set_output_handler(dec->src_sync, dec, uac_sync_output_handler);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uac_audio_sync_release(struct uac_dec_hdl *dec)
|
||||
{
|
||||
if (dec->src_sync) {
|
||||
audio_hw_src_stop(dec->src_sync);
|
||||
audio_hw_src_close(dec->src_sync);
|
||||
local_irq_disable();
|
||||
free(dec->src_sync);
|
||||
dec->src_sync = NULL;
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uac_audio_close(void)
|
||||
{
|
||||
if (!uac_dec || !uac_dec->start) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uac_dec->start = 0;
|
||||
uac_dec->sync_start = 0;
|
||||
|
||||
if (uac_dec->check_data_timer) {
|
||||
sys_hi_timer_del(uac_dec->check_data_timer);
|
||||
}
|
||||
|
||||
audio_decoder_close(&uac_dec->decoder);
|
||||
uac_audio_sync_release(uac_dec);
|
||||
if (!uac_dec->dec_no_out_sound) {
|
||||
audio_mixer_ch_close(&uac_dec->mix_ch);
|
||||
app_audio_state_exit(APP_AUDIO_STATE_MUSIC);
|
||||
}
|
||||
|
||||
#if (defined(TCFG_PCM_ENC2TWS_ENABLE) && (TCFG_PCM_ENC2TWS_ENABLE))
|
||||
if (uac_dec->dec_no_out_sound) {
|
||||
uac_dec->dec_no_out_sound = 0;
|
||||
pcm2tws_enc_close();
|
||||
encfile_tws_dec_close();
|
||||
local_tws_stop();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
pc_eq_drc_close(uac_dec);
|
||||
#if (defined(USER_AUDIO_PROCESS_ENABLE) && (USER_AUDIO_PROCESS_ENABLE != 0))
|
||||
if (uac_dec->user_hdl) {
|
||||
user_audio_process_close(uac_dec->user_hdl);
|
||||
uac_dec->user_hdl = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
|
||||
audio_digital_vol_close(MUSIC_DVOL);
|
||||
#endif/*SYS_VOL_TYPE == VOL_TYPE_DIGITAL*/
|
||||
|
||||
|
||||
/* 此处不进行clock_del,改为在usb_audio_demo_exit后 */
|
||||
/* 由于usb_audio_mic_close前adc中断还会不断唤醒usb_audio_mic_write_task */
|
||||
/* 降低时钟会导致系统跑不过来 */
|
||||
/* audio_codec_clock_del(AUDIO_PC_MODE); */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uac_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv)
|
||||
{
|
||||
switch (argv[0]) {
|
||||
case AUDIO_DEC_EVENT_END:
|
||||
puts("USB AUDIO_DEC_EVENT_END\n");
|
||||
if ((u8)argv[1] != (u8)(uac_dec_maigc - 1)) {
|
||||
log_i("maigc err, %s\n", __FUNCTION__);
|
||||
break;
|
||||
}
|
||||
/*uac_audio_close();*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int uac_audio_start(void)
|
||||
{
|
||||
int err;
|
||||
struct audio_fmt f = {0};
|
||||
struct uac_dec_hdl *dec = uac_dec;
|
||||
|
||||
if (!uac_dec) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = audio_decoder_open(&dec->decoder, &uac_input, &decode_task);
|
||||
if (err) {
|
||||
goto __err;
|
||||
}
|
||||
|
||||
audio_decoder_set_handler(&dec->decoder, &uac_dec_handler);
|
||||
audio_decoder_set_event_handler(&dec->decoder, uac_dec_event_handler, uac_dec_maigc++);
|
||||
|
||||
|
||||
uac_dec_set_output_channel(dec);
|
||||
|
||||
f.coding_type = AUDIO_CODING_PCM;
|
||||
f.sample_rate = dec->sample_rate;
|
||||
f.channel = dec->output_ch;
|
||||
|
||||
sound_pcm_dev_channel_mapping(dec->output_ch);
|
||||
|
||||
err = audio_decoder_set_fmt(&dec->decoder, &f);
|
||||
|
||||
if (err) {
|
||||
goto __err;
|
||||
}
|
||||
|
||||
#if (defined(TCFG_PCM_ENC2TWS_ENABLE) && (TCFG_PCM_ENC2TWS_ENABLE))
|
||||
dec->dec_no_out_sound = 0;
|
||||
if (dec2tws_check_enable() == true) {
|
||||
audio_decoder_set_output_channel(&dec->decoder, UAC_DEC_PCM_ENC_CHANNEL);
|
||||
dec->output_ch = AUDIO_CH_IS_MONO(UAC_DEC_PCM_ENC_CHANNEL) ? 1 : 2;;
|
||||
struct audio_fmt enc_fmt = {0};
|
||||
enc_fmt.coding_type = UAC_DEC_PCM_ENC_TYPE;
|
||||
enc_fmt.bit_rate = 128;
|
||||
enc_fmt.channel = dec->output_ch;
|
||||
enc_fmt.sample_rate = audio_output_rate(dec->sample_rate);//dec->decoder.fmt.sample_rate;
|
||||
#if (defined(TCFG_PCM2TWS_SBC_ENABLE) && (TCFG_PCM2TWS_SBC_ENABLE))
|
||||
#endif
|
||||
|
||||
int ret = pcm2tws_enc_open(&enc_fmt);
|
||||
if (ret == 0) {
|
||||
#if (defined(TCFG_PCM2TWS_SBC_ENABLE) && (TCFG_PCM2TWS_SBC_ENABLE))
|
||||
pcm2tws_enc_set_output_handler(local_tws_output);
|
||||
#else
|
||||
pcm2tws_enc_set_output_handler(encfile_tws_wfile);
|
||||
ret = encfile_tws_dec_open(&enc_fmt);
|
||||
#endif
|
||||
if (ret == 0) {
|
||||
dec->dec_no_out_sound = 1;
|
||||
pcm2tws_enc_set_resume_handler(uac_dec_resume);
|
||||
audio_decoder_task_del_wait(&decode_task, &dec->wait);
|
||||
local_tws_start(&enc_fmt);
|
||||
audio_decoder_set_run_max(&dec->decoder, 20);
|
||||
dec->src_out_sr = enc_fmt.sample_rate;
|
||||
goto __dec_start;
|
||||
} else {
|
||||
pcm2tws_enc_close();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
|
||||
audio_digital_vol_open(MUSIC_DVOL, app_audio_get_volume(APP_AUDIO_STATE_MUSIC), MUSIC_DVOL_MAX, MUSIC_DVOL_FS, -1);
|
||||
#endif/*SYS_VOL_TYPE == VOL_TYPE_DIGITAL*/
|
||||
|
||||
// 设置叠加功能
|
||||
audio_mixer_ch_open(&dec->mix_ch, &mixer);
|
||||
audio_mixer_ch_set_sample_rate(&dec->mix_ch, audio_output_rate(f.sample_rate));
|
||||
|
||||
|
||||
dec->src_out_sr = audio_output_rate(f.sample_rate);
|
||||
|
||||
__dec_start:
|
||||
uac_audio_sync_init(dec);
|
||||
pc_eq_drc_open(dec, &f);
|
||||
|
||||
app_audio_state_switch(APP_AUDIO_STATE_MUSIC, get_max_sys_vol());
|
||||
|
||||
|
||||
u16 l_volume, r_volume;
|
||||
|
||||
uac_get_cur_vol(0, &l_volume, &r_volume);
|
||||
u8 vol = uac_vol_switch(l_volume);
|
||||
app_audio_set_volume(APP_AUDIO_STATE_MUSIC, vol, 0);
|
||||
|
||||
|
||||
|
||||
#if (defined(TCFG_DEC2TWS_ENABLE) && (TCFG_DEC2TWS_ENABLE))
|
||||
bt_tws_sync_volume();
|
||||
#endif
|
||||
|
||||
#if (defined(USER_AUDIO_PROCESS_ENABLE) && (USER_AUDIO_PROCESS_ENABLE != 0))
|
||||
struct user_audio_digital_parm vol_parm = {0};
|
||||
#if (defined(USER_DIGITAL_VOLUME_ADJUST_ENABLE) && (USER_DIGITAL_VOLUME_ADJUST_ENABLE != 0))
|
||||
vol_parm.en = true;
|
||||
vol_parm.vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE);
|
||||
vol_parm.vol_max = app_audio_get_max_volume();
|
||||
vol_parm.fade_step = 2;
|
||||
#endif
|
||||
dec->user_hdl = user_audio_process_open((void *)&vol_parm, NULL, NULL);
|
||||
#endif
|
||||
|
||||
err = audio_decoder_start(&dec->decoder);
|
||||
if (err) {
|
||||
goto __err;
|
||||
}
|
||||
|
||||
dec->state = 0;
|
||||
dec->cnt = 0;
|
||||
dec->check_data_timer = sys_hi_timer_add(NULL, audio_pc_check_timer, 10);
|
||||
audio_codec_clock_set(AUDIO_PC_MODE, AUDIO_CODING_PCM, dec->wait.preemption);
|
||||
dec->start = 1;
|
||||
return 0;
|
||||
|
||||
__err:
|
||||
|
||||
pc_eq_drc_close(dec);
|
||||
#if (defined(USER_AUDIO_PROCESS_ENABLE) && (USER_AUDIO_PROCESS_ENABLE != 0))
|
||||
if (dec->user_hdl) {
|
||||
user_audio_process_close(dec->user_hdl);
|
||||
dec->user_hdl = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int uac_wait_res_handler(struct audio_res_wait *wait, int event)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (event == AUDIO_RES_GET) {
|
||||
err = uac_audio_start();
|
||||
} else if (event == AUDIO_RES_PUT) {
|
||||
uac_audio_close();
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void uac_speaker_stream_rx_handler(int event, void *data, int len)
|
||||
{
|
||||
if (uac_dec) {
|
||||
audio_decoder_resume(&uac_dec->decoder);
|
||||
}
|
||||
}
|
||||
|
||||
extern struct uac_stream_info *puac_speaker_info;
|
||||
static int usb_audio_play_open(void *_info)
|
||||
{
|
||||
struct uac_dec_hdl *dec;
|
||||
|
||||
if (uac_dec) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
dec = zalloc(sizeof(*dec));
|
||||
if (!dec) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
uac_dec = dec;
|
||||
|
||||
dec->sample_rate = (u32)_info & 0xFFFFFF;
|
||||
dec->channel = (u32)_info >> 24;
|
||||
printf("usb_audio_play_open sr:%d ch:%d\n", dec->sample_rate, dec->channel); //通道是2个
|
||||
set_uac_speaker_rx_handler(dec, uac_speaker_stream_rx_handler);
|
||||
dec->wait.priority = 2;
|
||||
dec->wait.preemption = 1;
|
||||
dec->wait.handler = uac_wait_res_handler;
|
||||
audio_decoder_task_add_wait(&decode_task, &dec->wait);
|
||||
|
||||
clock_add(DEC_PCM_CLK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usb_audio_play_close(void *arg)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (!uac_dec) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (uac_dec->start) {
|
||||
uac_audio_close();
|
||||
}
|
||||
|
||||
|
||||
audio_decoder_task_del_wait(&decode_task, &uac_dec->wait);
|
||||
|
||||
clock_remove(DEC_PCM_CLK);
|
||||
|
||||
local_irq_disable();
|
||||
free(uac_dec);
|
||||
uac_dec = NULL;
|
||||
local_irq_enable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uac_dec_restart(int magic)
|
||||
{
|
||||
if ((!uac_dec) || (magic != uac_dec_maigc)) {
|
||||
return -1;
|
||||
}
|
||||
int _info = (uac_dec->channel << 24) | uac_dec->sample_rate;
|
||||
usb_audio_play_close(NULL);
|
||||
int err = usb_audio_play_open((void *)_info);
|
||||
return err;
|
||||
}
|
||||
|
||||
int uac_dec_push_restart(void)
|
||||
{
|
||||
if (!uac_dec) {
|
||||
return false;
|
||||
}
|
||||
int argv[3];
|
||||
argv[0] = (int)uac_dec_restart;
|
||||
argv[1] = 1;
|
||||
argv[2] = (int)uac_dec_maigc;
|
||||
os_taskq_post_type(os_current_task(), Q_CALLBACK, ARRAY_SIZE(argv), argv);
|
||||
return true;
|
||||
}
|
||||
|
||||
void uac_dec_resume(void)
|
||||
{
|
||||
if (uac_dec && (uac_dec->start)) {
|
||||
audio_decoder_resume(&uac_dec->decoder);
|
||||
}
|
||||
}
|
||||
int uac_dec_no_out_sound(void)
|
||||
{
|
||||
if (uac_dec && uac_dec->dec_no_out_sound) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
extern int usb_audio_mic_open(void *_info);
|
||||
extern int usb_audio_mic_close(void *arg);
|
||||
extern void usb_audio_mic_set_gain(int gain);
|
||||
|
||||
static int usb_device_event_handler(u8 event, int value)
|
||||
{
|
||||
switch (event) {
|
||||
case USB_AUDIO_PLAY_OPEN:
|
||||
/*tone_play_stop();*/
|
||||
usb_audio_play_open((void *)value);
|
||||
break;
|
||||
case USB_AUDIO_PLAY_CLOSE:
|
||||
usb_audio_play_close((void *)value);
|
||||
break;
|
||||
case USB_AUDIO_MIC_OPEN:
|
||||
usb_audio_mic_open((void *)value);
|
||||
break;
|
||||
case USB_AUDIO_MIC_CLOSE:
|
||||
usb_audio_mic_close((void *)value);
|
||||
break;
|
||||
case USB_AUDIO_SET_MIC_VOL:
|
||||
usb_audio_mic_set_gain(value);
|
||||
break;
|
||||
case USB_AUDIO_SET_PLAY_VOL:
|
||||
|
||||
value = uac_vol_switch(value & 0xffff); //left ch volume
|
||||
app_audio_set_volume(APP_AUDIO_STATE_MUSIC, value, 1);
|
||||
#if (defined(TCFG_DEC2TWS_ENABLE) && (TCFG_DEC2TWS_ENABLE))
|
||||
bt_tws_sync_volume();
|
||||
#endif
|
||||
|
||||
#if TCFG_UI_ENABLE
|
||||
u8 vol = app_audio_get_volume(APP_AUDIO_STATE_MUSIC);
|
||||
ui_set_tmp_menu(MENU_MAIN_VOL, 1000, vol, NULL);
|
||||
#endif //TCFG_UI_ENABLE
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usb_audio_event_handler(struct sys_event *event, void *priv)
|
||||
{
|
||||
switch (event->type) {
|
||||
case SYS_DEVICE_EVENT:
|
||||
if ((u32)event->arg == DEVICE_EVENT_FROM_UAC) {
|
||||
log_d("usb device event : %d %x\n", event->u.dev.event, event->u.dev.value);
|
||||
usb_device_event_handler(event->u.dev.event, event->u.dev.value);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
__attribute__((weak))int audio_dev_init()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_audio_demo_init(void)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
audio_dev_init();
|
||||
register_sys_event_handler(SYS_DEVICE_EVENT, DEVICE_EVENT_FROM_UAC, 2,
|
||||
usb_audio_event_handler);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void usb_audio_demo_exit(void)
|
||||
{
|
||||
unregister_sys_event_handler(usb_audio_event_handler);
|
||||
usb_audio_play_close(NULL);
|
||||
usb_audio_mic_close(NULL);
|
||||
audio_codec_clock_del(AUDIO_PC_MODE);
|
||||
}
|
||||
int audio_pc_src_resample_write(void *priv, s16 *data, u32 len)
|
||||
{
|
||||
if (uac_dec && uac_dec->start) { //避免src已经关闭,异步eq 还在输出写src,导致异常
|
||||
return audio_src_resample_write(priv, data, len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void pc_eq_drc_open(struct uac_dec_hdl *dec, struct audio_fmt *fmt)
|
||||
{
|
||||
if (!dec) {
|
||||
return;
|
||||
}
|
||||
#if TCFG_EQ_ENABLE&&TCFG_PC_MODE_EQ_ENABLE
|
||||
u8 drc_en = 0;
|
||||
#if TCFG_DRC_ENABLE&&TCFG_PC_MODE_DRC_ENABLE
|
||||
drc_en = 1;
|
||||
#endif//TCFG_PC_MODE_DRC_ENABLE
|
||||
|
||||
if (dec->src_sync) {
|
||||
dec->eq_drc = dec_eq_drc_setup(dec->src_sync, (eq_output_cb)audio_pc_src_resample_write, fmt->sample_rate, dec->output_ch, 1, drc_en);
|
||||
} else if (dec->dec_no_out_sound) {
|
||||
#if (defined(TCFG_PCM_ENC2TWS_ENABLE) && (TCFG_PCM_ENC2TWS_ENABLE))
|
||||
dec->eq_drc = dec_eq_drc_setup(dec->dec_no_out_sound, (eq_output_cb)pcm2tws_enc_output, fmt->sample_rate, dec->output_ch, 1, drc_en);
|
||||
#endif
|
||||
} else {
|
||||
dec->eq_drc = dec_eq_drc_setup(&dec->mix_ch, (eq_output_cb)audio_mixer_ch_write, fmt->sample_rate, dec->output_ch, 1, drc_en);
|
||||
}
|
||||
#endif//TCFG_PC_MODE_EQ_ENABLE
|
||||
|
||||
}
|
||||
|
||||
|
||||
void pc_eq_drc_close(struct uac_dec_hdl *dec)
|
||||
{
|
||||
if (!dec) {
|
||||
return;
|
||||
}
|
||||
#if TCFG_EQ_ENABLE&&TCFG_PC_MODE_EQ_ENABLE
|
||||
if (dec->eq_drc) {
|
||||
dec_eq_drc_free(dec->eq_drc);
|
||||
dec->eq_drc = NULL;
|
||||
}
|
||||
#endif//TCFG_PC_MODE_EQ_ENABLE
|
||||
|
||||
}
|
||||
#endif /* TCFG_APP_PC_EN */
|
||||
|
||||
286
cpu/br28/audio_dec/audio_dec_pcm.c
Normal file
286
cpu/br28/audio_dec/audio_dec_pcm.c
Normal file
@ -0,0 +1,286 @@
|
||||
#include "app_config.h"
|
||||
#include "audio_decoder.h"
|
||||
#include "media/includes.h"
|
||||
#include "audio_config.h"
|
||||
#include "system/includes.h"
|
||||
#include "audio_enc.h"
|
||||
#include "application/audio_eq.h"
|
||||
#include "application/audio_drc.h"
|
||||
#include "app_config.h"
|
||||
#include "audio_config.h"
|
||||
#include "audio_dec.h"
|
||||
#include "app_main.h"
|
||||
#include "clock_cfg.h"
|
||||
#include "audio_dec_eff.h"
|
||||
#include "audio_codec_clock.h"
|
||||
#include "audio_dvol.h"
|
||||
#include "audio_dec_pcm.h"
|
||||
|
||||
struct pcm_dec_hdl {
|
||||
struct audio_decoder decoder;
|
||||
struct audio_res_wait wait;
|
||||
struct audio_mixer_ch mix_ch;
|
||||
u8 start;
|
||||
u8 remain;
|
||||
u8 channel;
|
||||
u8 output_ch;
|
||||
int sample_rate;
|
||||
int (*pcm_read_cb)(void *, void *, int);
|
||||
};
|
||||
static struct pcm_dec_hdl *pcm_dec = NULL;
|
||||
extern struct audio_decoder_task decode_task;
|
||||
extern struct audio_dac_hdl dac_hdl;
|
||||
|
||||
|
||||
void pcm_dec_set_read_cb(int (*pcm_read_func)(void *, void *, int))
|
||||
{
|
||||
local_irq_disable();
|
||||
if (pcm_dec && pcm_dec->start == 1) {
|
||||
pcm_dec->pcm_read_cb = pcm_read_func;
|
||||
} else {
|
||||
y_printf(">>> %s, %d, pcm_dec set read cb failed!\n", __func__, __LINE__);
|
||||
}
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
static void pcm_LR_to_mono(s16 *pcm_lr, s16 *pcm_mono, int points_len)
|
||||
{
|
||||
s16 pcm_L;
|
||||
s16 pcm_R;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < points_len; i++, pcm_lr += 2) {
|
||||
pcm_L = *pcm_lr;
|
||||
pcm_R = *(pcm_lr + 1);
|
||||
*pcm_mono++ = (s16)(((int)pcm_L + pcm_R) >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
static int pcm_stream_read(struct audio_decoder *decoder, void *buf, u32 len)
|
||||
{
|
||||
int rlen = 0;
|
||||
struct pcm_dec_hdl *dec = container_of(decoder, struct pcm_dec_hdl, decoder);
|
||||
|
||||
local_irq_disable();
|
||||
if (dec) {
|
||||
if (dec->pcm_read_cb) {
|
||||
rlen = dec->pcm_read_cb(NULL, (void *)buf, len);
|
||||
}
|
||||
if (dec->channel == 2 && dec->output_ch == 1) {
|
||||
/* pcm_LR_to_mono((s16 *)buf, (s16 *)buf, rlen >> 2); */
|
||||
/* rlen >>= 1; */
|
||||
}
|
||||
}
|
||||
local_irq_enable();
|
||||
if (!rlen) {
|
||||
return -1;
|
||||
}
|
||||
return rlen;
|
||||
}
|
||||
|
||||
static const struct audio_dec_input pcm_input = {
|
||||
.coding_type = AUDIO_CODING_PCM,
|
||||
.data_type = AUDIO_INPUT_FILE,
|
||||
.ops = {
|
||||
.file = {
|
||||
.fread = pcm_stream_read,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static int pcm_dec_probe_handler(struct audio_decoder *decoder)
|
||||
{
|
||||
struct pcm_dec_hdl *dec = container_of(decoder, struct pcm_dec_hdl, decoder);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcm_dec_output_handler(struct audio_decoder *decoder, s16 *data, int len, void *priv)
|
||||
{
|
||||
struct pcm_dec_hdl *dec = container_of(decoder, struct pcm_dec_hdl, decoder);
|
||||
|
||||
if (!dec) {
|
||||
return 0;
|
||||
}
|
||||
int rlen = len;
|
||||
int wlen = 0;
|
||||
|
||||
if (!dec->remain) {
|
||||
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
|
||||
audio_digital_vol_run(MUSIC_DVOL, data, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
wlen = audio_mixer_ch_write(&dec->mix_ch, data, rlen);
|
||||
if (!wlen) {
|
||||
putchar('w');
|
||||
}
|
||||
rlen -= wlen;
|
||||
|
||||
if (rlen == 0) {
|
||||
dec->remain = 0;
|
||||
} else {
|
||||
dec->remain = 1;
|
||||
}
|
||||
return len - rlen;
|
||||
}
|
||||
|
||||
static const struct audio_dec_handler pcm_dec_handler = {
|
||||
.dec_probe = pcm_dec_probe_handler,
|
||||
.dec_output = pcm_dec_output_handler,
|
||||
};
|
||||
|
||||
static void pcm_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv)
|
||||
{
|
||||
switch (argv[0]) {
|
||||
case AUDIO_DEC_EVENT_END:
|
||||
/*pcm_audio_close();*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void pcm_dec_resume(void)
|
||||
{
|
||||
local_irq_disable();
|
||||
if (pcm_dec && pcm_dec->start) {
|
||||
audio_decoder_resume(&pcm_dec->decoder);
|
||||
}
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
static int pcm_audio_play_start(void)
|
||||
{
|
||||
int err;
|
||||
y_printf(">>>>>>>> Enter Func: %s \n", __func__);
|
||||
struct audio_fmt f = {0};
|
||||
struct pcm_dec_hdl *dec = pcm_dec;
|
||||
|
||||
if (!pcm_dec) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = audio_decoder_open(&dec->decoder, &pcm_input, &decode_task);
|
||||
if (err) {
|
||||
goto __err;
|
||||
}
|
||||
|
||||
audio_decoder_set_handler(&dec->decoder, &pcm_dec_handler);
|
||||
audio_decoder_set_event_handler(&dec->decoder, pcm_dec_event_handler, 0);
|
||||
|
||||
u8 dac_conn = audio_dac_get_channel(&dac_hdl);
|
||||
if (dac_conn == DAC_OUTPUT_LR) {
|
||||
dec->output_ch = 2;
|
||||
} else {
|
||||
dec->output_ch = 1;
|
||||
}
|
||||
|
||||
f.coding_type = AUDIO_CODING_PCM;
|
||||
f.sample_rate = dec->sample_rate;
|
||||
f.channel = dec->output_ch;
|
||||
|
||||
err = audio_decoder_set_fmt(&dec->decoder, &f);
|
||||
|
||||
printf(">>>>>>>> %s, dec->output_ch : %d\n", __func__, dec->output_ch);
|
||||
|
||||
#if TCFG_AUDIO_OUTPUT_IIS
|
||||
sound_pcm_dev_channel_mapping(dec->output_ch);
|
||||
#endif
|
||||
|
||||
if (err) {
|
||||
goto __err;
|
||||
}
|
||||
|
||||
|
||||
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
|
||||
audio_digital_vol_open(MUSIC_DVOL, app_audio_get_volume(APP_AUDIO_STATE_MUSIC), MUSIC_DVOL_MAX, MUSIC_DVOL_FS, -1);
|
||||
#endif/*SYS_VOL_TYPE == VOL_TYPE_DIGITAL*/
|
||||
|
||||
// 设置叠加功能
|
||||
audio_mixer_ch_open(&dec->mix_ch, &mixer);
|
||||
audio_mixer_ch_set_sample_rate(&dec->mix_ch, audio_output_rate(f.sample_rate));
|
||||
app_audio_state_switch(APP_AUDIO_STATE_MUSIC, get_max_sys_vol());
|
||||
|
||||
int vol = app_audio_get_volume(APP_AUDIO_STATE_MUSIC);
|
||||
app_audio_set_volume(APP_AUDIO_STATE_MUSIC, vol, 0);
|
||||
|
||||
err = audio_decoder_start(&dec->decoder);
|
||||
if (err) {
|
||||
goto __err;
|
||||
}
|
||||
audio_codec_clock_set(AUDIO_PC_MODE, AUDIO_CODING_PCM, dec->wait.preemption);
|
||||
dec->start = 1;
|
||||
return 0;
|
||||
|
||||
__err:
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int pcm_audio_play_stop(void)
|
||||
{
|
||||
if (!pcm_dec || !pcm_dec->start) {
|
||||
return 0;
|
||||
}
|
||||
pcm_dec->start = 0;
|
||||
audio_decoder_close(&pcm_dec->decoder);
|
||||
audio_mixer_ch_close(&pcm_dec->mix_ch);
|
||||
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
|
||||
audio_digital_vol_close(MUSIC_DVOL);
|
||||
#endif/*SYS_VOL_TYPE == VOL_TYPE_DIGITAL*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcm_wait_res_handler(struct audio_res_wait *wait, int event)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (event == AUDIO_RES_GET) {
|
||||
err = pcm_audio_play_start();
|
||||
} else if (event == AUDIO_RES_PUT) {
|
||||
/* pcm_audio_play_stop(); */
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
int pcm_audio_play_open(int sr, u8 ch)
|
||||
{
|
||||
struct pcm_dec_hdl *dec;
|
||||
|
||||
if (pcm_dec) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
dec = zalloc(sizeof(*dec));
|
||||
if (!dec) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pcm_dec = dec;
|
||||
|
||||
dec->sample_rate = sr;
|
||||
dec->channel = ch;
|
||||
y_printf(">>> pcm_audio_play_open sr:%d ch:%d\n", dec->sample_rate, dec->channel); //通道是2个
|
||||
dec->wait.priority = 2;
|
||||
dec->wait.preemption = 1;
|
||||
dec->wait.handler = pcm_wait_res_handler;
|
||||
audio_decoder_task_add_wait(&decode_task, &dec->wait);
|
||||
|
||||
clock_add(DEC_PCM_CLK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void pcm_audio_play_close(void)
|
||||
{
|
||||
if (!pcm_dec) {
|
||||
return;
|
||||
}
|
||||
pcm_audio_play_stop();
|
||||
audio_decoder_task_del_wait(&decode_task, &pcm_dec->wait);
|
||||
clock_remove(DEC_PCM_CLK);
|
||||
local_irq_disable();
|
||||
free(pcm_dec);
|
||||
pcm_dec = NULL;
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
16
cpu/br28/audio_dec/audio_dec_pcm.h
Normal file
16
cpu/br28/audio_dec/audio_dec_pcm.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef __AUDIO_DEC_PCM_H
|
||||
#define __AUDIO_DEC_PCM_H
|
||||
|
||||
#include "asm/cpu.h"
|
||||
|
||||
|
||||
void pcm_dec_resume(void);
|
||||
void pcm_dec_set_read_cb(int (*pcm_read_func)(void *, void *, int));
|
||||
int pcm_audio_play_open(int sr, u8 ch);
|
||||
void pcm_audio_play_close(void);
|
||||
|
||||
|
||||
extern int sound_pcm_dev_channel_mapping(int ch_num);
|
||||
|
||||
#endif
|
||||
|
||||
920
cpu/br28/audio_dec/audio_usb_mic.c
Normal file
920
cpu/br28/audio_dec/audio_usb_mic.c
Normal file
@ -0,0 +1,920 @@
|
||||
#include "asm/includes.h"
|
||||
#include "media/includes.h"
|
||||
#include "system/includes.h"
|
||||
#include "device/uac_stream.h"
|
||||
#include "audio_enc.h"
|
||||
#include "app_main.h"
|
||||
#include "user_cfg_id.h"
|
||||
#include "app_config.h"
|
||||
#include "audio_codec_clock.h"
|
||||
#include "audio_config.h"
|
||||
/* #include "application/audio_echo_reverb.h" */
|
||||
|
||||
/*USB MIC上行数据同步及变采样模块使能*/
|
||||
#define USB_MIC_SRC_ENABLE 1
|
||||
|
||||
#if TCFG_USB_MIC_CVP_ENABLE
|
||||
#include "aec_user.h"
|
||||
#include "overlay_code.h"
|
||||
#endif/*TCFG_USB_MIC_CVP_ENABLE*/
|
||||
|
||||
#if USB_MIC_SRC_ENABLE
|
||||
#include "audio_track.h"
|
||||
#include "Resample_api.h"
|
||||
#endif/*USB_MIC_SRC_ENABLE*/
|
||||
|
||||
#define USB_AUDIO_MIC_WRITE_TASK_NAME "usbmic_write"
|
||||
|
||||
#define PCM_ENC2USB_OUTBUF_LEN (6 * 1024)
|
||||
|
||||
#define USB_MIC_BUF_NUM 3
|
||||
|
||||
#if TCFG_AUDIO_TRIPLE_MIC_ENABLE
|
||||
#define USB_MIC_CH_NUM 3 /* 3mic通话 */
|
||||
#elif TCFG_AUDIO_DUAL_MIC_ENABLE
|
||||
#define USB_MIC_CH_NUM 2 /* 双mic通话 */
|
||||
#else
|
||||
#define USB_MIC_CH_NUM 1 /* 单mic通话 */
|
||||
#endif
|
||||
|
||||
#define USB_MIC_IRQ_POINTS 256
|
||||
#define USB_MIC_BUFS_SIZE (USB_MIC_CH_NUM * USB_MIC_BUF_NUM * USB_MIC_IRQ_POINTS)
|
||||
|
||||
#define USB_MIC_STOP 0x00
|
||||
#define USB_MIC_START 0x01
|
||||
|
||||
#ifndef VM_USB_MIC_GAIN
|
||||
#define VM_USB_MIC_GAIN 5
|
||||
#endif
|
||||
|
||||
#define USB_PLNK_MIC_GAIN_ENABLE 1 //PLNK_MIC数字增益放大使能
|
||||
#define USB_PLNK_MIC_DIG_GAIN 60.f //PLNK_MIC数字增益(Gain = 10^(dB_diff/20))
|
||||
|
||||
extern struct audio_adc_hdl adc_hdl;
|
||||
extern u16 uac_get_mic_vol(const u8 usb_id);
|
||||
extern int usb_output_sample_rate();
|
||||
#if USB_MIC_SRC_ENABLE
|
||||
typedef struct {
|
||||
u8 start;
|
||||
u8 busy;
|
||||
u16 in_sample_rate;
|
||||
u16 out_sample_rate;
|
||||
u32 *runbuf;
|
||||
s16 output[320 * 3 + 16];
|
||||
RS_STUCT_API *ops;
|
||||
void *audio_track;
|
||||
} usb_mic_sw_src_t;
|
||||
static usb_mic_sw_src_t *usb_mic_src = NULL;
|
||||
#endif/*USB_MIC_SRC_ENABLE*/
|
||||
|
||||
|
||||
|
||||
struct _usb_mic_hdl {
|
||||
struct audio_adc_output_hdl adc_output;
|
||||
struct adc_mic_ch mic_ch;
|
||||
s16 adc_buf[USB_MIC_BUFS_SIZE];
|
||||
enum enc_source source;
|
||||
OS_SEM sem;
|
||||
|
||||
cbuffer_t output_cbuf;
|
||||
u8 *output_buf;//[PCM_ENC2USB_OUTBUF_LEN];
|
||||
u8 rec_tx_channels;
|
||||
u8 mic_data_ok;/*mic数据等到一定长度再开始发送*/
|
||||
u8 status;
|
||||
u8 drop_data; //用来丢掉刚开mic的前几帧数据
|
||||
#if TCFG_USB_MIC_ECHO_ENABLE
|
||||
ECHO_API_STRUCT *p_echo_hdl;
|
||||
#endif
|
||||
#if (USB_MIC_CH_NUM > 1)
|
||||
s16 tmp_buf[USB_MIC_IRQ_POINTS];
|
||||
#endif/*USB_MIC_CH_NUM*/
|
||||
#if (USB_MIC_CH_NUM > 2)
|
||||
s16 tmp_buf_1[USB_MIC_IRQ_POINTS];
|
||||
#endif/*USB_MIC_CH_NUM*/
|
||||
s16 *usb_mic_data;
|
||||
u16 data_len;
|
||||
float dig_gain;
|
||||
};
|
||||
|
||||
struct audio_sample_track_context {
|
||||
u32 in_sr;
|
||||
volatile u8 track_step;
|
||||
volatile int samples;
|
||||
volatile u32 sample_rate;
|
||||
volatile u32 adc_points;
|
||||
volatile u32 next_period;
|
||||
volatile int period;
|
||||
};
|
||||
static u32 adc_hwp = 0;
|
||||
static u32 adc_points = 0;
|
||||
static void *user_audio_local_sample_track_open(int in_sr, int sample_rate, int period)
|
||||
{
|
||||
struct audio_sample_track_context *ctx;
|
||||
ctx = (struct audio_sample_track_context *)zalloc(sizeof(struct audio_sample_track_context));
|
||||
if (!ctx) {
|
||||
return NULL;
|
||||
}
|
||||
ctx->in_sr = in_sr;
|
||||
ctx->sample_rate = sample_rate;
|
||||
ctx->period = period * sample_rate / 1000;
|
||||
adc_points = 0;
|
||||
return ctx;
|
||||
}
|
||||
int get_audio_adc_points_time()//获取总的采样周期
|
||||
{
|
||||
return adc_points + ((JL_AUDIO->ADC_HWP > adc_hwp) ? (JL_AUDIO->ADC_HWP - adc_hwp) : (JL_AUDIO->ADC_HWP + JL_AUDIO->ADC_LEN - adc_hwp));
|
||||
}
|
||||
static int user_audio_local_sample_track_in_period(void *c, int samples)
|
||||
{
|
||||
struct audio_sample_track_context *ctx = (struct audio_sample_track_context *)c;
|
||||
if (ctx->track_step == 0) {
|
||||
ctx->track_step = 1;
|
||||
goto __exit;
|
||||
}
|
||||
if (ctx->track_step == 1) {
|
||||
ctx->track_step = 2;
|
||||
ctx->next_period = ctx->period;
|
||||
ctx->samples = 0;
|
||||
goto __exit;
|
||||
}
|
||||
ctx->samples += samples;
|
||||
if (time_after(ctx->samples, ctx->next_period)) {
|
||||
int adc_points = get_audio_adc_points_time();
|
||||
int points_diff = (adc_points - ctx->adc_points);
|
||||
if (points_diff > 0) {
|
||||
int sample_rate = ((u64)((u64)ctx->in_sr * (u64)ctx->samples)) / points_diff;
|
||||
/* printf("> track : %d %d %d %d< \n", sample_rate, ctx->samples, ctx->in_sr, points_diff); */
|
||||
/* printf("> track : %d < \n", sample_rate); */
|
||||
ctx->sample_rate = sample_rate;
|
||||
}
|
||||
ctx->adc_points = adc_points;
|
||||
ctx->next_period = ctx->period;
|
||||
ctx->samples = 0;
|
||||
}
|
||||
__exit:
|
||||
return ctx->sample_rate;
|
||||
}
|
||||
static int user_audio_local_sample_track_rate(void *c)
|
||||
{
|
||||
struct audio_sample_track_context *ctx = (struct audio_sample_track_context *)c;
|
||||
return ctx->sample_rate;
|
||||
}
|
||||
static void user_audio_local_sample_track_close(void *c)
|
||||
{
|
||||
struct audio_sample_track_context *ctx = (struct audio_sample_track_context *)c;
|
||||
if (!ctx) {
|
||||
return;
|
||||
}
|
||||
ctx->track_step = 0;
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
static struct _usb_mic_hdl *usb_mic_hdl = NULL;
|
||||
#if TCFG_USB_MIC_ECHO_ENABLE
|
||||
ECHO_PARM_SET usbmic_echo_parm_default = {
|
||||
.delay = 200, //回声的延时时间 0-300ms
|
||||
.decayval = 50, // 0-70%
|
||||
.direct_sound_enable = 1, //直达声使能 0/1
|
||||
.filt_enable = 1, //发散滤波器使能
|
||||
};
|
||||
EF_REVERB_FIX_PARM usbmic_echo_fix_parm_default = {
|
||||
.wetgain = 2048, ////湿声增益:[0:4096]
|
||||
.drygain = 4096, ////干声增益: [0:4096]
|
||||
.sr = MIC_EFFECT_SAMPLERATE, ////采样率
|
||||
.max_ms = 200, ////所需要的最大延时,影响 need_buf 大小
|
||||
};
|
||||
#endif
|
||||
static int usb_audio_mic_sync(u32 data_size)
|
||||
{
|
||||
#if 0
|
||||
int change_point = 0;
|
||||
|
||||
if (data_size > __this->rec_top_size) {
|
||||
change_point = -1;
|
||||
} else if (data_size < __this->rec_bottom_size) {
|
||||
change_point = 1;
|
||||
}
|
||||
|
||||
if (change_point) {
|
||||
struct audio_pcm_src src;
|
||||
src.resample = 0;
|
||||
src.ratio_i = (1024) * 2;
|
||||
src.ratio_o = (1024 + change_point) * 2;
|
||||
src.convert = 1;
|
||||
dev_ioctl(__this->rec_dev, AUDIOC_PCM_RATE_CTL, (u32)&src);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usb_audio_mic_tx_handler(int event, void *data, int len)
|
||||
{
|
||||
if (usb_mic_hdl == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (usb_mic_hdl->status == USB_MIC_STOP) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
int r_len = 0;
|
||||
u8 ch = 0;
|
||||
u8 double_read = 0;
|
||||
|
||||
/* int rlen = 0; */
|
||||
|
||||
if (usb_mic_hdl->mic_data_ok == 0) {
|
||||
if (usb_mic_hdl->output_cbuf.data_len > (PCM_ENC2USB_OUTBUF_LEN / 4)) {
|
||||
usb_mic_hdl->mic_data_ok = 1;
|
||||
}
|
||||
//y_printf("mic_tx NULL\n");
|
||||
memset(data, 0, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
#if USB_MIC_SRC_ENABLE
|
||||
if (usb_mic_src && usb_mic_src->audio_track) {
|
||||
user_audio_local_sample_track_in_period(usb_mic_src->audio_track, (len >> 1) / usb_mic_hdl->rec_tx_channels);
|
||||
}
|
||||
#endif/*USB_MIC_SRC_ENABLE*/
|
||||
|
||||
/* usb_audio_mic_sync(size); */
|
||||
if (usb_mic_hdl->rec_tx_channels == 2) {
|
||||
len = cbuf_read(&usb_mic_hdl->output_cbuf, data, len / 2);
|
||||
s16 *tx_pcm = (s16 *)data;
|
||||
int cnt = len / 2;
|
||||
for (cnt = len / 2; cnt >= 2;) {
|
||||
tx_pcm[cnt - 1] = tx_pcm[cnt / 2 - 1];
|
||||
tx_pcm[cnt - 2] = tx_pcm[cnt / 2 - 1];
|
||||
cnt -= 2;
|
||||
}
|
||||
len *= 2;
|
||||
} else {
|
||||
len = cbuf_read(&usb_mic_hdl->output_cbuf, data, len);
|
||||
}
|
||||
if (!len) {
|
||||
putchar('M');
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
int usb_audio_mic_write(void *data, u16 len)
|
||||
{
|
||||
int wlen = len;
|
||||
if (usb_mic_hdl) {
|
||||
if (usb_mic_hdl->status == USB_MIC_STOP) {
|
||||
return len;
|
||||
}
|
||||
|
||||
int outlen = len;
|
||||
s16 *obuf = data;
|
||||
|
||||
#if USB_MIC_SRC_ENABLE
|
||||
if (usb_mic_src && usb_mic_src->start) {
|
||||
usb_mic_src->busy = 1;
|
||||
u32 sr = usb_output_sample_rate();
|
||||
usb_mic_src->ops->set_sr(usb_mic_src->runbuf, sr);
|
||||
outlen = usb_mic_src->ops->run(usb_mic_src->runbuf, data, len >> 1, usb_mic_src->output);
|
||||
usb_mic_src->busy = 0;
|
||||
ASSERT(outlen <= (sizeof(usb_mic_src->output) >> 1));
|
||||
//printf("16->48k:%d,%d,%d\n",len >> 1,outlen,sizeof(usb_mic_src->output));
|
||||
obuf = usb_mic_src->output;
|
||||
outlen = outlen << 1;
|
||||
}
|
||||
#endif/*USB_MIC_SRC_ENABLE*/
|
||||
wlen = cbuf_write(&usb_mic_hdl->output_cbuf, obuf, outlen);
|
||||
if (wlen != outlen) {
|
||||
r_printf("usb_mic write full:%d-%d\n", wlen, outlen);
|
||||
}
|
||||
}
|
||||
return wlen;
|
||||
}
|
||||
|
||||
static void adc_output_to_cbuf(void *priv, s16 *data, int len)
|
||||
{
|
||||
if (usb_mic_hdl == NULL) {
|
||||
return ;
|
||||
}
|
||||
if (usb_mic_hdl->status == USB_MIC_STOP) {
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
switch (usb_mic_hdl->source) {
|
||||
case ENCODE_SOURCE_MIC:
|
||||
case ENCODE_SOURCE_LINE0_LR:
|
||||
case ENCODE_SOURCE_LINE1_LR:
|
||||
case ENCODE_SOURCE_LINE2_LR: {
|
||||
|
||||
adc_hwp = JL_AUDIO->ADC_HWP;
|
||||
adc_points += len / 2;
|
||||
|
||||
|
||||
#if TCFG_USB_MIC_CVP_ENABLE
|
||||
#if (USB_MIC_CH_NUM == 3)/*3 Mic*/
|
||||
s16 *mic0_data = data;
|
||||
s16 *mic1_data = usb_mic_hdl->tmp_buf;
|
||||
s16 *mic1_data_pos = usb_mic_hdl->tmp_buf_1;
|
||||
//printf("mic_data: %x, %x, %d\n",data, mic1_data_pos, len);
|
||||
for (u16 i = 0; i < (len >> 1); i++) {
|
||||
mic0_data[i] = data[i * 3];
|
||||
mic1_data[i] = data[i * 3 + 1];
|
||||
mic1_data_pos[i] = data[i * 3 + 2];
|
||||
}
|
||||
audio_aec_inbuf_ref(mic1_data, len);
|
||||
audio_aec_inbuf_ref_1(mic1_data_pos, len);
|
||||
audio_aec_inbuf(data, len);
|
||||
return;
|
||||
|
||||
#elif (USB_MIC_CH_NUM == 2)/*DualMic*/
|
||||
s16 *mic0_data = data;
|
||||
s16 *mic1_data = usb_mic_hdl->tmp_buf;
|
||||
s16 *mic1_data_pos = data + (len / 2);
|
||||
//printf("mic_data:%x,%x,%d\n",data,mic1_data_pos,len);
|
||||
for (u16 i = 0; i < (len >> 1); i++) {
|
||||
mic0_data[i] = data[i * 2];
|
||||
mic1_data[i] = data[i * 2 + 1];
|
||||
}
|
||||
memcpy(mic1_data_pos, mic1_data, len);
|
||||
|
||||
#if 0 /*debug*/
|
||||
static u16 mic_cnt = 0;
|
||||
if (mic_cnt++ > 300) {
|
||||
putchar('1');
|
||||
audio_aec_inbuf(mic1_data_pos, len);
|
||||
if (mic_cnt > 600) {
|
||||
mic_cnt = 0;
|
||||
}
|
||||
} else {
|
||||
putchar('0');
|
||||
audio_aec_inbuf(mic0_data, len);
|
||||
}
|
||||
return;
|
||||
#endif/*debug end*/
|
||||
#if (TCFG_AUDIO_DMS_MIC_MANAGE == DMS_MASTER_MIC0)
|
||||
audio_aec_inbuf_ref(mic1_data_pos, len);
|
||||
audio_aec_inbuf(data, len);
|
||||
#else
|
||||
audio_aec_inbuf_ref(data, len);
|
||||
audio_aec_inbuf(mic1_data_pos, len);
|
||||
#endif/*TCFG_AUDIO_DMS_MIC_MANAGE*/
|
||||
#else/*SingleMic*/
|
||||
audio_aec_inbuf(data, len);
|
||||
#endif/*USB_MIC_CH_NUM*/
|
||||
|
||||
#else /* TCFG_USB_MIC_CVP_ENABLE == 0 */
|
||||
if (usb_mic_hdl->drop_data != 0) {
|
||||
usb_mic_hdl-> drop_data--;
|
||||
memset(data, 0, len);
|
||||
}
|
||||
#if TCFG_USB_MIC_ECHO_ENABLE
|
||||
if (usb_mic_hdl->p_echo_hdl) {
|
||||
run_echo(usb_mic_hdl->p_echo_hdl, data, data, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 由于usb_audio_mic_write中SRC执行时间较长在adc中断中写数据会影响usb中断 */
|
||||
/* 改为在usb_audio_mic_write_task中向usb写数据 */
|
||||
/* adc输入一帧数据,唤醒一次运行任务处理数据 */
|
||||
usb_mic_hdl->usb_mic_data = data;
|
||||
usb_mic_hdl->data_len = len;
|
||||
os_sem_set(&usb_mic_hdl->sem, 0);
|
||||
os_sem_post(&usb_mic_hdl->sem);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if USB_MIC_SRC_ENABLE
|
||||
static int sw_src_init(u32 in_sr, u32 out_sr)
|
||||
{
|
||||
usb_mic_src = zalloc(sizeof(usb_mic_sw_src_t));
|
||||
ASSERT(usb_mic_src);
|
||||
|
||||
usb_mic_src->in_sample_rate = in_sr;
|
||||
usb_mic_src->out_sample_rate = out_sr;
|
||||
|
||||
usb_mic_src->ops = get_rs16_context();
|
||||
/* usb_mic_src->ops = get_rsfast_context(); */
|
||||
g_printf("ops:0x%x\n", usb_mic_src->ops);
|
||||
ASSERT(usb_mic_src->ops);
|
||||
u32 need_buf = usb_mic_src->ops->need_buf();
|
||||
g_printf("runbuf:%d\n", need_buf);
|
||||
usb_mic_src->runbuf = malloc(need_buf);
|
||||
ASSERT(usb_mic_src->runbuf);
|
||||
RS_PARA_STRUCT rs_para_obj;
|
||||
rs_para_obj.nch = 1;
|
||||
|
||||
rs_para_obj.new_insample = in_sr;
|
||||
rs_para_obj.new_outsample = out_sr;
|
||||
printf("sw src,in = %d,out = %d\n", rs_para_obj.new_insample, rs_para_obj.new_outsample);
|
||||
usb_mic_src->ops->open(usb_mic_src->runbuf, &rs_para_obj);
|
||||
|
||||
usb_mic_src->audio_track = user_audio_local_sample_track_open(in_sr, out_sr, 2000);
|
||||
usb_mic_src->start = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sw_src_exit(void)
|
||||
{
|
||||
if (usb_mic_src) {
|
||||
usb_mic_src->start = 0;
|
||||
while (usb_mic_src->busy) {
|
||||
putchar('w');
|
||||
os_time_dly(2);
|
||||
}
|
||||
|
||||
user_audio_local_sample_track_close(usb_mic_src->audio_track);
|
||||
usb_mic_src->audio_track = NULL;
|
||||
|
||||
local_irq_disable();
|
||||
if (usb_mic_src->runbuf) {
|
||||
free(usb_mic_src->runbuf);
|
||||
usb_mic_src->runbuf = 0;
|
||||
}
|
||||
free(usb_mic_src);
|
||||
usb_mic_src = NULL;
|
||||
local_irq_enable();
|
||||
printf("sw_src_exit\n");
|
||||
}
|
||||
printf("sw_src_exit ok\n");
|
||||
return 0;
|
||||
}
|
||||
#endif/*USB_MIC_SRC_ENABLE*/
|
||||
|
||||
|
||||
|
||||
#if TCFG_USB_MIC_CVP_ENABLE
|
||||
static int usb_mic_aec_output(s16 *data, u16 len)
|
||||
{
|
||||
//putchar('k');
|
||||
if (usb_mic_hdl == NULL) {
|
||||
return len ;
|
||||
}
|
||||
if (usb_mic_hdl->status == USB_MIC_STOP) {
|
||||
return len;
|
||||
}
|
||||
|
||||
int outlen = len;
|
||||
s16 *outdat = data;
|
||||
/* if (aec_hdl->dump_packet) { */
|
||||
/* aec_hdl->dump_packet--; */
|
||||
/* //memset(outdat, 0, outlen); */
|
||||
/* } */
|
||||
u16 wlen = usb_audio_mic_write(outdat, outlen);
|
||||
return len;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
int uac_mic_vol_switch(int vol)
|
||||
{
|
||||
return vol * 14 / 100;
|
||||
}
|
||||
|
||||
float uac_mic_dig_gain_switch(int vol)
|
||||
{
|
||||
float gain = vol / 10.f;
|
||||
return gain;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* USB Audio MIC Write Task
|
||||
* Description: USB MIC 写数据任务
|
||||
* Arguments : priv 私用参数
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static void usb_audio_mic_write_task(void *priv)
|
||||
{
|
||||
printf("==Audio Usb Mic Write Task==\n");
|
||||
|
||||
while (1) {
|
||||
os_sem_pend(&usb_mic_hdl->sem, 0);
|
||||
|
||||
putchar('.');
|
||||
if (usb_mic_hdl->status) {
|
||||
usb_audio_mic_write(usb_mic_hdl->usb_mic_data, usb_mic_hdl->data_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* PDM MIC API
|
||||
* Description: PDM mic操作接口
|
||||
* Arguments : None.
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
#if (TCFG_AUDIO_ADC_MIC_CHA == PLNK_MIC)
|
||||
/* #define USB_PLNK_SR 16000#<{(|16000/44100/48000|)}># */
|
||||
#define USB_PLNK_SCLK 2400000 /*1M-4M,SCLK/SR需为整数且在1-4096范围*/
|
||||
#define USB_PLNK_CH_NUM 1 /*支持的最大通道(max = 2)*/
|
||||
#define USB_PLNK_IRQ_POINTS 256 /*采样中断点数*/
|
||||
#include "pdm_link.h"
|
||||
#include "media/audio_gain_process.h"
|
||||
static audio_plnk_t *audio_plnk_mic = NULL;
|
||||
static void audio_plnk_mic_output(void *buf, u16 len)
|
||||
{
|
||||
s16 *mic0 = (s16 *)buf;
|
||||
if (audio_plnk_mic) {
|
||||
#if TCFG_USB_MIC_CVP_ENABLE
|
||||
audio_aec_inbuf(mic0, len << 1);
|
||||
#else
|
||||
#if USB_PLNK_MIC_GAIN_ENABLE
|
||||
GainProcess_16Bit(mic0, mic0, USB_PLNK_MIC_DIG_GAIN, 1, 1, 1, len);
|
||||
#endif
|
||||
usb_mic_hdl->usb_mic_data = mic0;
|
||||
usb_mic_hdl->data_len = len << 1;
|
||||
os_sem_set(&usb_mic_hdl->sem, 0);
|
||||
os_sem_post(&usb_mic_hdl->sem);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static int usb_pdm_mic_en(u8 en, u16 sr, u16 gain)
|
||||
{
|
||||
printf("usb_pdm_mic_en:%d\n", en);
|
||||
if (en) {
|
||||
if (audio_plnk_mic) {
|
||||
printf("audio_plnk_mic re-malloc error\n");
|
||||
return -1;
|
||||
}
|
||||
audio_plnk_mic = zalloc(sizeof(audio_plnk_t));
|
||||
if (audio_plnk_mic == NULL) {
|
||||
printf("audio_plnk_mic zalloc failed\n");
|
||||
return -1;
|
||||
}
|
||||
audio_mic_pwr_ctl(MIC_PWR_ON);
|
||||
audio_plnk_mic->ch_num = USB_PLNK_CH_NUM;
|
||||
audio_plnk_mic->sr = sr;
|
||||
audio_plnk_mic->buf_len = USB_PLNK_IRQ_POINTS;
|
||||
#if (PLNK_CH_EN == PLNK_CH0_EN)
|
||||
audio_plnk_mic->ch0_mode = CH0MD_CH0_SCLK_RISING_EDGE;
|
||||
audio_plnk_mic->ch1_mode = CH1MD_CH0_SCLK_FALLING_EDGE;
|
||||
#elif (PLNK_CH_EN == PLNK_CH1_EN)
|
||||
audio_plnk_mic->ch0_mode = CH0MD_CH1_SCLK_FALLING_EDGE;
|
||||
audio_plnk_mic->ch1_mode = CH1MD_CH1_SCLK_RISING_EDGE;
|
||||
#else
|
||||
audio_plnk_mic->ch0_mode = CH0MD_CH0_SCLK_RISING_EDGE;
|
||||
audio_plnk_mic->ch1_mode = CH1MD_CH1_SCLK_RISING_EDGE;
|
||||
#endif
|
||||
audio_plnk_mic->buf = zalloc(audio_plnk_mic->buf_len * audio_plnk_mic->ch_num * 2 * 2);
|
||||
ASSERT(audio_plnk_mic->buf);
|
||||
audio_plnk_mic->sclk_io = TCFG_AUDIO_PLNK_SCLK_PIN;
|
||||
audio_plnk_mic->ch0_io = TCFG_AUDIO_PLNK_DAT0_PIN;
|
||||
audio_plnk_mic->ch1_io = TCFG_AUDIO_PLNK_DAT1_PIN;
|
||||
audio_plnk_mic->output = audio_plnk_mic_output;
|
||||
audio_plnk_open(audio_plnk_mic);
|
||||
audio_plnk_start(audio_plnk_mic);
|
||||
SFR(JL_ASS->CLK_CON, 0, 2, 3);
|
||||
} else {
|
||||
audio_plnk_close();
|
||||
#if TCFG_AUDIO_ANC_ENABLE
|
||||
//printf("anc_status:%d\n",anc_status_get());
|
||||
if (anc_status_get() == 0) {
|
||||
audio_mic_pwr_ctl(MIC_PWR_OFF);
|
||||
}
|
||||
#else
|
||||
audio_mic_pwr_ctl(MIC_PWR_OFF);
|
||||
#endif/*TCFG_AUDIO_ANC_ENABLE*/
|
||||
if (audio_plnk_mic->buf) {
|
||||
free(audio_plnk_mic->buf);
|
||||
}
|
||||
if (audio_plnk_mic) {
|
||||
free(audio_plnk_mic);
|
||||
audio_plnk_mic = NULL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif/* #if (TCFG_AUDIO_ADC_MIC_CHA == PLNK_MIC) */
|
||||
|
||||
int usb_audio_mic_open(void *_info)
|
||||
{
|
||||
int err = 0;
|
||||
if (usb_mic_hdl) {
|
||||
return 0;
|
||||
}
|
||||
usb_mic_hdl = zalloc(sizeof(*usb_mic_hdl));
|
||||
if (!usb_mic_hdl) {
|
||||
return -EFAULT;
|
||||
}
|
||||
usb_mic_hdl->status = USB_MIC_STOP;
|
||||
|
||||
usb_mic_hdl->output_buf = zalloc(PCM_ENC2USB_OUTBUF_LEN);
|
||||
if (!usb_mic_hdl->output_buf) {
|
||||
printf("usb_mic_hdl->output_buf NULL\n");
|
||||
|
||||
if (usb_mic_hdl) {
|
||||
free(usb_mic_hdl);
|
||||
usb_mic_hdl = NULL;
|
||||
}
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
u32 sample_rate = (u32)_info & 0xFFFFFF;
|
||||
usb_mic_hdl->rec_tx_channels = (u32)_info >> 24;
|
||||
usb_mic_hdl->source = ENCODE_SOURCE_MIC;
|
||||
printf("usb mic sr:%d ch:%d\n", sample_rate, usb_mic_hdl->rec_tx_channels);
|
||||
|
||||
|
||||
usb_mic_hdl->drop_data = 10; //用来丢掉前几帧数据
|
||||
usb_mic_hdl->dig_gain = 1.f; // 用来初始化数字增益
|
||||
u32 out_sample_rate = sample_rate;
|
||||
#if TCFG_USB_MIC_CVP_ENABLE
|
||||
sample_rate = 16000;
|
||||
printf("usb mic sr[aec]:%d\n", sample_rate);
|
||||
/*加载清晰语音处理代码*/
|
||||
audio_cvp_code_load();
|
||||
audio_aec_open(sample_rate, TCFG_USB_MIC_CVP_MODE, usb_mic_aec_output);
|
||||
#else
|
||||
os_sem_create(&usb_mic_hdl->sem, 0);
|
||||
err = task_create(usb_audio_mic_write_task, NULL, USB_AUDIO_MIC_WRITE_TASK_NAME);
|
||||
#endif
|
||||
|
||||
#if USB_MIC_SRC_ENABLE
|
||||
sw_src_init(sample_rate, out_sample_rate);
|
||||
#endif /*USB_MIC_SRC_ENABLE*/
|
||||
|
||||
|
||||
cbuf_init(&usb_mic_hdl->output_cbuf, usb_mic_hdl->output_buf, PCM_ENC2USB_OUTBUF_LEN);
|
||||
|
||||
#if TCFG_MIC_EFFECT_ENABLE
|
||||
app_var.usb_mic_gain = mic_effect_get_micgain();
|
||||
#else
|
||||
app_var.usb_mic_gain = uac_mic_vol_switch(uac_get_mic_vol(0));
|
||||
#endif//TCFG_MIC_EFFECT_ENABLE
|
||||
|
||||
#if (TCFG_USB_MIC_DATA_FROM_MICEFFECT)
|
||||
mic_effect_to_usbmic_onoff(1);
|
||||
#else
|
||||
#if (TCFG_AUDIO_ADC_MIC_CHA == PLNK_MIC)
|
||||
usb_pdm_mic_en(1, sample_rate, app_var.usb_mic_gain);
|
||||
#else
|
||||
audio_mic_pwr_ctl(MIC_PWR_ON);
|
||||
#if 1
|
||||
#if (TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_0)
|
||||
printf("adc_mic0 open\n");
|
||||
audio_adc_mic_open(&usb_mic_hdl->mic_ch, AUDIO_ADC_MIC_0, &adc_hdl);
|
||||
#ifndef TALK_MIC0_GAIN
|
||||
audio_adc_mic_set_gain(&usb_mic_hdl->mic_ch, app_var.usb_mic_gain);
|
||||
#else
|
||||
audio_adc_mic_set_gain(&usb_mic_hdl->mic_ch, TALK_MIC0_GAIN);
|
||||
#endif
|
||||
#endif/*TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_0*/
|
||||
#if (TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_1)
|
||||
printf("adc_mic1 open\n");
|
||||
audio_adc_mic1_open(&usb_mic_hdl->mic_ch, AUDIO_ADC_MIC_1, &adc_hdl);
|
||||
#ifndef FF_MIC1_GAIN
|
||||
audio_adc_mic1_set_gain(&usb_mic_hdl->mic_ch, app_var.usb_mic_gain);
|
||||
#else
|
||||
audio_adc_mic1_set_gain(&usb_mic_hdl->mic_ch, FF_MIC1_GAIN);
|
||||
#endif
|
||||
#endif/*(TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_1)*/
|
||||
#if (TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_2)
|
||||
printf("adc_mic2 open\n");
|
||||
audio_adc_mic2_open(&usb_mic_hdl->mic_ch, AUDIO_ADC_MIC_2, &adc_hdl);
|
||||
#ifndef FB_MIC2_GAIN
|
||||
audio_adc_mic2_set_gain(&usb_mic_hdl->mic_ch, app_var.usb_mic_gain);
|
||||
#else
|
||||
audio_adc_mic2_set_gain(&usb_mic_hdl->mic_ch, FB_MIC2_GAIN);
|
||||
#endif
|
||||
#endif/*(TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_2)*/
|
||||
#if (TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_3)
|
||||
printf("adc_mic3 open\n");
|
||||
audio_adc_mic3_open(&usb_mic_hdl->mic_ch, AUDIO_ADC_MIC_3, &adc_hdl);
|
||||
#ifndef OTHER_MIC3_GAIN
|
||||
audio_adc_mic3_set_gain(&usb_mic_hdl->mic_ch, app_var.usb_mic_gain);
|
||||
#else
|
||||
audio_adc_mic3_set_gain(&usb_mic_hdl->mic_ch, OTHER_MIC3_GAIN);
|
||||
#endif
|
||||
#endif/*(TCFG_AUDIO_ADC_MIC_CHA & AUDIO_ADC_MIC_3)*/
|
||||
audio_adc_mic_set_sample_rate(&usb_mic_hdl->mic_ch, sample_rate);
|
||||
audio_adc_mic_set_buffs(&usb_mic_hdl->mic_ch, usb_mic_hdl->adc_buf, USB_MIC_IRQ_POINTS * 2, USB_MIC_BUF_NUM);
|
||||
usb_mic_hdl->adc_output.handler = adc_output_to_cbuf;
|
||||
audio_adc_add_output_handler(&adc_hdl, &usb_mic_hdl->adc_output);
|
||||
audio_adc_mic_start(&usb_mic_hdl->mic_ch);
|
||||
#else
|
||||
audio_mic_open(&usb_mic_hdl->mic_ch, sample_rate, app_var.usb_mic_gain);
|
||||
usb_mic_hdl->adc_output.handler = adc_output_to_cbuf;
|
||||
audio_mic_add_output(&usb_mic_hdl->adc_output);
|
||||
audio_mic_start(&usb_mic_hdl->mic_ch);
|
||||
#endif
|
||||
#endif/*TCFG_AUDIO_ADC_MIC_CHA == PLNK_MIC*/
|
||||
#if TCFG_USB_MIC_ECHO_ENABLE
|
||||
usb_mic_hdl->p_echo_hdl = open_echo(&usbmic_echo_parm_default, &usbmic_echo_fix_parm_default);
|
||||
if (usb_mic_hdl->p_echo_hdl) {
|
||||
update_echo_gain(usb_mic_hdl->p_echo_hdl, usbmic_echo_fix_parm_default.wetgain, usbmic_echo_fix_parm_default.drygain);
|
||||
}
|
||||
#endif
|
||||
#endif//TCFG_USB_MIC_DATA_FROM_MICEFFECT
|
||||
set_uac_mic_tx_handler(NULL, usb_audio_mic_tx_handler);
|
||||
|
||||
/* 需要用时钟管理,防止其他操作降低USB_MIC时钟 */
|
||||
audio_codec_clock_set(AUDIO_USB_MIC_MODE, AUDIO_CODING_PCM, 0);
|
||||
|
||||
usb_mic_hdl->status = USB_MIC_START;
|
||||
/* __this->rec_begin = 0; */
|
||||
return 0;
|
||||
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
u32 usb_mic_is_running()
|
||||
{
|
||||
if (usb_mic_hdl) {
|
||||
return SPK_AUDIO_RATE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*************************************************************
|
||||
*
|
||||
* usb mic gain save
|
||||
*
|
||||
*************************************************************
|
||||
*/
|
||||
static int usb_mic_gain_save_timer;
|
||||
static u8 usb_mic_gain_save_cnt;
|
||||
static void usb_audio_mic_gain_save_do(void *priv)
|
||||
{
|
||||
//printf(" usb_audio_mic_gain_save_do %d\n", usb_mic_gain_save_cnt);
|
||||
local_irq_disable();
|
||||
if (++usb_mic_gain_save_cnt >= 5) {
|
||||
sys_timer_del(usb_mic_gain_save_timer);
|
||||
usb_mic_gain_save_timer = 0;
|
||||
usb_mic_gain_save_cnt = 0;
|
||||
local_irq_enable();
|
||||
printf("USB_GAIN_SAVE\n");
|
||||
syscfg_write(VM_USB_MIC_GAIN, &app_var.usb_mic_gain, 1);
|
||||
return;
|
||||
}
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
static void usb_audio_mic_gain_change(u8 gain)
|
||||
{
|
||||
local_irq_disable();
|
||||
app_var.usb_mic_gain = gain;
|
||||
usb_mic_gain_save_cnt = 0;
|
||||
if (usb_mic_gain_save_timer == 0) {
|
||||
usb_mic_gain_save_timer = sys_timer_add(NULL, usb_audio_mic_gain_save_do, 1000);
|
||||
}
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
int usb_audio_mic_get_gain(void)
|
||||
{
|
||||
return app_var.usb_mic_gain;
|
||||
}
|
||||
|
||||
void usb_audio_mic_set_gain(int gain)
|
||||
{
|
||||
if (usb_mic_hdl == NULL) {
|
||||
r_printf("usb_mic_hdl NULL gain");
|
||||
return;
|
||||
}
|
||||
#ifndef CONFIG_BOARD_AISPEECH_NR_GAIN
|
||||
gain = uac_mic_vol_switch(gain);
|
||||
audio_adc_mic_set_gain(&usb_mic_hdl->mic_ch, gain);
|
||||
usb_audio_mic_gain_change(gain);
|
||||
#else
|
||||
printf("AIS 3MIC set digital gain");
|
||||
usb_mic_hdl->dig_gain = uac_mic_dig_gain_switch(gain);
|
||||
#endif /*CONFIG_BOARD_AISPEECH_NR_GAIN*/
|
||||
}
|
||||
|
||||
float usb_audio_mic_get_dig_gain(void)
|
||||
{
|
||||
if (usb_mic_hdl == NULL) {
|
||||
r_printf("usb_mic_hdl NULL gain");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return usb_mic_hdl->dig_gain;
|
||||
}
|
||||
|
||||
int usb_audio_mic_close(void *arg)
|
||||
{
|
||||
if (usb_mic_hdl == NULL) {
|
||||
r_printf("usb_mic_hdl NULL close");
|
||||
return 0;
|
||||
}
|
||||
printf("usb_mic_hdl->status %x\n", usb_mic_hdl->status);
|
||||
if (usb_mic_hdl && usb_mic_hdl->status == USB_MIC_START) {
|
||||
printf("usb_audio_mic_close in\n");
|
||||
usb_mic_hdl->status = USB_MIC_STOP;
|
||||
#if TCFG_USB_MIC_CVP_ENABLE
|
||||
audio_aec_close();
|
||||
#else
|
||||
task_kill(USB_AUDIO_MIC_WRITE_TASK_NAME);
|
||||
#endif
|
||||
#if (TCFG_USB_MIC_DATA_FROM_MICEFFECT)
|
||||
mic_effect_to_usbmic_onoff(0);
|
||||
#else
|
||||
#if (TCFG_AUDIO_ADC_MIC_CHA == PLNK_MIC)
|
||||
usb_pdm_mic_en(0, 0, 0);
|
||||
#else
|
||||
#if 1
|
||||
audio_adc_mic_close(&usb_mic_hdl->mic_ch);
|
||||
audio_adc_del_output_handler(&adc_hdl, &usb_mic_hdl->adc_output);
|
||||
#else
|
||||
audio_mic_close(&usb_mic_hdl->mic_ch, &usb_mic_hdl->adc_output);
|
||||
#endif
|
||||
audio_mic_pwr_ctl(MIC_PWR_OFF);
|
||||
#endif/*TCFG_AUDIO_ADC_MIC_CHA == PLNK_MIC*/
|
||||
#if TCFG_USB_MIC_ECHO_ENABLE
|
||||
if (usb_mic_hdl->p_echo_hdl) {
|
||||
close_echo(usb_mic_hdl->p_echo_hdl);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if USB_MIC_SRC_ENABLE
|
||||
sw_src_exit();
|
||||
#endif /*USB_MIC_SRC_ENABLE*/
|
||||
cbuf_clear(&usb_mic_hdl->output_cbuf);
|
||||
if (usb_mic_hdl) {
|
||||
|
||||
if (usb_mic_hdl->output_buf) {
|
||||
free(usb_mic_hdl->output_buf);
|
||||
usb_mic_hdl->output_buf = NULL;
|
||||
}
|
||||
free(usb_mic_hdl);
|
||||
usb_mic_hdl = NULL;
|
||||
}
|
||||
#if TCFG_USB_MIC_CVP_ENABLE
|
||||
audio_codec_clock_del(AUDIO_USB_MIC_MODE);
|
||||
#endif /*TCFG_USB_MIC_CVP_ENABLE*/
|
||||
}
|
||||
printf("usb_audio_mic_close out\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_mic_stream_sample_rate(void)
|
||||
{
|
||||
#if USB_MIC_SRC_ENABLE
|
||||
if (usb_mic_src && usb_mic_src->audio_track) {
|
||||
int sr = user_audio_local_sample_track_rate(usb_mic_src->audio_track);
|
||||
if ((sr < (usb_mic_src->out_sample_rate + 50)) && (sr > (usb_mic_src->out_sample_rate - 50))) {
|
||||
return sr;
|
||||
}
|
||||
return usb_mic_src->out_sample_rate;
|
||||
}
|
||||
#endif /*USB_MIC_SRC_ENABLE*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 usb_mic_stream_size()
|
||||
{
|
||||
if (!usb_mic_hdl) {
|
||||
return 0;
|
||||
}
|
||||
if (usb_mic_hdl->status == USB_MIC_START) {
|
||||
if (usb_mic_hdl) {
|
||||
return cbuf_get_data_size(&usb_mic_hdl->output_cbuf);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 usb_mic_stream_length()
|
||||
{
|
||||
return PCM_ENC2USB_OUTBUF_LEN;
|
||||
}
|
||||
|
||||
int usb_output_sample_rate()
|
||||
{
|
||||
int sample_rate = usb_mic_stream_sample_rate();
|
||||
int buf_size = usb_mic_stream_size();
|
||||
|
||||
sample_rate = (u32)(usb_mic_src->in_sample_rate * sample_rate) / usb_mic_src->out_sample_rate;/*统计输出采样率,重新转换成输入采样率调输入*/
|
||||
if (buf_size >= (usb_mic_stream_length() * 1 / 2)) {
|
||||
sample_rate += (sample_rate * 5 / 10000);
|
||||
//putchar('+');
|
||||
}
|
||||
if (buf_size <= (usb_mic_stream_length() / 3)) {
|
||||
sample_rate -= (sample_rate * 5 / 10000);
|
||||
//putchar('-');
|
||||
}
|
||||
|
||||
return sample_rate;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user