KT24-1110_65E-HA-651B/cpu/br25/audio_mic/mic_effect.c

1849 lines
58 KiB
C
Raw Normal View History

2024-11-10 10:44:17 +00:00
#include "audio_splicing.h"
#include "application/audio_bfilt.h"
#include "media/audio_eq_drc_apply.h"
#include "application/audio_echo_src.h"
#include "application/audio_energy_detect.h"
#include "clock_cfg.h"
#include "media/audio_stream.h"
#include "media/includes.h"
#include "mic_effect.h"
#include "asm/dac.h"
#include "audio_enc/audio_enc.h"
#include "audio_dec.h"
#include "stream_entry.h"
#include "effect_linein.h"
#include "audio_recorder_mix.h"
#include "app_task.h"
#include "vollevel_detect.h"
#include "media/effects_adj.h"
#include "audio_effect/audio_eff_default_parm.h"
#include "audio_effect/audio_autotune_demo.h"
#include "media/convert_data.h"
#include "simpleAGC.h"
#define LOG_TAG "[APP-REVERB]"
#define LOG_ERROR_ENABLE
#define LOG_INFO_ENABLE
#define LOG_DUMP_ENABLE
#define LOG_DEBUG_ENABLE
#include "debug.h"
#ifdef SUPPORT_MS_EXTENSIONS
//#pragma bss_seg(".audio_mic_stream_bss")
//#pragma data_seg(".audio_mic_stream_data")
#pragma const_seg(".audio_mic_effect_const")
#pragma code_seg(".audio_mic_effect_code")
#endif
#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE
#define LOUDNESS_DEBUG_ENABLE 0//分贝指示器
// 混响不叠加播U/SD的情况下可以使能否则可能会出现某些高码率歌曲会卡顿的问题
#ifdef CONFIG_BOARD_AC696X_MEGAPHONE
#define ENABLE_BYPASS_CH_AND_EQ2 1//使能bypass ch and EQ2
#else
#define ENABLE_BYPASS_CH_AND_EQ2 0//使能bypass ch and EQ2
#endif
extern struct audio_dac_hdl dac_hdl;
struct aud_reverb_process {
struct audio_stream_entry entry; // 音频流入口
s16 *tmpbuf[3];
void *eff;//struct __mic_effect
s16 *out_buf;
u8 bit_wide;//eq是否输出32bit位宽
u8 in_ch;
u8 divide;//左右声道是否需要独立的gain
};
struct __mic_effect {
OS_MUTEX mutex;
struct __mic_effect_parm parm;
mic_stream *mic;
struct audio_eq *mic_eq0; //eq 句柄
struct audio_drc *mic_drc0; //eq 句柄
struct convert_data *convert0;//32-》16
#if TCFG_EQ_ENABLE && TCFG_MIC_TUNNING_EQ_ENABLE
struct audio_eq *mic_tunning_eq; //eq 句柄
#endif
struct audio_eq *mic_eq4; //eq drc句柄
struct audio_drc *mic_drc4; //eq drc句柄
struct convert_data *convert4;//32-》16
/* struct aud_gain_process *gain;//最后一级 的增益调节 */
struct audio_stream *stream; // 音频流
struct audio_stream_entry entry; // effect 音频入口
int out_len;
int process_len;
u8 input_ch_num; //mic输入给混响数据流的源声道数
NOISEGATE_API_STRUCT *noisegate;
void *d_vol;
HOWLING_API_STRUCT *howling_ps;
HOWLING_API_STRUCT *notch_howling;
voice_changer_hdl *voice_changer;
#if defined(TCFG_MIC_AUTOTUNE_ENABLE) && TCFG_MIC_AUTOTUNE_ENABLE
autotune_hdl *autotune;
#endif
struct channel_switch *channel_zoom;
struct audio_dac_channel *dac;
#if (RECORDER_MIX_EN)
struct __stream_entry *rec_hdl;
#endif
#if (TCFG_USB_MIC_DATA_FROM_MICEFFECT||TCFG_USB_MIC_DATA_FROM_DAC)
struct __stream_entry *usbmic_hdl;
u8 usbmic_start;
#endif
void *energy_hdl; //能量检测的hdl
u8 dodge_en; //能量检测运行过程闪避是否使能
struct __effect_linein *linein;
struct audio_drc *drc;
u8 pause_mark;
LOUDNESS_M_STRUCT loudness_adc;
LOUDNESS_M_STRUCT loudness_drc_out;
struct __stream_entry *loudness_debug_hdl;
struct audio_src_handle *src_hdl;
struct audio_eq *mic_eq3; //eq drc句柄
struct audio_drc *mic_drc3; //eq drc句柄
u8 main_pause;
//分支0节点
PLATE_REVERB_API_STRUCT *sub_0_plate_reverb_hdl;
struct audio_eq *mic_eq1; //eq drc句柄
struct audio_drc *mic_drc1; //eq drc句柄
//分支1节点
ECHO_API_STRUCT *sub_1_echo_hdl;
struct audio_eq *mic_eq2; //eq drc句柄
struct audio_drc *mic_drc2; //eq drc句柄
//分支1 2 3的总处理
struct aud_reverb_process *aud_reverb;
};
struct __mic_stream_parm *g_mic_parm = NULL;
static struct __mic_effect *p_effect = NULL;
#define __this p_effect
#define R_ALIN(var,al) ((((var)+(al)-1)/(al))*(al))
void *mic_tunning_eq_open(u32 sample_rate, u8 ch_num);
void mic_tunning_eq_close(void *eq);
void *mic_eq_open(u32 sample_rate, u8 ch_num, u8 eq_name);
void *mic_drc_open(u32 sample_rate, u8 ch_num, u8 drc_name, u8 _32bit);
void mic_eq_close(void *eq);
void mic_drc_close(void *drc);
void mic_effect_echo_parm_parintf(ECHO_PARM_SET *parm);
void *mic_energy_detect_open(u32 sr, u8 ch_num);
void mic_energy_detect_close(void *hdl);
void mic_voicechange_switch(u8 eff_mode);
s16 *aud_reverb_process_run(struct aud_reverb_process *hdl, s16 *data, int len);
static void audio_reverb_process_output_data_process_len(struct audio_stream_entry *entry, int len)
{
struct aud_reverb_process *hdl = container_of(entry, struct aud_reverb_process, entry);
}
static int audio_reverb_process_data_handler(struct audio_stream_entry *entry,
struct audio_data_frame *in,
struct audio_data_frame *out)
{
struct aud_reverb_process *hdl = container_of(entry, struct aud_reverb_process, entry);
/* if (in->data_len != 304) { */
/* printf("in->data_len %d\n", in->data_len); */
/* } */
out->data_sync = in->data_sync;
struct __mic_effect *eff = hdl->eff;
if (eff->sub_0_plate_reverb_hdl) {
out->channel = 2;//in->channel;
} else {
out->channel = in->channel;
}
out->data_len = out->channel * in->data_len;
hdl->in_ch = in->channel;
out->data = aud_reverb_process_run(hdl, (short *)((int)in->data + in->offset), (in->data_len - in->offset)); //默认输出2ch
if (out->channel == 1) {
pcm_dual_to_single(out->data, out->data, in->data_len * 2);
}
return in->data_len;
}
struct aud_reverb_process *aud_reverb_open(struct __mic_effect *eff, u8 bit_wide)
{
struct aud_reverb_process *hdl = zalloc(sizeof(struct aud_reverb_process));
hdl->eff = eff;
hdl->bit_wide = bit_wide;
hdl->entry.data_process_len = audio_reverb_process_output_data_process_len;
hdl->entry.data_handler = audio_reverb_process_data_handler;
return hdl;
}
void aud_reverb_close(struct aud_reverb_process *hdl)
{
if (!hdl) {
return;
}
local_irq_disable();
audio_stream_del_entry(&hdl->entry);
local_irq_enable();
for (int i = 0; i < 3; i++) {
if (hdl->tmpbuf[i]) {
free(hdl->tmpbuf[i]);
hdl->tmpbuf[i] = NULL;
}
}
free(hdl);
hdl = NULL;
}
void pcm_single_to_dual_32bit(void *out, void *in, u16 len)
{
s32 *outbuf = out;
s32 *inbuf = in;
len >>= 2;
while (len--) {
*outbuf++ = *inbuf;
*outbuf++ = *inbuf;
inbuf++;
}
}
s16 *aud_reverb_process_run(struct aud_reverb_process *hdl, s16 *data, int len)
{
struct __mic_effect *eff = hdl->eff;
u8 ch_num = eff->input_ch_num;
if (eff->sub_0_plate_reverb_hdl) {
//ch0
if (hdl->in_ch == 2) {
if (!hdl->tmpbuf[0]) {
hdl->tmpbuf[0] = malloc(len);//2ch 16 bit buf
}
u8 *tmp = hdl->tmpbuf[0];
pcm_dual_to_single(&tmp[len / 2], data, len);
run_plate_reverb(eff->sub_0_plate_reverb_hdl, &tmp[len / 2], hdl->tmpbuf[0], len / 2); //内部单变双
} else {
if (!hdl->bit_wide) { //16 bit
if (!hdl->tmpbuf[0]) {
hdl->tmpbuf[0] = malloc(len * 2);//2ch 16 bit buf
}
run_plate_reverb(eff->sub_0_plate_reverb_hdl, data, hdl->tmpbuf[0], len); //16bit 内部单变双
audio_dec_eq_run(eff->mic_eq1, hdl->tmpbuf[0], hdl->tmpbuf[0], len * 2);// 16bit 2ch
audio_dec_drc_run(eff->mic_drc1, hdl->tmpbuf[0], len * 2); //16bit 2ch
} else {
if (!hdl->tmpbuf[0]) {
hdl->tmpbuf[0] = malloc(len * 2 * 2);//2ch 32 bit buf
}
u8 *tmp = hdl->tmpbuf[0];
u8 *tar = &tmp[len * 2 * 2 - 2 * len]; //放在最后 16bit 2ch
run_plate_reverb(eff->sub_0_plate_reverb_hdl, data, tar, len); //16 bit 内部单变双
audio_dec_eq_run(eff->mic_eq1, tar, hdl->tmpbuf[0], len * 2);// 32bit 2ch out
audio_dec_drc_run(eff->mic_drc1, hdl->tmpbuf[0], len * 2 * 2); //32bit 2ch
}
}
}
//ch1
u32 points = 0;
if (hdl->in_ch == 1) {
if (!hdl->bit_wide) { //16 bit
u8 *tmp = NULL;
u8 *tar = NULL;
if (eff->sub_1_echo_hdl) {
if (!hdl->tmpbuf[1]) {
hdl->tmpbuf[1] = malloc(len * 2);//2ch 16 bit buf
}
//ch1
tmp = hdl->tmpbuf[1];
tar = &tmp[len];
if ((TCFG_MIC_EFFECT_SEL & MIC_EFFECT_MEGAPHONE)) {
memcpy(tar, data, len);
} else {
run_echo(eff->sub_1_echo_hdl, data, tar, len);
}
audio_dec_eq_run(eff->mic_eq2, tar, NULL, len); //1ch
audio_dec_drc_run(eff->mic_drc2, tar, len); //16bit 1ch
pcm_single_to_dual(hdl->tmpbuf[1], tar, len);//16bit 2ch
}
#if ENABLE_BYPASS_CH_AND_EQ2
if (!hdl->tmpbuf[2]) {
hdl->tmpbuf[2] = malloc(len * 2);//2ch 16 bit buf
}
//ch2
audio_dec_eq_run(eff->mic_eq3, data, NULL, len);//1ch
audio_dec_drc_run(eff->mic_drc3, data, len); //16bit 1ch
pcm_single_to_dual(hdl->tmpbuf[2], data, len);//16bit 2ch
#endif
points = (len * 2) / 2;
} else {
u8 *tmp = NULL;
u8 *tar = NULL;
if (eff->sub_1_echo_hdl) {
if (!hdl->tmpbuf[1]) {
hdl->tmpbuf[1] = malloc(len * 2 * 2); //2ch 32 bit buf
}
//ch1
tmp = hdl->tmpbuf[1];
tar = &tmp[len * 2 * 2 - len]; //放在最后 16bit 1ch
u8 *tar2 = &tmp[len * 2]; //buf中间位置
run_echo(eff->sub_1_echo_hdl, data, tar, len);
audio_dec_eq_run(eff->mic_eq2, tar, tar2, len); //16 ->32 1ch
audio_dec_drc_run(eff->mic_drc2, tar2, len * 2); //32bit 1ch
pcm_single_to_dual_32bit(hdl->tmpbuf[1], tar2, len * 2); //32bit 2ch out
}
//ch2
if (!hdl->tmpbuf[2]) {
hdl->tmpbuf[2] = malloc(len * 2 * 2); //2ch 32 bit buf
}
tmp = hdl->tmpbuf[2];
tar = &tmp[len * 2]; //buf中间位置
audio_dec_eq_run(eff->mic_eq3, data, tar, len);//16->32bit 1ch
audio_dec_drc_run(eff->mic_drc3, tar, len * 2); //32bit 1ch
pcm_single_to_dual_32bit(hdl->tmpbuf[2], tar, len * 2); //32bit 2ch
points = (len * 2 * 2) / 4;
}
} else {
if (!hdl->bit_wide) { //16 bit
u8 *tmp = NULL;
u8 *tar = NULL;
if (eff->sub_1_echo_hdl) {
if (!hdl->tmpbuf[1]) {
hdl->tmpbuf[1] = malloc(len);//2ch 16 bit buf
}
tmp = hdl->tmpbuf[1];
tar = &tmp[len / 2];
pcm_dual_to_single(tar, data, len);
run_echo(eff->sub_1_echo_hdl, tar, tar, len / 2);
pcm_single_to_dual(tmp, tar, len / 2);
audio_dec_eq_run(eff->mic_eq2, tmp, hdl->tmpbuf[1], len); //立体声处理2ch
audio_dec_drc_run(eff->mic_drc2, hdl->tmpbuf[1], len); //16bit 2ch
}
//ch2
if (!hdl->tmpbuf[2]) {
hdl->tmpbuf[2] = malloc(len);//2ch 16bit buf
}
audio_dec_eq_run(eff->mic_eq3, data, hdl->tmpbuf[2], len);
audio_dec_drc_run(eff->mic_drc3, hdl->tmpbuf[2], len); //16bit 2ch
points = len / 2;
} else {
u8 *tmp = NULL;
u8 *tar = NULL;
if (eff->sub_1_echo_hdl) {
if (!hdl->tmpbuf[1]) {
hdl->tmpbuf[1] = malloc(len * 2); //2ch 32 bit buf
}
//ch1
tmp = hdl->tmpbuf[1];
tar = &tmp[len * 2 - len / 2];
pcm_dual_to_single(tar, data, len);
run_echo(eff->sub_1_echo_hdl, tar, tar, len / 2);
pcm_single_to_dual(tmp, tar, len / 2);
audio_dec_eq_run(eff->mic_eq2, tmp, hdl->tmpbuf[1], len); //立体声处理2ch
audio_dec_drc_run(eff->mic_drc2, hdl->tmpbuf[1], len * 2); //32bit 2ch
}
//ch2
if (!hdl->tmpbuf[2]) {
hdl->tmpbuf[2] = malloc(len * 2 * 2); //2ch 32 bit buf
}
audio_dec_eq_run(eff->mic_eq3, data, hdl->tmpbuf[2], len);
audio_dec_drc_run(eff->mic_drc3, hdl->tmpbuf[2], len * 2); //32bit 2ch
points = (len * 2) / 4;
}
}
MixParam mix0 = {0};
MixParam mix1 = {0};
MixParam mix2 = {0};
u8 mode = get_mic_eff_mode();
Mix_TOOL_SET *mix_gain = &eff_mode[mode].mix_gain;
mix0.data = hdl->tmpbuf[0];
mix0.gain = mix_gain->gain1;
mix1.data = hdl->tmpbuf[1];
mix1.gain = mix_gain->gain2;
mix2.data = hdl->tmpbuf[2];
mix2.gain = mix_gain->gain3;
u8 out_ch_num = 2;
if (!hdl->bit_wide) { //16 bit
if (eff->sub_1_echo_hdl && eff->sub_0_plate_reverb_hdl) {
Mix16to16(&mix0, &mix1, &mix2, hdl->tmpbuf[0], out_ch_num, 3, points / out_ch_num);
} else if (eff->sub_0_plate_reverb_hdl) {
Mix16to16(&mix0, &mix2, NULL, hdl->tmpbuf[0], out_ch_num, 2, points / out_ch_num);
} else {
#if ENABLE_BYPASS_CH_AND_EQ2
Mix16to16(&mix1, &mix2, NULL, hdl->tmpbuf[1], out_ch_num, 2, points / out_ch_num);
#endif
return hdl->tmpbuf[1];
}
return hdl->tmpbuf[0];
} else {
if (eff->sub_1_echo_hdl && eff->sub_0_plate_reverb_hdl) {
Mix32to16(&mix0, &mix1, &mix2, hdl->tmpbuf[0], out_ch_num, 3, points / out_ch_num);
} else if (eff->sub_0_plate_reverb_hdl) {
Mix32to16(&mix0, &mix2, NULL, hdl->tmpbuf[0], out_ch_num, 2, points / out_ch_num);
} else {
Mix32to16(&mix1, &mix2, NULL, hdl->tmpbuf[1], out_ch_num, 2, points / out_ch_num);
return hdl->tmpbuf[1];
}
}
return hdl->tmpbuf[0];
}
/*----------------------------------------------------------------------------*/
/**@brief mic数据流串接入口
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
static u32 mic_effect_effect_run(void *priv, void *in, void *out, u32 inlen, u32 outlen)
{
struct __mic_effect *effect = (struct __mic_effect *)priv;
if (effect == NULL) {
return 0;
}
struct audio_data_frame frame = {0};
frame.channel = effect->input_ch_num;
frame.sample_rate = effect->parm.sample_rate;
frame.data_len = inlen;
frame.data = in;
effect->out_len = 0;
effect->process_len = inlen;
if (effect->pause_mark) {
memset(in, 0, inlen);
return inlen;
} else {
}
#if LOUDNESS_DEBUG_ENABLE
loudness_meter_short(&effect->loudness_adc, in, inlen / 2);
#endif
while (1) {
audio_stream_run(&effect->entry, &frame);
if (effect->out_len >= effect->process_len) {
break;
}
frame.data = (s16 *)((u8 *)in + effect->out_len);
frame.data_len = inlen - effect->out_len;
}
return outlen;
}
/*----------------------------------------------------------------------------*/
/**@brief 释放mic数据流资源
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void mic_effect_destroy(struct __mic_effect **hdl)
{
if (hdl == NULL || *hdl == NULL) {
return ;
}
struct __mic_effect *effect = *hdl;
if (effect->mic) {
log_i("mic_stream_destroy\n\n\n");
mic_stream_destroy(&effect->mic);
}
#if TCFG_MIC_DODGE_EN
if (effect->energy_hdl) {
mic_energy_detect_close(effect->energy_hdl);
}
#endif
if (effect->noisegate) {
log_i("close_noisegate\n\n\n");
audio_noisegate_close(effect->noisegate);
}
if (effect->howling_ps) {
log_i("close_howling\n\n\n");
close_howling(effect->howling_ps);
}
if (effect->notch_howling) {
log_i("close_howling\n\n\n");
close_howling(effect->notch_howling);
}
#if defined(TCFG_MIC_VOICE_CHANGER_ENABLE) && TCFG_MIC_VOICE_CHANGER_ENABLE
if (effect->voice_changer) {
audio_voice_changer_close_demo(effect->voice_changer);
}
#endif
#if defined(TCFG_MIC_AUTOTUNE_ENABLE) && TCFG_MIC_AUTOTUNE_ENABLE
if (effect->autotune) {
audio_autotune_close_demo(effect->autotune);
}
#endif
#if TCFG_EQ_ENABLE && TCFG_MIC_TUNNING_EQ_ENABLE
if (effect->mic_tunning_eq) {
mic_tunning_eq_close(effect->mic_tunning_eq);
}
#endif
if (effect->mic_eq0) {
log_i("mic_eq0_close\n\n\n");
mic_eq_close(effect->mic_eq0);
}
if (effect->mic_drc0) {
log_i("mic_drc0_close\n\n\n");
mic_drc_close(effect->mic_drc0);
}
if (effect->convert0) {
log_i("convet0_data_close\n\n\n");
convet_data_close(effect->convert0);
}
if (effect->mic_eq1) {
log_i("mic_eq1_close\n\n\n");
mic_eq_close(effect->mic_eq1);
}
if (effect->mic_drc1) {
log_i("mic_drc1_close\n\n\n");
mic_drc_close(effect->mic_drc1);
}
if (effect->mic_eq2) {
log_i("mic_eq2_close\n\n\n");
mic_eq_close(effect->mic_eq2);
}
if (effect->mic_drc2) {
log_i("mic_drc2_close\n\n\n");
mic_drc_close(effect->mic_drc2);
}
if (effect->mic_eq3) {
log_i("mic_eq3_close\n\n\n");
mic_eq_close(effect->mic_eq3);
}
if (effect->mic_drc3) {
log_i("mic_drc3_close\n\n\n");
mic_drc_close(effect->mic_drc3);
}
if (effect->mic_eq4) {
log_i("mic_eq4_close\n\n\n");
mic_eq_close(effect->mic_eq4);
}
if (effect->mic_drc4) {
log_i("mic_drc4_close\n\n\n");
mic_drc_close(effect->mic_drc4);
}
if (effect->convert4) {
log_i("convet4_data_close\n\n\n");
convet_data_close(effect->convert4);
}
/* if (effect->gain) { */
/* log_i("audio_gain_close_demo\n\n\n"); */
/* audio_gain_close_demo(effect->gain); */
/* effect->gain = NULL; */
/* } */
if (effect->sub_1_echo_hdl) {
close_echo(effect->sub_1_echo_hdl);
}
if (effect->sub_0_plate_reverb_hdl) {
close_plate_reverb(effect->sub_0_plate_reverb_hdl);
}
if (effect->d_vol) {
audio_stream_del_entry(audio_dig_vol_entry_get(effect->d_vol));
#if SYS_DIGVOL_GROUP_EN
sys_digvol_group_ch_close("mic_mic");
#else
audio_dig_vol_close(effect->d_vol);
#endif/*SYS_DIGVOL_GROUP_EN*/
}
/* if (effect->linein) { */
/* effect_linein_close(&effect->linein); */
/* } */
if (effect->src_hdl) {
audio_stream_del_entry(&effect->src_hdl->entry);
audio_hw_src_stop(effect->src_hdl);
audio_hw_src_close(effect->src_hdl);
free(effect->src_hdl);
effect->src_hdl = NULL;
}
if (effect->channel_zoom) {
channel_switch_close(&effect->channel_zoom);
/*effect->channel_zoom = NULL;*/
}
if (effect->loudness_debug_hdl) {
stream_entry_close(&effect->loudness_debug_hdl);
}
if (effect->dac) {
audio_stream_del_entry(&effect->dac->entry);
audio_dac_free_channel(effect->dac);
free(effect->dac);
effect->dac = NULL;
}
#if (RECORDER_MIX_EN)
if (effect->rec_hdl) {
stream_entry_close(&effect->rec_hdl);
}
#endif
#if (TCFG_USB_MIC_DATA_FROM_MICEFFECT||TCFG_USB_MIC_DATA_FROM_DAC)
if (effect->usbmic_hdl) {
stream_entry_close(&effect->usbmic_hdl);
}
#endif
if (effect->aud_reverb) {
aud_reverb_close(effect->aud_reverb);
}
if (effect->stream) {
audio_stream_close(effect->stream);
}
local_irq_disable();
free(effect);
*hdl = NULL;
local_irq_enable();
mem_stats();
clock_remove_set(REVERB_CLK);
}
/*----------------------------------------------------------------------------*/
/**@brief 串流唤醒
@param
@return
@note 使
*/
/*----------------------------------------------------------------------------*/
static void mic_stream_resume(void *p)
{
struct __mic_effect *effect = (struct __mic_effect *)p;
/* audio_decoder_resume_all(&decode_task); */
}
/*----------------------------------------------------------------------------*/
/**@brief 串流数据处理长度回调
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void mic_effect_data_process_len(struct audio_stream_entry *entry, int len)
{
struct __mic_effect *effect = container_of(entry, struct __mic_effect, entry);
effect->out_len += len;
/* printf("out len[%d]",effect->out_len); */
}
static int mic_effect_record_stream_callback(void *priv, struct audio_data_frame *in)
{
struct __mic_effect *effect = (struct __mic_effect *)priv;
s16 *data = in->data;
u32 len = in->data_len;
return recorder_mix_pcm_write((u8 *)data, len);
}
extern int usb_audio_mic_write_do(void *data, u16 len);
static int mic_effect_otherout_stream_callback(void *priv, struct audio_data_frame *in)
{
struct __mic_effect *effect = (struct __mic_effect *)priv;
s16 *data = in->data;
u32 len = in->data_len;
#if ((TCFG_USB_MIC_DATA_FROM_MICEFFECT||TCFG_USB_MIC_DATA_FROM_DAC))
if (effect->usbmic_start) {
if (len) {
usb_audio_mic_write_do(data, len);
}
} else {
}
#endif
return len;
}
void mic_effect_to_usbmic_onoff(u8 mark)
{
#if (TCFG_USB_MIC_DATA_FROM_MICEFFECT||TCFG_USB_MIC_DATA_FROM_DAC)
if (__this) {
__this->usbmic_start = mark ? 1 : 0;
}
#endif
}
static void inline rl_rr_mix_to_rl_rr(short *data, int len)
{
s32 tmp32_1;
s32 tmp32_2;
s16 *inbuf = data;
inbuf = inbuf + 2; //定位到第三通道
len >>= 3;
__asm__ volatile(
"1: \n\t"
"rep %0 { \n\t"
" %2 = h[%1 ++= 2](s) \n\t" //取第三通道值,并地址偏移两个字节指向第四通道数据
" %3 = h[%1 ++= -2](s) \n\t" //取第四通道值,并地址偏移两个字节指向第三通道数据
" %2 = %2 + %3 \n\t"
" %2 = sat16(%2)(s) \n\t" //饱和处理
" h[%1 ++= 2] = %2 \n\t" //存取第三通道数据,并地址偏移两个字节指向第四通道数据
" h[%1 ++= 6] = %2 \n\t" //存取第四通道数据,并地址偏移六个字节指向第三通道相邻的数据
"} \n\t"
"if(%0 != 0) goto 1b \n\t"
:
"=&r"(len),
"=&r"(inbuf),
"=&r"(tmp32_1),
"=&r"(tmp32_2)
:
"0"(len),
"1"(inbuf),
"2"(tmp32_1),
"3"(tmp32_2)
:
);
}
static int effect_to_dac_data_pro_handle(struct audio_stream_entry *entry, struct audio_data_frame *in)
{
#if (SOUNDCARD_ENABLE)
if (in->data_len == 0) {
return 0;
}
#if 1
rl_rr_mix_to_rl_rr(in->data, in->data_len);//汇编加速
#else
s16 *outbuf = in->data;
s16 *inbuf = in->data;
s32 tmp32;
u16 len = in->data_len;
len >>= 3;
while (len--) {
*outbuf++ = inbuf[0];
*outbuf++ = inbuf[1];
tmp32 = (inbuf[2] + inbuf[3]);
if (tmp32 < -32768) {
tmp32 = -32768;
} else if (tmp32 > 32767) {
tmp32 = 32767;
}
*outbuf++ = tmp32;
*outbuf++ = tmp32;
inbuf += 4;
}
#endif
#endif
return 0;
}
#if TCFG_APP_RECORD_EN
static int prob_handler_to_record(struct audio_stream_entry *entry, struct audio_data_frame *in)
{
if (app_get_curr_task() != APP_RECORD_TASK) {
return 0;
}
if (in->data_len == 0) {
return 0;
}
if (recorder_is_encoding() == 0) {
return 0;
}
int wlen = recorder_userdata_to_enc(in->data, in->data_len);
if (wlen != in->data_len) {
putchar('N');
}
return 0;
}
#endif
int audio_data_check_cb(struct audio_stream_entry *entry, struct audio_data_frame *data_buf)
{
if (__this) {
loudness_meter_short(&__this->loudness_drc_out, data_buf->data, data_buf->data_len / 2);
}
return data_buf->data_len;
}
#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR || TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)
#define DAC_OUTPUT_CHANNELS 2
#elif (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_MONO_R || TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_MONO_R || TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_MONO_LR_DIFF)
#define DAC_OUTPUT_CHANNELS 1
#elif (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR)
#define DAC_OUTPUT_CHANNELS 4
#else
#define DAC_OUTPUT_CHANNELS 3
#endif
static u8 reverb_mode = 0;
static u8 voicechange_mode = 0;
void switch_mic_effect_mode(void)
{
reverb_mode++;
if (reverb_mode > 2) {
reverb_mode = 0;
}
printf("\n--func=%s [%d] \n", __FUNCTION__, reverb_mode);
set_mic_reverb_mode_by_id(reverb_mode);
}
/*----------------------------------------------------------------------------*/
/**@brief (mic数据流)混响打开接口
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
bool mic_effect_start(void)
{
bool ret = false;
mem_stats();
printf("\n--func=%s\n", __FUNCTION__);
if (__this) {
log_e("reverb is already start \n");
return ret;
}
struct __mic_effect *effect = (struct __mic_effect *)zalloc(sizeof(struct __mic_effect));
if (effect == NULL) {
return false;
}
u8 mode = get_mic_eff_mode();
struct eff_parm *mic_eff = &eff_mode[mode];
clock_add_set(REVERB_CLK);
os_mutex_create(&effect->mutex);
memcpy(&effect->parm, &effect_parm_default, sizeof(struct __mic_effect_parm));
struct __mic_stream_parm *mic_parm = (struct __mic_stream_parm *)&effect_mic_stream_parm_default;
if (g_mic_parm) {
mic_parm = g_mic_parm;
}
#if LOUDNESS_DEBUG_ENABLE
loudness_meter_init(&effect->loudness_adc, effect_mic_stream_parm_default.sample_rate, 50, 1);
loudness_meter_init(&effect->loudness_drc_out, effect_mic_stream_parm_default.sample_rate, 50, 2);
effect->loudness_debug_hdl = stream_entry_open(effect, audio_data_check_cb, 0);// 能量计算及打印节点
#endif
if ((TCFG_MIC_EFFECT_SEL & MIC_EFFECT_ECHO)
&& (TCFG_MIC_EFFECT_SEL & MIC_EFFECT_REVERB)) {
log_e("effect config err ?? !!!, cann't support echo && reverb at the same time\n");
mic_effect_destroy(&effect);
return false;
}
u16 irq_points = mic_parm->point_unit;
u8 ch_num = 1; //??
effect->input_ch_num = ch_num;
#if TCFG_MIC_DODGE_EN
if (effect->parm.effect_config & BIT(MIC_EFFECT_CONFIG_ENERGY_DETECT)) {
effect->energy_hdl = mic_energy_detect_open(effect->parm.sample_rate, ch_num);
effect->dodge_en = 0;//默认关闭, 需要通过按键触发打开
}
#endif
///声音门限初始化
if (effect->parm.effect_config & BIT(MIC_EFFECT_CONFIG_NOISEGATE)) {
effect->noisegate = audio_noisegate_open_demo(AEID_MIC_NS_GATE, MIC_EFFECT_SAMPLERATE, ch_num);
}
///啸叫抑制初始化
if (effect->parm.effect_config & BIT(MIC_EFFECT_CONFIG_HOWLING)) {
log_i("open_howling\n\n\n");
effect->howling_ps = open_howling(NULL, effect->parm.sample_rate, 0, 1);//以频
}
if (effect->parm.effect_config & BIT(MIC_EFFECT_CONFIG_HOWLING_TRAP)) {
log_i("open_howling\n\n\n");
HOWLING_PARM_SET howling_param = {
.threshold = mic_eff->notchhowling_parm.parm.threshold,
.fade_time = mic_eff->notchhowling_parm.parm.fade_n,
.notch_Q = mic_eff->notchhowling_parm.parm.Q,
.notch_gain = mic_eff->notchhowling_parm.parm.gain,
.sample_rate = MIC_EFFECT_SAMPLERATE,
.channel = 1,
};
#if (TCFG_USER_TWS_ENABLE == 0)
effect->notch_howling = open_howling(&howling_param, effect->parm.sample_rate, 0, 0);//陷波
#endif
}
#if defined(TCFG_MIC_VOICE_CHANGER_ENABLE) && TCFG_MIC_VOICE_CHANGER_ENABLE
effect->voice_changer = audio_voice_changer_open_demo(AEID_MIC_VOICE_CHANGER, effect->parm.sample_rate);
#endif
#if defined(TCFG_MIC_AUTOTUNE_ENABLE) && TCFG_MIC_AUTOTUNE_ENABLE
effect->autotune = audio_autotune_open_demo(AEID_MIC_AUTOTUNE, effect->parm.sample_rate);
#endif
log_i("effect->parm.sample_rate %d\n", effect->parm.sample_rate);
#if TCFG_EQ_ENABLE && TCFG_MIC_TUNNING_EQ_ENABLE
effect->mic_tunning_eq = mic_tunning_eq_open(effect->parm.sample_rate, ch_num);
#endif
if (effect->parm.effect_config & BIT(MIC_EFFECT_CONFIG_EQ0)) {
effect->mic_eq0 = mic_eq_open(effect->parm.sample_rate, ch_num, AEID_MIC_EQ0);
if (effect->mic_eq0 && effect->mic_eq0->out_32bit) {
effect->mic_drc0 = mic_drc_open(effect->parm.sample_rate, ch_num, AEID_MIC_DRC0, 1);
effect->convert0 = convet_data_open(0, (irq_points << 1) * ch_num);
} else {
#if ENABLE_BYPASS_CH_AND_EQ2
effect->mic_drc0 = mic_drc_open(effect->parm.sample_rate, ch_num, AEID_MIC_DRC0, 0);
#endif
}
}
#if ENABLE_BYPASS_CH_AND_EQ2
effect->mic_eq3 = mic_eq_open(effect->parm.sample_rate, ch_num, AEID_MIC_EQ3);
#endif
if (effect->mic_eq3 && effect->mic_eq3->out_32bit) {
effect->mic_drc3 = mic_drc_open(effect->parm.sample_rate, ch_num, AEID_MIC_DRC3, 1);
}
// sub 0 分流节点
if ((TCFG_MIC_EFFECT_SEL & MIC_EFFECT_ECHO) || (TCFG_MIC_EFFECT_SEL & MIC_EFFECT_MEGAPHONE)) {
effect->sub_1_echo_hdl = open_echo((ECHO_PARM_SET *)&mic_eff->echo_parm.parm, (EF_REVERB_FIX_PARM *)&effect_echo_fix_parm_default);
if (effect->sub_1_echo_hdl) {
#if ENABLE_BYPASS_CH_AND_EQ2
effect->mic_eq2 = mic_eq_open(effect->parm.sample_rate, ch_num, AEID_MIC_EQ2);
#endif
if (effect->mic_eq2 && effect->mic_eq2->out_32bit) {
effect->mic_drc2 = mic_drc_open(effect->parm.sample_rate, ch_num, AEID_MIC_DRC2, 1);
}
}
}
if (TCFG_MIC_EFFECT_SEL & MIC_EFFECT_REVERB) {
effect->sub_0_plate_reverb_hdl = open_plate_reverb((Plate_reverb_parm *)&mic_eff->plate_reverb_parm.parm, effect->parm.sample_rate);
if (effect->sub_0_plate_reverb_hdl) {
ch_num = 2;
}
effect->mic_eq1 = mic_eq_open(effect->parm.sample_rate, ch_num, AEID_MIC_EQ1);
if (effect->mic_eq1 && effect->mic_eq1->out_32bit) {
effect->mic_drc1 = mic_drc_open(effect->parm.sample_rate, ch_num, AEID_MIC_DRC1, 1);
}
}
//多路混合后 EQ drc
#if TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE
effect->mic_eq4 = mic_eq_open(effect->parm.sample_rate, ch_num, AEID_MIC_EQ4);
if (effect->mic_eq4 && effect->mic_eq4->out_32bit) {
effect->mic_drc4 = mic_drc_open(effect->parm.sample_rate, ch_num, AEID_MIC_DRC4, 1);
effect->convert4 = convet_data_open(0, (irq_points << 1) * ch_num);
}
#endif/*TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE*/
/* effect->gain = audio_gain_open_demo(AEID_MIC_GAIN, ch_num); */
///初始化数字音量
struct audio_stream_entry *dvol_entry;
if (effect->parm.effect_config & BIT(MIC_EFFECT_CONFIG_DVOL)) {
effect_dvol_default_parm.ch_total = ch_num;
#if SYS_DIGVOL_GROUP_EN
dvol_entry = sys_digvol_group_ch_open("mic_mic", -1, &effect_dvol_default_parm);
effect->d_vol = audio_dig_vol_group_hdl_get(sys_digvol_group, "mic_mic");
#else
effect->d_vol = audio_dig_vol_open((audio_dig_vol_param *)&effect_dvol_default_parm);
dvol_entry = audio_dig_vol_entry_get(effect->d_vol);
#endif /*SYS_DIGVOL_GROUP_EN*/
}
//打开混响变采样
if (effect->parm.effect_config & BIT(MIC_EFFECT_CONFIG_SOFT_SRC)) {
u32 out_sr = audio_output_nor_rate();
effect->src_hdl = zalloc(sizeof(struct audio_src_handle));
audio_hw_src_open(effect->src_hdl, ch_num, SRC_TYPE_RESAMPLE);
audio_hw_src_set_rate(effect->src_hdl, effect->parm.sample_rate, out_sr);
}
//混响通路混合linein
/* if (effect->parm.effect_config & BIT(MIC_EFFECT_CONFIG_LINEIN)) { */
/* effect->linein = effect_linein_open(); */
/* } */
u8 output_channels = DAC_OUTPUT_CHANNELS;
if (output_channels != ch_num) {
u32 points_num = REVERB_LADC_IRQ_POINTS * 4;
effect->channel_zoom = channel_switch_open(output_channels == 2 ? AUDIO_CH_LR : (output_channels == 4 ? AUDIO_CH_QUAD : AUDIO_CH_DIFF), output_channels == 4 ? (points_num * 2 + 128) : 1024);
//effect->channel_zoom = channel_switch_open(AUDIO_CH_LR, 1024);
}
effect->dac = (struct audio_dac_channel *)zalloc(sizeof(struct audio_dac_channel));
if (effect->dac) {
audio_dac_new_channel(&dac_hdl, effect->dac);
struct audio_dac_channel_attr attr;
audio_dac_channel_get_attr(effect->dac, &attr);
attr.delay_time = mic_parm->dac_delay;
attr.write_mode = WRITE_MODE_FORCE;
audio_dac_channel_set_attr(effect->dac, &attr);
effect->dac->entry.prob_handler = effect_to_dac_data_pro_handle;
/* audio_dac_channel_set_pause(effect->dac,1); */
}
effect->entry.data_process_len = mic_effect_data_process_len;
#if (RECORDER_MIX_EN)
///送录音数据流
effect->rec_hdl = stream_entry_open(effect, mic_effect_record_stream_callback, 1);
#endif
#if (TCFG_USB_MIC_DATA_FROM_MICEFFECT||TCFG_USB_MIC_DATA_FROM_DAC)
effect->usbmic_hdl = stream_entry_open(effect, mic_effect_otherout_stream_callback, 1);
#endif
u8 bit_wide = 0;
if (effect->mic_eq1 && effect->mic_eq1->out_32bit) {
bit_wide = 1;
}
effect->aud_reverb = aud_reverb_open(effect, bit_wide);
// 数据流串联
struct audio_stream_entry *entries[25] = {NULL};
u8 entry_cnt = 0;
entries[entry_cnt++] = &effect->entry;
#if TCFG_MIC_DODGE_EN
if (effect->energy_hdl) {
entries[entry_cnt++] = audio_energy_detect_entry_get(effect->energy_hdl);
}
#endif
if (effect->noisegate) {
entries[entry_cnt++] = &effect->noisegate->entry;
}
#if TCFG_EQ_ENABLE && TCFG_MIC_TUNNING_EQ_ENABLE
if (effect->mic_tunning_eq) {
entries[entry_cnt++] = &effect->mic_tunning_eq->entry;
}
#endif
if (effect->mic_eq0) {
entries[entry_cnt++] = &effect->mic_eq0->entry;
}
if (effect->mic_drc0) {
entries[entry_cnt++] = &effect->mic_drc0->entry;
}
if (effect->mic_eq0 && effect->mic_eq0->out_32bit) {
if (effect->convert0) {
entries[entry_cnt++] = &effect->convert0->entry;
}
}
if (effect->howling_ps) {
entries[entry_cnt++] = &effect->howling_ps->entry;
}
if (effect->notch_howling) {
entries[entry_cnt++] = &effect->notch_howling->entry;
}
if (effect->voice_changer) {
entries[entry_cnt++] = &effect->voice_changer->entry;
}
#if defined(TCFG_MIC_AUTOTUNE_ENABLE) && TCFG_MIC_AUTOTUNE_ENABLE
if (effect->autotune) {
entries[entry_cnt++] = &effect->autotune->entry;
}
#endif
if (effect->aud_reverb) {
entries[entry_cnt++] = &effect->aud_reverb->entry;
}
if (effect->d_vol) {
entries[entry_cnt++] = dvol_entry;
}
if (effect->mic_eq4) {
entries[entry_cnt++] = &effect->mic_eq4->entry;
if (effect->mic_eq4->out_32bit) {
if (effect->mic_drc4) {
entries[entry_cnt++] = &effect->mic_drc4->entry;
}
if (effect->convert4) {
entries[entry_cnt++] = &effect->convert4->entry;
}
}
}
/* if (effect->gain) { */
/* entries[entry_cnt++] = &effect->gain->entry; */
/* } */
if (effect->loudness_debug_hdl) {
entries[entry_cnt++] = &effect->loudness_debug_hdl->entry;
}
if (effect->channel_zoom) {
entries[entry_cnt++] = &effect->channel_zoom->entry;
}
if (effect->dac) {
entries[entry_cnt++] = &effect->dac->entry;
#if (TCFG_USB_MIC_DATA_FROM_DAC)
if (effect->usbmic_hdl) {
entries[entry_cnt++] = &effect->usbmic_hdl->entry;
}
#endif
}
effect->stream = audio_stream_open(effect, mic_stream_resume);
audio_stream_add_list(effect->stream, entries, entry_cnt);
/* effect->main_pause = 2; */
///mic 数据流初始化
effect->mic = mic_stream_creat(mic_parm);
if (effect->mic == NULL) {
mic_effect_destroy(&effect);
return false;
}
mic_stream_set_output(effect->mic, (void *)effect, mic_effect_effect_run);
mic_stream_start(effect->mic);
#if (RECORDER_MIX_EN)
recorder_mix_pcm_stream_open(effect->parm.sample_rate, ch_num);
#endif
clock_set_cur();
__this = effect;
log_info("--------------------------effect start ok\n");
mem_stats();
mic_effect_change_mode(mode);
return true;
}
/*----------------------------------------------------------------------------*/
/**@brief mic增益调节
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
/* void mic_effect_mic_gain_parm_fill(EFFECTS_MIC_GAIN_PARM *parm, u8 fade, u8 online) */
/* { */
/* if (__this == NULL || parm == NULL) { */
/* return ; */
/* } */
/* audio_mic_set_gain(parm->gain); */
/* } */
/*----------------------------------------------------------------------------*/
/**@brief mic效果模式切换数据流音效组合切换
@param
@return
@note 使
*/
/*----------------------------------------------------------------------------*/
void mic_effect_change_mode(u16 mode)
{
set_mic_reverb_mode_by_id(mode);
}
/*----------------------------------------------------------------------------*/
/**@brief 获取mic效果模式数据流音效组合
@param
@return
@note 使
*/
/*----------------------------------------------------------------------------*/
u16 mic_effect_get_cur_mode(void)
{
return get_mic_eff_mode();
}
void *mic_eq_open(u32 sample_rate, u8 ch_num, u8 eq_name)
{
#if TCFG_EQ_ENABLE
#if(TCFG_MIC_EFFECT_SEL == MIC_EFFECT_MEGAPHONE)
if ((eq_name == AEID_MIC_EQ1)) {
return NULL;
}
#endif
u8 mode = get_mic_eff_mode();
struct audio_eq_param parm = {0};
parm.channels = ch_num;
if ((eq_name == AEID_MIC_EQ0) || (eq_name == AEID_MIC_EQ4)) {
/* parm.out_32bit = 1;//32bit位宽输出 */ //696默认使用16bitEQ
}
parm.no_wait = 0;//同步方式
parm.cb = eq_get_filter_info;
parm.sr = sample_rate;
parm.eq_name = eq_name;
u8 index = get_eq_module_index(eq_name);
log_d("index %d\n", index);
parm.max_nsection = eff_mode[mode].eq_parm[index].seg_num;
parm.nsection = eff_mode[mode].eq_parm[index].seg_num;
parm.seg = eff_mode[mode].eq_parm[index].seg;
parm.global_gain = eff_mode[mode].eq_parm[index].global_gain;
log_d("=====mic eq_name %d\n", eq_name);
struct audio_eq *eq = audio_dec_eq_open(&parm);
return eq;
#else
return NULL;
#endif//TCFG_EQ_ENABLE
}
void *mic_drc_open(u32 sample_rate, u8 ch_num, u8 drc_name, u8 _32bit)
{
#if TCFG_DRC_ENABLE
u8 mode = get_mic_eff_mode();
log_i("sample_rate %d %d\n", sample_rate, ch_num);
struct audio_drc_param parm = {0};
parm.channels = ch_num;
parm.sr = sample_rate;
parm.out_32bit = _32bit;
parm.cb = drc_get_filter_info;
parm.drc_name = drc_name;
u8 index = get_drc_module_index(drc_name);
parm.wdrc = &eff_mode[mode].drc_parm[index];
log_d("=====drc_name %d\n", drc_name);
struct audio_drc *drc = audio_dec_drc_open(&parm);
clock_add(EQ_CLK);
return drc;
#else
return NULL;
#endif//TCFG_DRC_ENABLE
}
void mic_eq_close(void *eq)
{
#if TCFG_EQ_ENABLE
if (eq) {
audio_dec_eq_close(eq);
clock_remove(EQ_CLK);
}
#endif
return;
}
void mic_drc_close(void *drc)
{
#if TCFG_DRC_ENABLE
if (drc) {
audio_dec_drc_close(drc);
drc = NULL;
clock_remove(EQ_CLK);
}
#endif
return;
}
#if TCFG_EQ_ENABLE && TCFG_MIC_TUNNING_EQ_ENABLE
struct eq_seg_info mic_high_bass_eq_seg[] = {
{0, EQ_IIR_TYPE_BAND_PASS, 100, 0, 0.7f},
{1, EQ_IIR_TYPE_BAND_PASS, 1000, 0, 0.7f},
};
struct eq_tool mic_tunning_eq_parm = {0};
/*
*mic tunning_eq
* */
void *mic_tunning_eq_open(u32 sample_rate, u8 ch_num)
{
u8 seg_num = ARRAY_SIZE(mic_high_bass_eq_seg);
mic_tunning_eq_parm.seg_num = seg_num;
mic_tunning_eq_parm.global_gain = 0;
memcpy(&mic_tunning_eq_parm.seg, mic_high_bass_eq_seg, sizeof(mic_high_bass_eq_seg));
struct audio_eq_param parm = {0};
parm.channels = ch_num;
parm.cb = eq_get_filter_info;
parm.sr = sample_rate;
parm.eq_name = AEID_MIC_TUNNING_EQ;
parm.max_nsection = mic_tunning_eq_parm.seg_num;
parm.nsection = mic_tunning_eq_parm.seg_num;
parm.seg = mic_tunning_eq_parm.seg;
parm.global_gain = mic_tunning_eq_parm.global_gain;
parm.fade = 1;//高低音增益更新差异大,会引入哒哒音,此处使能系数淡入
parm.fade_step = 0.4f;//淡入步进0.1f~1.0f
log_d("=====mic tunning eq_name %d\n", parm.eq_name);
struct audio_eq *eq = audio_dec_eq_open(&parm);
return eq;
}
/*
*mic tunning_eq
* */
void mic_tunning_eq_close(void *eq)
{
if (eq) {
audio_dec_eq_close(eq);
}
}
/*
*index:0 low, 1 high
*gain:-12~0dB
* */
void mic_tunning_eq_update(u8 index, float gain)
{
if (gain > 0) {
gain = 0;
} else if (gain < -12) {
gain = -12;
}
mic_tunning_eq_parm.seg[index].gain = gain;
/* log_d("mic tunning eq index %d, %d\n", index, (int)gain); */
struct audio_eq *hdl = get_cur_eq_hdl_by_name(AEID_MIC_TUNNING_EQ);
if (hdl) {
cur_eq_set_update(AEID_MIC_TUNNING_EQ, &mic_tunning_eq_parm.seg[index], mic_tunning_eq_parm.seg_num, 1);
}
}
/*
*
*/
void mic_tunning_eq_update_parm(u8 mode)
{
#if 0
u8 seg_num = ARRAY_SIZE(mic_high_bass_eq_seg);
struct audio_eq *hdl = get_cur_eq_hdl_by_name(AEID_MIC_TUNNING_EQ);
for (int i = 0; i < seg_num; i++) {
if (hdl) {
cur_eq_set_update(AEID_MIC_TUNNING_EQ, &mic_tunning_eq_parm.seg[i], mic_tunning_eq_parm.seg_num, 1);
}
}
#endif
}
#endif/*TCFG_EQ_ENABLE && TCFG_MIC_TUNNING_EQ_ENABLE*/
#if TCFG_MIC_DODGE_EN
void mic_e_det_handler(u8 event, u8 ch)
{
//printf(">>>> ch:%d %s\n", ch, event ? ("MUTE") : ("UNMUTE"));
struct __mic_effect *effect = (struct __mic_effect *)__this;
#if SYS_DIGVOL_GROUP_EN
//printf("effect_dvol_default_parm.ch_total %d effect->dodge_en %d\n", effect_dvol_default_parm.ch_total, effect->dodge_en);
if (ch == effect_dvol_default_parm.ch_total) {
if (effect->dodge_en) {
if (effect && effect->d_vol) {
if (event) { //推出闪避
audio_dig_vol_group_dodge(sys_digvol_group, "mic_mic", 100, 100);
} else { //启动闪避
audio_dig_vol_group_dodge(sys_digvol_group, "mic_mic", 100, 0);
}
}
}
}
#endif
}
/*----------------------------------------------------------------------------*/
/**@brief 打开mic 能量检测
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void *mic_energy_detect_open(u32 sr, u8 ch_num)
{
audio_energy_detect_param e_det_param = {0};
e_det_param.mute_energy = dodge_parm.dodge_out_thread;//人声能量小于mute_energy 退出闪避
e_det_param.unmute_energy = dodge_parm.dodge_in_thread;//人声能量大于 100触发闪避
e_det_param.mute_time_ms = dodge_parm.dodge_out_time_ms;
e_det_param.unmute_time_ms = dodge_parm.dodge_in_time_ms;
e_det_param.count_cycle_ms = 2;
e_det_param.sample_rate = sr;
e_det_param.event_handler = mic_e_det_handler;
e_det_param.ch_total = ch_num;
e_det_param.dcc = 1;
void *audio_e_det_hdl = audio_energy_detect_open(&e_det_param);
return audio_e_det_hdl;
}
/*----------------------------------------------------------------------------*/
/**@brief 关闭mic 能量检测
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mic_energy_detect_close(void *hdl)
{
if (hdl) {
audio_stream_del_entry(audio_energy_detect_entry_get(hdl));
#if SYS_DIGVOL_GROUP_EN
struct __mic_effect *effect = (struct __mic_effect *)__this;
if (effect->d_vol) {
audio_dig_vol_group_dodge(sys_digvol_group, "mic_mic", 100, 100); // undodge
}
#endif
audio_energy_detect_close(hdl);
}
}
/*----------------------------------------------------------------------------*/
/**@brief 能量检测运行过程,是否触发闪避
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mic_dodge_ctr(void)
{
struct __mic_effect *effect = (struct __mic_effect *)__this;
if (effect) {
effect->dodge_en = !effect->dodge_en;
}
}
u8 mic_dodge_get_status(void)
{
struct __mic_effect *effect = (struct __mic_effect *)__this;
if (effect) {
return effect->dodge_en;
}
return 0;
}
#endif
/*----------------------------------------------------------------------------*/
/**@brief (mic数据流)混响关闭接口
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mic_effect_stop(void)
{
mic_effect_destroy(&__this);
}
/*----------------------------------------------------------------------------*/
/**@brief (mic数据流)混响暂停接口(整个数据流不运行)
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mic_effect_pause(u8 mark)
{
if (__this) {
__this->pause_mark = mark ? 1 : 0;
}
}
/*----------------------------------------------------------------------------*/
/**@brief (mic数据流)混响暂停输出到DAC(数据流后级不写入DAC)
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mic_effect_dac_pause(u8 mark)
{
if (__this && __this->dac) {
audio_dac_channel_set_pause(__this->dac, mark);
}
}
/*----------------------------------------------------------------------------*/
/**@brief (mic数据流)混响状态获取接口
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
u8 mic_effect_get_status(void)
{
return ((__this) ? 1 : 0);
}
/*----------------------------------------------------------------------------*/
/**@brief 数字音量调节接口
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mic_effect_set_dvol(u8 vol)
{
if (__this && __this->d_vol) {
audio_dig_vol_set(__this->d_vol, 3, vol);
}
}
u8 mic_effect_get_dvol(void)
{
if (__this && __this->d_vol) {
return audio_dig_vol_get(__this->d_vol, 1);
}
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 获取mic增益接口
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
u8 mic_effect_get_micgain(void)
{
//动态调的需实时记录
return effect_mic_stream_parm_default.mic_gain;
}
/*----------------------------------------------------------------------------*/
/**@brief reverb 效果声增益调节接口
@param wet增益系数%[0,300];dry增益系数%[0,200]
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mic_effect_set_reverb_wet(int wet)
{
if (__this == NULL || __this->sub_0_plate_reverb_hdl == NULL) {
return ;
}
os_mutex_pend(&__this->mutex, 0);
Plate_reverb_parm parm;
memcpy(&parm, & __this->sub_0_plate_reverb_hdl->reverb_parm_obj, sizeof(Plate_reverb_parm));
parm.wet = wet;
update_plate_reverb_parm(__this->sub_0_plate_reverb_hdl, &parm);
os_mutex_post(&__this->mutex);
}
int mic_effect_get_reverb_wet(void)
{
if (__this && __this->sub_0_plate_reverb_hdl) {
return __this->sub_0_plate_reverb_hdl->reverb_parm_obj.wet;
}
return 0;
}
void mic_effect_set_reverb_dry(int dry)
{
if (__this == NULL || __this->sub_0_plate_reverb_hdl == NULL) {
return ;
}
os_mutex_pend(&__this->mutex, 0);
Plate_reverb_parm parm;
memcpy(&parm, & __this->sub_0_plate_reverb_hdl->reverb_parm_obj, sizeof(Plate_reverb_parm));
parm.dry = dry;
update_plate_reverb_parm(__this->sub_0_plate_reverb_hdl, &parm);
os_mutex_post(&__this->mutex);
}
int mic_effect_get_reverb_dry(void)
{
if (__this && __this->sub_0_plate_reverb_hdl) {
return __this->sub_0_plate_reverb_hdl->reverb_parm_obj.dry;
}
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief echo 回声延时调节接口
@param delay [0,max_ms]
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mic_effect_set_echo_delay(u32 delay)
{
if (__this == NULL || __this->sub_1_echo_hdl == NULL) {
return ;
}
os_mutex_pend(&__this->mutex, 0);
ECHO_PARM_SET parm;
memcpy(&parm, &__this->sub_1_echo_hdl->echo_parm_obj, sizeof(ECHO_PARM_SET));
parm.delay = delay;
update_echo_parm(__this->sub_1_echo_hdl, &parm);
os_mutex_post(&__this->mutex);
}
u32 mic_effect_get_echo_delay(void)
{
if (__this && __this->sub_1_echo_hdl) {
return __this->sub_1_echo_hdl->echo_parm_obj.delay;
}
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief echo 回声衰减系数调节接口
@param decay %[0,90]
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mic_effect_set_echo_decay(u32 decay)
{
if (__this == NULL || __this->sub_1_echo_hdl == NULL) {
return ;
}
os_mutex_pend(&__this->mutex, 0);
ECHO_PARM_SET parm;
memcpy(&parm, &__this->sub_1_echo_hdl->echo_parm_obj, sizeof(ECHO_PARM_SET));
parm.decayval = decay;
update_echo_parm(__this->sub_1_echo_hdl, &parm);
os_mutex_post(&__this->mutex);
}
u32 mic_effect_get_echo_decay(void)
{
if (__this && __this->sub_1_echo_hdl) {
return __this->sub_1_echo_hdl->echo_parm_obj.decayval;
}
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief echo 回声wetgain调节接口
@param wetgain 湿%[0,200]
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mic_effect_set_echo_wetgain(u32 wetgain)
{
if (__this == NULL || __this->sub_1_echo_hdl == NULL) {
return ;
}
os_mutex_pend(&__this->mutex, 0);
ECHO_PARM_SET parm;
memcpy(&parm, &__this->sub_1_echo_hdl->echo_parm_obj, sizeof(ECHO_PARM_SET));
parm.wetgain = wetgain;
update_echo_parm(__this->sub_1_echo_hdl, &parm);
os_mutex_post(&__this->mutex);
}
u32 mic_effect_get_echo_wetgain(void)
{
if (__this && __this->sub_1_echo_hdl) {
return __this->sub_1_echo_hdl->echo_parm_obj.wetgain;
}
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief echo 回声drygain调节接口
@param %[0,100]
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mic_effect_set_echo_drygain(u32 drygain)
{
if (__this == NULL || __this->sub_1_echo_hdl == NULL) {
return ;
}
os_mutex_pend(&__this->mutex, 0);
ECHO_PARM_SET parm;
memcpy(&parm, &__this->sub_1_echo_hdl->echo_parm_obj, sizeof(ECHO_PARM_SET));
parm.drygain = drygain;
update_echo_parm(__this->sub_1_echo_hdl, &parm);
os_mutex_post(&__this->mutex);
}
u32 mic_effect_get_echo_drygain(void)
{
if (__this && __this->sub_1_echo_hdl) {
return __this->sub_1_echo_hdl->echo_parm_obj.drygain;
}
return 0;
}
//*********************变声音效切换例程**********************************//
/* VOICE_CHANGER_NONE,//原声 */
/* VOICE_CHANGER_UNCLE,//大叔 */
/* VOICE_CHANGER_GODDESS,//女神 */
/* VOICE_CHANGER_BABY,//娃娃音 */
/* VOICE_CHANGER_MAGIC,//魔音女声 */
/* VOICE_CHANGER_MONSTER,//怪兽音 */
/* VOICE_CHANGER_DONALD_DUCK,//唐老鸭 */
/* VOICE_CHANGER_MINIONS,//小黄人 */
/* VOICE_CHANGER_ROBOT,//机器音 */
/* VOICE_CHANGER_WHISPER,//气音 */
/* VOICE_CHANGER_MELODY,//固定旋律音 */
/* VOICE_CHANGER_FEEDBACK,//调制音 */
VOICECHANGER_PARM parm = {
.shiftv = 100,//[50-200];越尖锐,越大声音越沉;100就是原声
.formant_shift = 100,
.effect_v = EFFECT_VOICECHANGE_PITCHSHIFT,
};
/*----------------------------------------------------------------------------*/
/**@brief 变声音调重置为原声音调
@param NULL
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mic_pitchv_reset_parm(void)
{
#if defined(TCFG_MIC_VOICE_CHANGER_ENABLE) && TCFG_MIC_VOICE_CHANGER_ENABLE
parm.shiftv = 100;
audio_voice_changer_update_parm(AEID_MIC_VOICE_CHANGER, &parm);
#endif
}
/*----------------------------------------------------------------------------*/
/**@brief 变声音调递增
@param NULL
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mic_pitchv_up(void)
{
#if defined(TCFG_MIC_VOICE_CHANGER_ENABLE) && TCFG_MIC_VOICE_CHANGER_ENABLE
if (parm.shiftv < 190) {
parm.shiftv += 10;
audio_voice_changer_update_parm(AEID_MIC_VOICE_CHANGER, &parm);
}
#endif
}
/*----------------------------------------------------------------------------*/
/**@brief 变声音调递减
@param NULL
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mic_pitchv_down(void)
{
#if defined(TCFG_MIC_VOICE_CHANGER_ENABLE) && TCFG_MIC_VOICE_CHANGER_ENABLE
if (parm.shiftv > 60) {
parm.shiftv -= 10;
audio_voice_changer_update_parm(AEID_MIC_VOICE_CHANGER, &parm);
}
#endif
}
/*----------------------------------------------------------------------------*/
/**@brief 变声音效循环切换
@param NULL
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mic_voicechange_loop(void)
{
voicechange_mode++;
if (voicechange_mode >= VOICE_CHANGER_MAX) {
voicechange_mode = VOICE_CHANGER_NONE;
}
mic_voicechange_switch(voicechange_mode);
}
/*----------------------------------------------------------------------------*/
/**@brief 变声音效指定模式切换
@param eff_mode
@return
@note
*/
/*----------------------------------------------------------------------------*/
void mic_voicechange_switch(u8 eff_mode)
{
#if defined(TCFG_MIC_VOICE_CHANGER_ENABLE) && TCFG_MIC_VOICE_CHANGER_ENABLE
if (!mic_effect_get_status()) {
mic_effect_start();
/* return; */
}
switch (eff_mode) {
case VOICE_CHANGER_NONE://原声,录音棚
/* tone_play_index(IDEX_TONE_MIC_OST, 1); */
break;
case VOICE_CHANGER_UNCLE://大叔
/* tone_play_index(IDEX_TONE_UNCLE, 1); */
break;
case VOICE_CHANGER_GODDESS://女神
/* tone_play_index(IDEX_TONE_GODNESS, 1); */
break;
case VOICE_CHANGER_BABY://娃娃音
/* tone_play_index(IDEX_TONE_BABY, 1); */
break;
case VOICE_CHANGER_MAGIC://魔音女声
/* tone_play_index(IDEX_TONE_BABY, 1); */
break;
case VOICE_CHANGER_MONSTER://怪兽音
/* tone_play_index(IDEX_TONE_BABY, 1); */
break;
case VOICE_CHANGER_DONALD_DUCK://唐老鸭
/* tone_play_index(IDEX_TONE_BABY, 1); */
break;
case VOICE_CHANGER_MINIONS://小黄人
/* tone_play_index(IDEX_TONE_BABY, 1); */
break;
case VOICE_CHANGER_ROBOT://机器音
/* tone_play_index(IDEX_TONE_BABY, 1); */
break;
case VOICE_CHANGER_WHISPER://气音
/* tone_play_index(IDEX_TONE_BABY, 1); */
break;
case VOICE_CHANGER_MELODY://固定旋律音
/* tone_play_index(IDEX_TONE_BABY, 1); */
break;
case VOICE_CHANGER_FEEDBACK://调制音
/* tone_play_index(IDEX_TONE_BABY, 1); */
break;
default:
puts("mic_ERROR\n");
/* mic_effect_stop(); */
break;
}
audio_voice_changer_mode_switch(AEID_MIC_VOICE_CHANGER, eff_mode);
#endif//TCFG_MIC_VOICE_CHANGER_ENABLE
}
/**************************各个音效模块参数设置接口(调试工具/模式切换会使用勿修改)************************************/
void plate_reverb_update_parm(void *parm, int bypass)
{
if (__this && __this->sub_0_plate_reverb_hdl) {
update_plate_reverb_parm(__this->sub_0_plate_reverb_hdl, parm);
plate_reverb_update_bypass(__this->sub_0_plate_reverb_hdl, bypass);
}
}
void echo_updata_parm(void *parm, int bypass)
{
if (__this && __this->sub_1_echo_hdl) {
update_echo_parm(__this->sub_1_echo_hdl, parm);
echo_update_bypass(__this->sub_1_echo_hdl, bypass);
}
}
void noisegate_update_parm(void *parm, int bypass)
{
audio_noisegate_update(AEID_MIC_NS_GATE, parm);
audio_noisegate_bypass(AEID_MIC_NS_GATE, bypass);
}
void howling_pitch_shift_update_parm(void *parm, int bypass)
{
if (__this && __this->howling_ps) {
update_howling_parm(__this->howling_ps, parm);
howling_update_bypass(__this->howling_ps, bypass);
}
}
void notchhowline_update_parm(void *parm, int bypass)
{
if (__this && __this->notch_howling) {
update_howling_parm(__this->notch_howling, parm);
howling_update_bypass(__this->notch_howling, bypass);
}
}
/**************************各个音效模块参数设置接口 END************************************/
#endif