KT24-1110_65E-HA-651B/cpu/br25/audio_mic/mic_effect.c
2024-11-10 18:44:17 +08:00

1849 lines
58 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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