pinebuds/services/audio_process/audio_process.c

1239 lines
34 KiB
C

/***************************************************************************
*
* Copyright 2015-2019 BES.
* All rights reserved. All unpublished rights reserved.
*
* No part of this work may be used or reproduced in any form or by any
* means, or stored in a database or retrieval system, without prior written
* permission of BES.
*
* Use of this work is governed by a license granted by BES.
* This work contains confidential and proprietary information of
* BES. which is protected by copyright, trade secret,
* trademark and other intellectual property rights.
*
****************************************************************************/
/*******************************************************************************
** namer : Audio Process
** description : Manage auido process algorithms, include :hw iir eq, sw iir
*eq,
** hw fir eq, drc...
** version : V1.0
** author : Yunjie Huo
** modify : 2018.12.4
** todo : NULL
** MIPS : NO PROCESS: 34M(TWS, one ear, Mono, AAC, 48k)
** DRC1: 36M(3 bands)
** DRC2: 12M
*******************************************************************************/
/*
Audio Flow:
DECODE --> SW IIR EQ --> DRC --> LIMTER --> VOLUME --> HW IIR EQ --> SPK
+-----------------------------+
| DAC | | |
+--------+ +-----------+ +-----+ +--------+ | +--------+
+-----------+ | +-----+ | | PCM | | | | | |
| | | | | | | | | DECODE +---->+ SW IIR EQ +--->+ DRC
+--->+ LIMTER +--->+ VOLUME +--->+ HW IIR EQ +--->+ SPK | | | | | |
| | | | | | | | | | |
+--------+ +-----------+ +-----+ +--------+ | +--------+
+-----------+ | +-----+
+-----------------------------+
| ------------ | ------------------------- | -------- | ----------- |
| Algorithm | description | MIPS(M) | RAM(kB) |
| ------------ | ------------------------- | -------- | ----------- |
| DRC | Dynamic Range Compression | 12M/band | 13 |
| Limiter/DRC2 | Limiter | 12M | 5 |
| EQ | Equalizer | 1M/band | Almost zero |
*/
#include "audio_process.h"
#include "audio_cfg.h"
#include "drc.h"
#include "hal_cmu.h"
#include "hal_location.h"
#include "hal_timer.h"
#include "hal_trace.h"
#include "hw_codec_iir_process.h"
#include "hw_iir_process.h"
#include "limiter.h"
#include "stdbool.h"
#include "string.h"
#include "tgt_hardware.h"
#if defined(USB_EQ_TUNING)
#if !defined(__HW_DAC_IIR_EQ_PROCESS__) && !defined(__SW_IIR_EQ_PROCESS__)
#error \
"Either HW_DAC_IIR_EQ_PROCESS or SW_IIR_EQ_PROCESS should be defined when enabling USB_EQ_TUNING"
#endif
#endif
#if defined(__PC_CMD_UART__) || defined(USB_EQ_TUNING)
#include "hal_cmd.h"
#if defined(__SW_IIR_EQ_PROCESS__)
#define AUDIO_EQ_SW_IIR_UPDATE_CFG
#endif
#if defined(__HW_DAC_IIR_EQ_PROCESS__)
#define AUDIO_EQ_HW_DAC_IIR_UPDATE_CFG
#endif
#if defined(__HW_IIR_EQ_PROCESS__)
#define AUDIO_EQ_HW_IIR_UPDATE_CFG
#endif
#ifdef __HW_FIR_EQ_PROCESS__
#define AUDIO_EQ_HW_FIR_UPDATE_CFG
#endif
#ifdef __AUDIO_DRC__
#define AUDIO_DRC_UPDATE_CFG
#endif
#ifdef __AUDIO_DRC2__
#define AUDIO_DRC2_UPDATE_CFG
#endif
#endif
#if defined(__SW_IIR_EQ_PROCESS__)
extern const IIR_CFG_T *const audio_eq_sw_iir_cfg_list[EQ_SW_IIR_LIST_NUM];
#endif
#if defined(__HW_DAC_IIR_EQ_PROCESS__)
extern const IIR_CFG_T *const POSSIBLY_UNUSED
audio_eq_hw_dac_iir_cfg_list[EQ_HW_DAC_IIR_LIST_NUM];
#endif
#if defined(__HW_IIR_EQ_PROCESS__)
extern const IIR_CFG_T *const POSSIBLY_UNUSED
audio_eq_hw_iir_cfg_list[EQ_HW_IIR_LIST_NUM];
#endif
#ifdef __HW_FIR_EQ_PROCESS__
extern const FIR_CFG_T *const audio_eq_hw_fir_cfg_list[EQ_HW_FIR_LIST_NUM];
#endif
#ifdef __AUDIO_DRC__
extern const DrcConfig audio_drc_cfg;
#endif
#ifdef __AUDIO_DRC2__
extern const LimiterConfig audio_drc2_cfg;
#endif
#if defined(AUDIO_EQ_SW_IIR_UPDATE_CFG) || \
defined(AUDIO_EQ_HW_FIR_UPDATE_CFG) || \
defined(AUDIO_EQ_HW_DAC_IIR_UPDATE_CFG) || \
defined(AUDIO_EQ_HW_IIR_UPDATE_CFG) || defined(AUDIO_DRC_UPDATE_CFG) || \
defined(AUDIO_DRC2_UPDATE_CFG)
#define AUDIO_UPDATE_CFG
#endif
#ifdef __AUDIO_DRC__
#define AUDIO_DRC_NEEDED_SIZE (1024 * 13)
#else
#define AUDIO_DRC_NEEDED_SIZE (0)
#endif
#ifdef __AUDIO_DRC2__
#define AUDIO_DRC2_NEEDED_SIZE (1024 * 5)
#else
#define AUDIO_DRC2_NEEDED_SIZE (0)
#endif
#define AUDIO_MEMORY_SIZE (AUDIO_DRC_NEEDED_SIZE + AUDIO_DRC2_NEEDED_SIZE)
#if AUDIO_MEMORY_SIZE > 0
#include "audio_memory.h"
#endif
#ifndef CODEC_OUTPUT_DEV
#define CODEC_OUTPUT_DEV CFG_HW_AUD_OUTPUT_PATH_SPEAKER_DEV
#endif
typedef signed int pcm_24bits_t;
typedef signed short int pcm_16bits_t;
typedef struct {
enum AUD_BITS_T sample_bits;
enum AUD_SAMPRATE_T sample_rate;
enum AUD_CHANNEL_NUM_T sw_ch_num;
enum AUD_CHANNEL_NUM_T hw_ch_num;
#if defined(__SW_IIR_EQ_PROCESS__)
bool sw_iir_enable;
#endif
#if defined(__HW_DAC_IIR_EQ_PROCESS__)
bool hw_dac_iir_enable;
#endif
#if defined(__HW_IIR_EQ_PROCESS__)
bool hw_iir_enable;
#endif
#if defined(__HW_FIR_EQ_PROCESS__)
bool hw_fir_enable;
#endif
#if AUDIO_MEMORY_SIZE > 0
uint8_t *audio_heap;
#endif
#ifdef __AUDIO_DRC__
DrcState *drc_st;
#endif
#ifdef __AUDIO_DRC2__
LimiterState *drc2_st;
#endif
#ifdef AUDIO_UPDATE_CFG
bool update_cfg;
#endif
#ifdef USB_EQ_TUNING
bool eq_updated_cfg;
#endif
#ifdef AUDIO_EQ_SW_IIR_UPDATE_CFG
IIR_CFG_T sw_iir_cfg;
#endif
#ifdef AUDIO_EQ_HW_DAC_IIR_UPDATE_CFG
IIR_CFG_T hw_dac_iir_cfg;
#endif
#ifdef AUDIO_EQ_HW_IIR_UPDATE_CFG
IIR_CFG_T hw_iir_cfg;
#endif
#ifdef AUDIO_EQ_HW_FIR_UPDATE_CFG
FIR_CFG_T hw_fir_cfg;
#endif
#ifdef AUDIO_DRC_UPDATE_CFG
bool drc_update;
DrcConfig drc_cfg;
#endif
#ifdef AUDIO_DRC2_UPDATE_CFG
bool drc2_update;
LimiterConfig drc2_cfg;
#endif
} AUDIO_PROCESS_T;
static AUDIO_PROCESS_T audio_process = {
.sample_bits = AUD_BITS_NULL,
.sample_rate = AUD_SAMPRATE_NULL,
.sw_ch_num = AUD_CHANNEL_NUM_NULL,
.hw_ch_num = AUD_CHANNEL_NUM_NULL,
#if defined(__SW_IIR_EQ_PROCESS__)
.sw_iir_enable = false,
#endif
#if defined(__HW_DAC_IIR_EQ_PROCESS__)
.hw_dac_iir_enable = false,
#endif
#if defined(__HW_IIR_EQ_PROCESS__)
.hw_iir_enable = false,
#endif
#if defined(__HW_FIR_EQ_PROCESS__)
.hw_fir_enable = false,
#endif
#ifdef AUDIO_UPDATE_CFG
.update_cfg = false,
#endif
#ifdef AUDIO_EQ_SW_IIR_UPDATE_CFG
.sw_iir_cfg = {.num = 0},
#endif
#ifdef AUDIO_EQ_HW_DAC_IIR_UPDATE_CFG
.hw_dac_iir_cfg = {.num = 0},
#endif
#ifdef AUDIO_EQ_HW_IIR_UPDATE_CFG
.hw_iir_cfg = {.num = 0},
#endif
#ifdef AUDIO_EQ_HW_FIR_UPDATE_CFG
.hw_fir_cfg = {.len = 0},
#endif
#ifdef AUDIO_DRC_UPDATE_CFG
.drc_update = false,
.drc_cfg = {.knee = 0,
.filter_type = {-1, -1},
.band_num = 1,
.look_ahead_time = 0,
.band_settings =
{
{0, 0, 1, 1, 1, 1},
{0, 0, 1, 1, 1, 1},
}},
#endif
#ifdef AUDIO_DRC2_UPDATE_CFG
.drc2_update = false,
.drc2_cfg =
{
.knee = 0,
.look_ahead_time = 0,
.threshold = 0,
.makeup_gain = 0,
.ratio = 1000,
.attack_time = 1,
.release_time = 1,
},
#endif
};
int audio_eq_set_cfg(const FIR_CFG_T *fir_cfg, const IIR_CFG_T *iir_cfg,
AUDIO_EQ_TYPE_T audio_eq_type) {
#if defined(__SW_IIR_EQ_PROCESS__) || defined(__HW_FIR_EQ_PROCESS__) || \
defined(__HW_DAC_IIR_EQ_PROCESS__) || defined(__HW_IIR_EQ_PROCESS__)
switch (audio_eq_type) {
#if defined(__SW_IIR_EQ_PROCESS__)
case AUDIO_EQ_TYPE_SW_IIR: {
if (iir_cfg) {
audio_process.sw_iir_enable = false;
#ifdef USB_EQ_TUNING
if (audio_process.eq_updated_cfg) {
iir_set_cfg(&audio_process.sw_iir_cfg);
} else
#endif
{
iir_set_cfg(iir_cfg);
}
audio_process.sw_iir_enable = true;
} else {
audio_process.sw_iir_enable = false;
}
} break;
#endif
#if defined(__HW_FIR_EQ_PROCESS__)
case AUDIO_EQ_TYPE_HW_FIR: {
if (fir_cfg) {
audio_process.hw_fir_enable = false;
fir_set_cfg(fir_cfg);
audio_process.hw_fir_enable = true;
} else {
audio_process.hw_fir_enable = false;
}
} break;
#endif
#if defined(__HW_DAC_IIR_EQ_PROCESS__)
case AUDIO_EQ_TYPE_HW_DAC_IIR: {
if (iir_cfg) {
HW_CODEC_IIR_CFG_T *hw_iir_cfg_dac = NULL;
enum AUD_SAMPRATE_T sample_rate_hw_dac_iir;
#ifdef __AUDIO_RESAMPLE__
int i;
for (i = 1; i < 129; i++) {
if (audio_process.sample_rate == AUD_SAMPRATE_7350 * i)
break;
if (audio_process.sample_rate == AUD_SAMPRATE_8000 * i)
break;
}
TRACE(1, "audio_process.sample_rate i:%d", i);
if (i == 129)
i = 6; // set default eq parameter;
sample_rate_hw_dac_iir = i * 8463.541666f; // AUD_SAMPRATE_8463
#else
sample_rate_hw_dac_iir = audio_process.sample_rate;
#endif
audio_process.hw_dac_iir_enable = false;
#ifdef USB_EQ_TUNING
if (audio_process.eq_updated_cfg) {
hw_iir_cfg_dac = hw_codec_iir_get_cfg(sample_rate_hw_dac_iir,
&audio_process.hw_dac_iir_cfg);
} else
#endif
{
hw_iir_cfg_dac = hw_codec_iir_get_cfg(sample_rate_hw_dac_iir, iir_cfg);
}
ASSERT(hw_iir_cfg_dac != NULL, "[%s] codec IIR parameter error!",
__func__);
hw_codec_iir_set_cfg(hw_iir_cfg_dac, sample_rate_hw_dac_iir,
HW_CODEC_IIR_DAC);
audio_process.hw_dac_iir_enable = true;
} else {
audio_process.hw_dac_iir_enable = false;
}
} break;
#endif
#if defined(__HW_IIR_EQ_PROCESS__)
case AUDIO_EQ_TYPE_HW_IIR: {
if (iir_cfg) {
HW_IIR_CFG_T *hw_iir_cfg = NULL;
audio_process.hw_iir_enable = false;
hw_iir_cfg = hw_iir_get_cfg(audio_process.sample_rate, iir_cfg);
ASSERT(hw_iir_cfg != NULL, "[%s] 0x%x codec IIR parameter error!",
__func__, (unsigned int)hw_iir_cfg);
hw_iir_set_cfg(hw_iir_cfg);
audio_process.hw_iir_enable = true;
} else {
audio_process.hw_iir_enable = false;
}
} break;
#endif
default: {
ASSERT(false, "[%s]Error eq type!", __func__);
}
}
#endif
return 0;
}
int SRAM_TEXT_LOC audio_process_run(uint8_t *buf, uint32_t len) {
int POSSIBLY_UNUSED pcm_len = 0;
if (audio_process.sample_bits == AUD_BITS_16) {
pcm_len = len / sizeof(pcm_16bits_t);
} else if (audio_process.sample_bits == AUD_BITS_24) {
pcm_len = len / sizeof(pcm_24bits_t);
} else {
ASSERT(0, "[%s] bits(%d) is invalid", __func__, audio_process.sample_bits);
}
if (audio_process.sw_ch_num == audio_process.hw_ch_num) {
// do nothing
} else if (audio_process.sw_ch_num == AUD_CHANNEL_NUM_1 &&
audio_process.hw_ch_num == AUD_CHANNEL_NUM_2) {
if (audio_process.sample_bits == AUD_BITS_16) {
int16_t *pcm_buf = (int16_t *)buf;
for (uint32_t i = 0, j = 0; i < pcm_len; i += 2, j++) {
pcm_buf[j] = pcm_buf[i];
}
} else {
int32_t *pcm_buf = (int32_t *)buf;
for (uint32_t i = 0, j = 0; i < pcm_len; i += 2, j++) {
pcm_buf[j] = pcm_buf[i];
}
}
pcm_len /= 2;
} else {
ASSERT(0, "[%s] sw_ch_num(%d) or hw_ch_num(%d) is invalid", __FUNCTION__,
audio_process.sw_ch_num, audio_process.hw_ch_num);
}
#ifdef AUDIO_PROCESS_DUMP
int *buf32 = (int *)buf;
for (int i = 0; i < 1024; i++)
dump_buf[i] = buf32[2 * i] >> 8;
audio_dump_clear_up();
audio_dump_add_channel_data(0, dump_buf, 1024);
#endif
// int32_t s_time,e_time;
// s_time = hal_fast_sys_timer_get();
#ifdef __SW_IIR_EQ_PROCESS__
if (audio_process.sw_iir_enable) {
iir_run(buf, pcm_len);
}
#endif
#ifdef __HW_FIR_EQ_PROCESS__
if (audio_process.hw_fir_enable) {
fir_run(buf, pcm_len);
}
#endif
#ifdef __AUDIO_DRC__
#ifdef AUDIO_DRC_UPDATE_CFG
if (audio_process.drc_update) {
drc_set_config(audio_process.drc_st, &audio_process.drc_cfg);
audio_process.drc_update = false;
}
#endif
drc_process(audio_process.drc_st, buf, pcm_len);
#endif
// int32_t m_time = hal_fast_sys_timer_get();
#ifdef __AUDIO_DRC2__
#ifdef AUDIO_DRC2_UPDATE_CFG
if (audio_process.drc2_update) {
limiter_set_config(audio_process.drc2_st, &audio_process.drc2_cfg);
audio_process.drc2_update = false;
}
#endif
limiter_process(audio_process.drc2_st, buf, pcm_len);
#endif
#ifdef __HW_IIR_EQ_PROCESS__
if (audio_process.hw_iir_enable) {
hw_iir_run(buf, pcm_len);
}
#endif
if (audio_process.sw_ch_num == audio_process.hw_ch_num) {
// do nothing
} else if (audio_process.sw_ch_num == AUD_CHANNEL_NUM_1 &&
audio_process.hw_ch_num == AUD_CHANNEL_NUM_2) {
if (audio_process.sample_bits == AUD_BITS_16) {
int16_t *pcm_buf = (int16_t *)buf;
for (int32_t i = pcm_len - 1, j = 2 * pcm_len - 1; i >= 0; i--, j -= 2) {
pcm_buf[j + 1] = pcm_buf[i];
pcm_buf[j + 0] = pcm_buf[i];
}
} else {
int32_t *pcm_buf = (int32_t *)buf;
for (int32_t i = pcm_len - 1, j = 2 * pcm_len - 2; i >= 0; i--, j -= 2) {
pcm_buf[j + 1] = pcm_buf[i];
pcm_buf[j + 0] = pcm_buf[i];
}
}
pcm_len *= 2;
} else {
ASSERT(0, "[%s] sw_ch_num(%d) or hw_ch_num(%d) is invalid", __FUNCTION__,
audio_process.sw_ch_num, audio_process.hw_ch_num);
}
#ifdef AUDIO_PROCESS_DUMP
// for(int i=0;i<1024;i++)
// dump_buf[i] = buf32[2 * i+0]>>8;
// audio_dump_add_channel_data(1, dump_buf, 1024);
audio_dump_run();
#endif
// e_time = hal_fast_sys_timer_get();
// TRACE(4,"[%s] Sample len = %d, drc1 %d us, drc2 %d us",
// __func__, pcm_len, FAST_TICKS_TO_US(m_time - s_time),
// FAST_TICKS_TO_US(e_time - m_time));
return 0;
}
/*
* frame_size stands for samples per channel
*/
int audio_process_open(enum AUD_SAMPRATE_T sample_rate,
enum AUD_BITS_T sample_bits,
enum AUD_CHANNEL_NUM_T sw_ch_num,
enum AUD_CHANNEL_NUM_T hw_ch_num, int32_t frame_size,
void *eq_buf, uint32_t len) {
TRACE(
5,
"[%s] sample_rate = %d, sample_bits = %d, sw_ch_num = %d, hw_ch_num = %d",
__func__, sample_rate, sample_bits, sw_ch_num, hw_ch_num);
#ifdef AUDIO_PROCESS_DUMP
audio_dump_init(1024, sizeof(short), 2);
#endif
audio_process.sample_rate = sample_rate;
audio_process.sample_bits = sample_bits;
audio_process.sw_ch_num = sw_ch_num;
audio_process.hw_ch_num = hw_ch_num;
#if defined(__HW_FIR_EQ_PROCESS__) && defined(__HW_IIR_EQ_PROCESS__)
void *fir_eq_buf = eq_buf;
uint32_t fir_len = len / 2;
void *iir_eq_buf = (uint8_t *)eq_buf + fir_len;
uint32_t iir_len = len / 2;
#elif defined(__HW_FIR_EQ_PROCESS__) && !defined(__HW_IIR_EQ_PROCESS__)
void *fir_eq_buf = eq_buf;
uint32_t fir_len = len;
#elif !defined(__HW_FIR_EQ_PROCESS__) && defined(__HW_IIR_EQ_PROCESS__)
void *iir_eq_buf = eq_buf;
uint32_t iir_len = len;
#endif
#ifdef __SW_IIR_EQ_PROCESS__
iir_open(sample_rate, sample_bits, sw_ch_num);
#ifdef AUDIO_EQ_SW_IIR_UPDATE_CFG
audio_eq_set_cfg(NULL, &audio_process.sw_iir_cfg, AUDIO_EQ_TYPE_SW_IIR);
#endif
#endif
#ifdef __HW_DAC_IIR_EQ_PROCESS__
enum AUD_SAMPRATE_T sample_rate_hw_dac_iir;
#ifdef __AUDIO_RESAMPLE__
int i;
for (i = 1; i < 129; i++) {
if (audio_process.sample_rate == AUD_SAMPRATE_7350 * i)
break;
if (audio_process.sample_rate == AUD_SAMPRATE_8000 * i)
break;
}
TRACE(1, "sample_rate i:%d", i);
if (i == 129)
i = 6; // set default eq parameter;
sample_rate_hw_dac_iir = i * 8463.541666f; // AUD_SAMPRATE_8463
#else
sample_rate_hw_dac_iir = audio_process.sample_rate;
#endif
hw_codec_iir_open(sample_rate_hw_dac_iir, HW_CODEC_IIR_DAC, CODEC_OUTPUT_DEV);
#ifdef AUDIO_EQ_HW_DAC_IIR_UPDATE_CFG
audio_eq_set_cfg(NULL, &audio_process.hw_dac_iir_cfg,
AUDIO_EQ_TYPE_HW_DAC_IIR);
#endif
#endif
#ifdef __HW_IIR_EQ_PROCESS__
hw_iir_open(sample_rate, sample_bits, sw_ch_num, iir_eq_buf, iir_len);
#ifdef AUDIO_EQ_HW_IIR_UPDATE_CFG
audio_eq_set_cfg(NULL, &audio_process.hw_iir_cfg, AUDIO_EQ_TYPE_HW_IIR);
#endif
#endif
#ifdef __HW_FIR_EQ_PROCESS__
#if defined(CHIP_BEST1000) && defined(FIR_HIGHSPEED)
hal_cmu_fir_high_speed_enable(HAL_CMU_FIR_USER_EQ);
#endif
fir_open(sample_rate, sample_bits, sw_ch_num, fir_eq_buf, fir_len);
#ifdef AUDIO_EQ_HW_FIR_UPDATE_CFG
audio_eq_set_cfg(&audio_process.hw_fir_cfg, NULL, AUDIO_EQ_TYPE_HW_FIR);
#endif
#endif
#if AUDIO_MEMORY_SIZE > 0
syspool_get_buff(&audio_process.audio_heap, AUDIO_MEMORY_SIZE);
audio_heap_init(audio_process.audio_heap, AUDIO_MEMORY_SIZE);
#endif
#ifdef __AUDIO_DRC__
audio_process.drc_st =
drc_create(sample_rate, frame_size, sample_bits, sw_ch_num,
#ifdef AUDIO_DRC_UPDATE_CFG
&audio_process.drc_cfg
#else
&audio_drc_cfg
#endif
);
#ifdef AUDIO_DRC_UPDATE_CFG
audio_process.drc_update = false;
#endif
#endif
#ifdef __AUDIO_DRC2__
audio_process.drc2_st =
limiter_create(sample_rate, frame_size, sample_bits, sw_ch_num,
#ifdef AUDIO_DRC2_UPDATE_CFG
&audio_process.drc2_cfg
#else
&audio_drc2_cfg
#endif
);
#ifdef AUDIO_DRC2_UPDATE_CFG
audio_process.drc2_update = false;
#endif
#endif
#if defined(__PC_CMD_UART__) && defined(USB_AUDIO_APP)
hal_cmd_open();
#endif
return 0;
}
int audio_process_close(void) {
#ifdef __SW_IIR_EQ_PROCESS__
audio_process.sw_iir_enable = false;
iir_close();
#endif
#ifdef __HW_DAC_IIR_EQ_PROCESS__
audio_process.hw_dac_iir_enable = false;
hw_codec_iir_close(HW_CODEC_IIR_DAC);
#endif
#ifdef __HW_IIR_EQ_PROCESS__
audio_process.hw_iir_enable = false;
hw_iir_close();
#endif
#ifdef __HW_FIR_EQ_PROCESS__
audio_process.hw_fir_enable = false;
fir_close();
#if defined(CHIP_BEST1000) && defined(FIR_HIGHSPEED)
hal_cmu_fir_high_speed_disable(HAL_CMU_FIR_USER_EQ);
#endif
#endif
#ifdef __AUDIO_DRC__
#ifdef AUDIO_DRC_UPDATE_CFG
audio_process.drc_update = false;
#endif
drc_destroy(audio_process.drc_st);
audio_process.drc_st = NULL;
#endif
#ifdef __AUDIO_DRC2__
#ifdef AUDIO_DRC2_UPDATE_CFG
audio_process.drc2_update = false;
#endif
limiter_destroy(audio_process.drc2_st);
audio_process.drc2_st = NULL;
#endif
#if AUDIO_MEMORY_SIZE > 0
size_t total = 0, used = 0, max_used = 0;
audio_memory_info(&total, &used, &max_used);
TRACE(3, "AUDIO MALLOC MEM: total - %d, used - %d, max_used - %d.", total,
used, max_used);
ASSERT(used == 0, "[%s] used != 0", __func__);
#endif
#if defined(__PC_CMD_UART__) && defined(USB_AUDIO_APP)
hal_cmd_close();
#endif
return 0;
}
#if defined(__PC_CMD_UART__) || defined(USB_EQ_TUNING)
int audio_ping_callback(uint8_t *buf, uint32_t len) {
// TRACE(0,"");
return 0;
}
#if defined(AUDIO_EQ_SW_IIR_UPDATE_CFG) && !defined(USB_EQ_TUNING)
#ifndef USB_AUDIO_APP
int audio_eq_sw_iir_callback(uint8_t *buf, uint32_t len) {
TRACE(3, "[%s] len = %d, sizeof(struct) = %d", __func__, len,
sizeof(IIR_CFG_T));
if (len != sizeof(IIR_CFG_T)) {
return 1;
}
memcpy(&audio_process.sw_iir_cfg, buf, sizeof(IIR_CFG_T));
TRACE(3, "band num:%d gain0:%d, gain1:%d",
(int32_t)audio_process.sw_iir_cfg.num,
(int32_t)(audio_process.sw_iir_cfg.gain0 * 10),
(int32_t)(audio_process.sw_iir_cfg.gain1 * 10));
for (uint8_t i = 0; i < audio_process.sw_iir_cfg.num; i++) {
TRACE(5, "band num:%d type %d gain:%d fc:%d q:%d", i,
(int32_t)(audio_process.sw_iir_cfg.param[i].type),
(int32_t)(audio_process.sw_iir_cfg.param[i].gain * 10),
(int32_t)(audio_process.sw_iir_cfg.param[i].fc * 10),
(int32_t)(audio_process.sw_iir_cfg.param[i].Q * 10));
}
#ifdef __SW_IIR_EQ_PROCESS__
{
iir_set_cfg(&audio_process.sw_iir_cfg);
audio_process.sw_iir_enable = true;
}
#endif
return 0;
}
#else
int audio_eq_sw_iir_callback(uint8_t *buf, uint32_t len) {
// IIR_CFG_T *rx_iir_cfg = NULL;
// rx_iir_cfg = (IIR_CFG_T *)buf;
// TRACE(3,"[%s] left gain = %f, right gain = %f", __func__,
// rx_iir_cfg->gain0, rx_iir_cfg->gain1);
// for(int i=0; i<rx_iir_cfg->num; i++)
// {
// TRACE(5,"[%s] iir[%d] gain = %f, f = %f, Q = %f", __func__, i,
// rx_iir_cfg->param[i].gain, rx_iir_cfg->param[i].fc,
// rx_iir_cfg->param[i].Q);
// }
// audio_eq_set_cfg(NULL,(const IIR_CFG_T *)rx_iir_cfg,AUDIO_EQ_TYPE_SW_IIR);
iir_update_cfg_tbl(buf, len);
return 0;
}
#endif
#endif
#ifdef AUDIO_EQ_HW_FIR_UPDATE_CFG
int audio_eq_hw_fir_callback(uint8_t *buf, uint32_t len) {
TRACE(3, "[%s] len = %d, sizeof(struct) = %d", __func__, len,
sizeof(FIR_CFG_T));
if (len != sizeof(FIR_CFG_T)) {
return 1;
}
FIR_CFG_T *rx_fir_cfg = NULL;
rx_fir_cfg = (FIR_CFG_T *)buf;
TRACE(3, "[%s] left gain = %d, right gain = %d", __func__, rx_fir_cfg->gain0,
rx_fir_cfg->gain1);
TRACE(6, "[%s] len = %d, coef: %d, %d......%d, %d", __func__, rx_fir_cfg->len,
rx_fir_cfg->coef[0], rx_fir_cfg->coef[1],
rx_fir_cfg->coef[rx_fir_cfg->len - 2],
rx_fir_cfg->coef[rx_fir_cfg->len - 1]);
rx_fir_cfg->gain0 = 6;
rx_fir_cfg->gain1 = 6;
if (rx_fir_cfg) {
memcpy(&audio_process.fir_cfg, rx_fir_cfg, sizeof(audio_process.fir_cfg));
audio_process.fir_enable = true;
fir_set_cfg(&audio_process.fir_cfg);
} else {
audio_process.fir_enable = false;
}
return 0;
}
#endif
#ifdef AUDIO_DRC_UPDATE_CFG
int audio_drc_callback(uint8_t *buf, uint32_t len) {
TRACE(3, "[%s] len = %d, sizeof(struct) = %d", __func__, len,
sizeof(DrcConfig));
if (len != sizeof(DrcConfig)) {
TRACE(1, "[%s] WARNING: Length is different", __func__);
return 1;
}
if (audio_process.drc_st == NULL) {
TRACE(1, "[%s] WARNING: audio_process.drc2_st = NULL", __func__);
TRACE(1, "[%s] WARNING: Please Play music, then tuning Limiter", __func__);
return 2;
}
memcpy(&audio_process.drc_cfg, buf, sizeof(DrcConfig));
audio_process.drc_update = true;
return 0;
}
#endif
#ifdef AUDIO_DRC2_UPDATE_CFG
int audio_drc2_callback(uint8_t *buf, uint32_t len) {
TRACE(3, "[%s] len = %d, sizeof(struct) = %d", __func__, len,
sizeof(LimiterConfig));
if (len != sizeof(LimiterConfig)) {
TRACE(1, "[%s] WARNING: Length is different", __func__);
return 1;
}
if (audio_process.drc2_st == NULL) {
TRACE(1, "[%s] WARNING: audio_process.drc2_st = NULL", __func__);
TRACE(1, "[%s] WARNING: Please Play music, then tuning Limiter", __func__);
return 2;
}
memcpy(&audio_process.drc2_cfg, buf, sizeof(LimiterConfig));
audio_process.drc2_update = true;
return 0;
}
#endif
#if defined(AUDIO_EQ_HW_DAC_IIR_UPDATE_CFG) && !defined(USB_EQ_TUNING)
int audio_eq_hw_dac_iir_callback(uint8_t *buf, uint32_t len) {
TRACE(3, "[%s] len = %d, sizeof(struct) = %d", __func__, len,
sizeof(IIR_CFG_T));
if (len != sizeof(IIR_CFG_T)) {
return 1;
}
memcpy(&audio_process.hw_dac_iir_cfg, buf, sizeof(IIR_CFG_T));
TRACE(3, "band num:%d gain0:%d, gain1:%d",
(int32_t)audio_process.hw_dac_iir_cfg.num,
(int32_t)(audio_process.hw_dac_iir_cfg.gain0 * 10),
(int32_t)(audio_process.hw_dac_iir_cfg.gain1 * 10));
for (uint8_t i = 0; i < audio_process.hw_dac_iir_cfg.num; i++) {
TRACE(5, "band num:%d type %d gain:%d fc:%d q:%d", i,
(int32_t)(audio_process.hw_dac_iir_cfg.param[i].type),
(int32_t)(audio_process.hw_dac_iir_cfg.param[i].gain * 10),
(int32_t)(audio_process.hw_dac_iir_cfg.param[i].fc * 10),
(int32_t)(audio_process.hw_dac_iir_cfg.param[i].Q * 10));
}
#ifdef __HW_DAC_IIR_EQ_PROCESS__
{
HW_CODEC_IIR_CFG_T *hw_iir_cfg_dac = NULL;
enum AUD_SAMPRATE_T sample_rate_hw_dac_iir;
#ifdef __AUDIO_RESAMPLE__
int i;
for (i = 1; i < 129; i++) {
if (audio_process.sample_rate == AUD_SAMPRATE_7350 * i)
break;
if (audio_process.sample_rate == AUD_SAMPRATE_8000 * i)
break;
}
TRACE(1, "audio_process.sample_rate i:%d", i);
if (i == 129)
i = 6; // set default eq parameter;
sample_rate_hw_dac_iir = i * 8463.541666f; // AUD_SAMPRATE_8463
#else
sample_rate_hw_dac_iir = audio_process.sample_rate;
#endif
hw_iir_cfg_dac = hw_codec_iir_get_cfg(sample_rate_hw_dac_iir,
&audio_process.hw_dac_iir_cfg);
ASSERT(hw_iir_cfg_dac != NULL, "[%s] %d codec IIR parameter error!",
__func__, (uint32_t)hw_iir_cfg_dac);
// hal_codec_iir_dump(hw_iir_cfg_dac);
hw_codec_iir_set_cfg(hw_iir_cfg_dac, sample_rate_hw_dac_iir,
HW_CODEC_IIR_DAC);
audio_process.hw_dac_iir_enable = true;
}
#endif
return 0;
}
#endif
#ifdef AUDIO_EQ_HW_IIR_UPDATE_CFG
int audio_eq_hw_iir_callback(uint8_t *buf, uint32_t len) {
TRACE(3, "[%s] len = %d, sizeof(struct) = %d", __func__, len,
sizeof(IIR_CFG_T));
if (len != sizeof(IIR_CFG_T)) {
return 1;
}
memcpy(&audio_process.hw_iir_cfg, buf, sizeof(IIR_CFG_T));
TRACE(3, "band num:%d gain0:%d, gain1:%d",
(int32_t)audio_process.hw_iir_cfg.num,
(int32_t)(audio_process.hw_iir_cfg.gain0 * 10),
(int32_t)(audio_process.hw_iir_cfg.gain1 * 10));
for (uint8_t i = 0; i < audio_process.hw_iir_cfg.num; i++) {
TRACE(5, "band num:%d type %d gain:%d fc:%d q:%d", i,
(int32_t)(audio_process.hw_iir_cfg.param[i].type),
(int32_t)(audio_process.hw_iir_cfg.param[i].gain * 10),
(int32_t)(audio_process.hw_iir_cfg.param[i].fc * 10),
(int32_t)(audio_process.hw_iir_cfg.param[i].Q * 10));
}
#ifdef __HW_IIR_EQ_PROCESS__
{
HW_IIR_CFG_T *hw_iir_cfg = NULL;
#ifdef __AUDIO_RESAMPLE__
enum AUD_SAMPRATE_T sample_rate_hw_iir = AUD_SAMPRATE_50781;
#else
enum AUD_SAMPRATE_T sample_rate_hw_iir = audio_process.sample_rate;
#endif
hw_iir_cfg = hw_iir_get_cfg(sample_rate_hw_iir, &audio_process.hw_iir_cfg);
ASSERT(hw_iir_cfg != NULL, "[%s] %d codec IIR parameter error!", __func__,
hw_iir_cfg);
hw_iir_set_cfg(hw_iir_cfg);
audio_process.hw_iir_enable = true;
}
#endif
return 0;
}
#endif
#endif // #ifdef __PC_CMD_UART__
#ifdef USB_EQ_TUNING
int audio_eq_usb_iir_callback(uint8_t *buf, uint32_t len) {
IIR_CFG_T *cur_cfg;
TRACE(2, "usb_iir_cb: len=[%d - %d]", len, sizeof(IIR_CFG_T));
if (len != sizeof(IIR_CFG_T)) {
return 1;
}
cur_cfg = (IIR_CFG_T *)buf;
TRACE(2, "-> sample_rate[%d], num[%d]",
/*cur_cfg->samplerate,*/ audio_process.sample_rate, cur_cfg->num);
#if defined(AUDIO_EQ_SW_IIR_UPDATE_CFG)
audio_process.sw_iir_cfg.gain0 = cur_cfg->gain0;
audio_process.sw_iir_cfg.gain1 = cur_cfg->gain1;
#endif
#if defined(AUDIO_EQ_HW_DAC_IIR_UPDATE_CFG)
#if defined(AUDIO_EQ_SW_IIR_UPDATE_CFG)
audio_process.hw_dac_iir_cfg.gain0 = 0;
audio_process.hw_dac_iir_cfg.gain1 = 0;
#else
audio_process.hw_dac_iir_cfg.gain0 = cur_cfg->gain0;
audio_process.hw_dac_iir_cfg.gain1 = cur_cfg->gain1;
#endif
#endif
#if defined(AUDIO_EQ_HW_DAC_IIR_UPDATE_CFG)
if (cur_cfg->num > AUD_DAC_IIR_NUM_EQ) {
audio_process.hw_dac_iir_cfg.num = AUD_DAC_IIR_NUM_EQ;
} else {
audio_process.hw_dac_iir_cfg.num = cur_cfg->num;
}
TRACE(1, "-> hw_dac_iir_num[%d]", audio_process.hw_dac_iir_cfg.num);
#endif
#if defined(AUDIO_EQ_SW_IIR_UPDATE_CFG)
audio_process.sw_iir_cfg.num =
cur_cfg->num - audio_process.hw_dac_iir_cfg.num;
TRACE(1, "-> sw_iir_num[%d]", audio_process.sw_iir_cfg.num);
#endif
// TRACE(2,"-> iir_num[%d - %d]", audio_process.hw_dac_iir_cfg.num,
// audio_process.sw_iir_cfg.num);
#if defined(AUDIO_EQ_HW_DAC_IIR_UPDATE_CFG)
if (audio_process.hw_dac_iir_cfg.num) {
memcpy((void *)(&audio_process.hw_dac_iir_cfg.param[0]),
(void *)(&cur_cfg->param[0]),
audio_process.hw_dac_iir_cfg.num * sizeof(IIR_PARAM_T));
}
#endif
#if defined(AUDIO_EQ_SW_IIR_UPDATE_CFG)
if (audio_process.sw_iir_cfg.num) {
memcpy((void *)(&audio_process.sw_iir_cfg.param[0]),
(void *)(&cur_cfg->param[audio_process.hw_dac_iir_cfg.num]),
audio_process.sw_iir_cfg.num * sizeof(IIR_PARAM_T));
} else {
// set a default filter
audio_process.sw_iir_cfg.num = 1;
audio_process.sw_iir_cfg.param[0].fc = 1000.0;
audio_process.sw_iir_cfg.param[0].gain = 0.0;
audio_process.sw_iir_cfg.param[0].type = IIR_TYPE_PEAK;
audio_process.sw_iir_cfg.param[0].Q = 1.0;
}
#endif
if (audio_process.sample_rate) {
audio_process.update_cfg = true;
}
audio_process.eq_updated_cfg = true;
return 0;
}
void audio_eq_usb_eq_update(void) {
if (audio_process.update_cfg) {
#if defined(AUDIO_EQ_HW_DAC_IIR_UPDATE_CFG)
HW_CODEC_IIR_CFG_T *hw_iir_cfg_dac = NULL;
if (audio_process.hw_dac_iir_cfg.num) {
enum AUD_SAMPRATE_T sample_rate_hw_dac_iir;
#ifdef __AUDIO_RESAMPLE__
int i;
for (i = 1; i < 129; i++) {
if (audio_process.sample_rate == AUD_SAMPRATE_7350 * i)
break;
if (audio_process.sample_rate == AUD_SAMPRATE_8000 * i)
break;
}
TRACE(1, "audio_process.sample_rate i:%d", i);
if (i == 129)
i = 6; // set default eq parameter;
sample_rate_hw_dac_iir = i * 8463.541666f; // AUD_SAMPRATE_8463
#else
sample_rate_hw_dac_iir = audio_process.sample_rate;
#endif
hw_iir_cfg_dac = hw_codec_iir_get_cfg(sample_rate_hw_dac_iir,
&audio_process.hw_dac_iir_cfg);
hw_codec_iir_set_cfg(hw_iir_cfg_dac, sample_rate_hw_dac_iir,
HW_CODEC_IIR_DAC);
audio_process.hw_dac_iir_enable = true;
} else {
audio_process.hw_dac_iir_enable = false;
}
#endif
#if defined(AUDIO_EQ_SW_IIR_UPDATE_CFG)
iir_set_cfg(&audio_process.sw_iir_cfg);
audio_process.sw_iir_enable = true;
#endif
audio_process.update_cfg = false;
/*
TRACE(4,"USB EQ Update: en[%d-%d], num[%d-%d]",
audio_process.hw_dac_iir_enable,
audio_process.sw_iir_enable, audio_process.hw_dac_iir_cfg.num,
audio_process.sw_iir_cfg.num);
*/
}
}
#endif // USB_EQ_TUNING
typedef struct {
uint8_t type;
uint8_t maxEqBandNum;
uint16_t sample_rate_num;
uint8_t sample_rate[50];
} query_eq_info_t;
extern int getMaxEqBand(void);
extern int getSampleArray(uint8_t *buf, uint16_t *num);
extern void hal_cmd_set_res_playload(uint8_t *data, int len);
#define CMD_TYPE_QUERY_DUT_EQ_INFO 0x00
int audio_cmd_callback(uint8_t *buf, uint32_t len) {
uint8_t type;
// uint32_t* sample_rate;
// uint8_t* p;
query_eq_info_t info;
type = buf[0];
// p = buf + 1;
TRACE(2, "%s type: %d", __func__, type);
switch (type) {
case CMD_TYPE_QUERY_DUT_EQ_INFO:
info.type = CMD_TYPE_QUERY_DUT_EQ_INFO;
info.maxEqBandNum = getMaxEqBand();
getSampleArray(info.sample_rate, &info.sample_rate_num);
hal_cmd_set_res_playload((uint8_t *)&info, 4 + info.sample_rate_num * 4);
break;
default:
break;
}
return 0;
}
#ifdef AUDIO_SECTION_ENABLE
int audio_cfg_burn_callback(uint8_t *buf, uint32_t len) {
TRACE(3, "[%s] len = %d, sizeof(struct) = %d", __func__, len,
sizeof_audio_cfg());
if (len != sizeof_audio_cfg()) {
return 1;
}
int res = 0;
res = store_audio_cfg_into_audio_section((AUDIO_CFG_T *)buf);
if (res) {
TRACE(2, "[%s] ERROR: res = %d", __func__, res);
res += 100;
} else {
TRACE(1, "[%s] Store audio cfg into audio section!!!", __func__);
}
return res;
}
#endif
int audio_process_init(void) {
#ifdef __PC_CMD_UART__
hal_cmd_init();
#ifdef AUDIO_EQ_SW_IIR_UPDATE_CFG
hal_cmd_register("iir_eq", audio_eq_sw_iir_callback); // Will be removed
hal_cmd_register("sw_iir_eq", audio_eq_sw_iir_callback);
#endif
#ifdef AUDIO_EQ_HW_DAC_IIR_UPDATE_CFG
hal_cmd_register("iir_eq", audio_eq_hw_dac_iir_callback); // Will be removed
hal_cmd_register("dac_iir_eq", audio_eq_hw_dac_iir_callback);
#endif
#ifdef AUDIO_EQ_HW_IIR_UPDATE_CFG
hal_cmd_register("iir_eq", audio_eq_hw_iir_callback); // Will be removed
hal_cmd_register("hw_iir_eq", audio_eq_hw_iir_callback);
#endif
#ifdef AUDIO_EQ_HW_FIR_UPDATE_CFG
hal_cmd_register("fir_eq", audio_eq_hw_fir_callback);
#endif
#ifdef AUDIO_DRC_UPDATE_CFG
hal_cmd_register("drc", audio_drc_callback);
#endif
#ifdef AUDIO_DRC2_UPDATE_CFG
hal_cmd_register("limiter", audio_drc2_callback);
#endif
#ifdef AUDIO_SECTION_ENABLE
hal_cmd_register("burn", audio_cfg_burn_callback);
hal_cmd_register("audio_burn", audio_cfg_burn_callback);
#endif
hal_cmd_register("cmd", audio_cmd_callback);
hal_cmd_register("ping", audio_ping_callback);
#endif
#ifdef USB_EQ_TUNING
hal_cmd_init();
#if defined(AUDIO_EQ_SW_IIR_UPDATE_CFG) || \
defined(AUDIO_EQ_HW_DAC_IIR_UPDATE_CFG)
hal_cmd_register("iir_eq", audio_eq_usb_iir_callback);
#endif
hal_cmd_register("cmd", audio_cmd_callback);
hal_cmd_register("ping", audio_ping_callback);
#endif
// load default cfg
#ifdef AUDIO_EQ_SW_IIR_UPDATE_CFG
memcpy(&audio_process.sw_iir_cfg, audio_eq_sw_iir_cfg_list[0],
sizeof(IIR_CFG_T));
#endif
#ifdef AUDIO_EQ_HW_DAC_IIR_UPDATE_CFG
memcpy(&audio_process.hw_dac_iir_cfg, audio_eq_hw_dac_iir_cfg_list[0],
sizeof(IIR_CFG_T));
#endif
#ifdef AUDIO_EQ_HW_IIR_UPDATE_CFG
memcpy(&audio_process.hw_iir_cfg, audio_eq_hw_iir_cfg_list[0],
sizeof(IIR_CFG_T));
#endif
#ifdef AUDIO_EQ_HW_FIR_UPDATE_CFG
memcpy(&audio_process.hw_fir_cfg, audio_eq_hw_fir_cfg_list[0],
sizeof(FIR_CFG_T));
#endif
#ifdef AUDIO_DRC_UPDATE_CFG
memcpy(&audio_process.drc_cfg, &audio_drc_cfg, sizeof(DrcConfig));
#endif
#ifdef AUDIO_DRC2_UPDATE_CFG
memcpy(&audio_process.drc2_cfg, &audio_drc2_cfg, sizeof(LimiterConfig));
#endif
return 0;
}