KT25-1015_AC695x_SDK310/cpu/br23/audio_dec/audio_dec_spdif.c
2025-10-15 15:18:43 +08:00

981 lines
31 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.

/*
****************************************************************
*File : audio_spdif.c
*Note :
*
****************************************************************
*********************** spdif_dec ******************************/
#include "asm/includes.h"
#include "media/includes.h"
#include "system/includes.h"
#include "effectrs_sync.h"
#include "media/audio_eq_drc_apply.h"
#include "app_config.h"
#include "audio_config.h"
#include "audio_dec.h"
#include "app_config.h"
#include "app_main.h"
#include "audio_enc.h"
#include "clock_cfg.h"
#include "media/pcm_decoder.h"
#if TCFG_SPDIF_ENABLE
#define SPDIF_DEC_DATA_BUF_LEN 1024*4
struct s_spdif_decode {
struct pcm_decoder pcm_dec;
struct file_decoder file_dec;
struct audio_stream *audio_stream; // 音频流
struct audio_res_wait wait;
struct audio_mixer_ch mix_ch;
u32 coding_type;
struct audio_fmt fmt;
volatile u32 pcm_sr;
cbuffer_t dec_cbuf;
u8 dec_data_buf[SPDIF_DEC_DATA_BUF_LEN];
u8 status;
#if AUDIO_SURROUND_CONFIG
surround_hdl *surround; //环绕音效句柄
#endif
#if AUDIO_VBASS_CONFIG
struct aud_gain_process *vbass_prev_gain;
vbass_hdl *vbass; //虚拟低音句柄
#endif
struct audio_eq *high_bass;
struct audio_drc *hb_drc;//高低音后的drc
struct convert_data *hb_convert;
struct audio_eq *eq; //eq drc句柄
struct audio_drc *drc; // drc句柄
struct convert_data *convert;
struct audio_eq *eq2; //eq drc句柄
struct dynamic_eq_hdl *dy_eq;
struct convert_data *convert2;
struct aud_gain_process *gain;
#if TCFG_EQ_DIVIDE_ENABLE
struct audio_eq *eq_rl_rr; //eq drc句柄
struct audio_drc *drc_rl_rr; // drc句柄
struct convert_data *convert_rl_rr;
struct __stream_entry *rl_rr_mix;//双声道相加除2处理
struct aud_gain_process *gain_rl_rr;
struct audio_vocal_tract vocal_tract;//声道合并目标句柄
struct audio_vocal_tract_ch synthesis_ch_fl_fr;//声道合并句柄
struct audio_vocal_tract_ch synthesis_ch_rl_rr;//声道合并句柄
struct channel_switch *ch_switch;//声道变换
#endif
};
static void reset_pcm_sample_rate(u32 sr);
int spdif_dec_open(struct audio_fmt fmt);
void spdif_dec_close(void);
struct audio_spdif_hdl spdif_slave_hdl;
struct s_spdif_decode *spdif_dec_hdl = NULL;
int spdif_non_linear_packet(u16 *pkt, u16 pkt_len)
{
enum IEC61937DataType data_type;
u16 search_index = 0;
int data_cp_begin_idx = 0;
int data_cp_len = 0;
u16 *data = pkt;
u16 *data_ptr = NULL;
int zero_cnt = 0;
u32 state = 0;
int pkt_size_bits, offset, skip_len;
if (spdif_slave_hdl.length_code > 0) {
if (spdif_slave_hdl.length_code >= SPDIF_DATA_DAM_LEN * 2) {
data_cp_begin_idx = 0;
data_cp_len = SPDIF_DATA_DAM_LEN * 2;
spdif_slave_hdl.length_code -= data_cp_len;
} else {
data_cp_begin_idx = 0;
data_cp_len = spdif_slave_hdl.length_code;
spdif_slave_hdl.length_code = 0;
}
//写入解码cbuf
/* int spdif_dec_write_data(s16 *data, int len) */
spdif_dec_write_data(&data[data_cp_begin_idx], data_cp_len * 2);
if (spdif_slave_hdl.length_code != 0) {
return 0;
} else {
search_index = data_cp_len;
}
}
if (spdif_slave_hdl.find_sync_word != 0) {
printf("[last:%d,%x]", search_index, data[search_index]);
if (data[search_index] == SYNCWORD2) {
puts("3");
} else {
puts("M");
spdif_slave_hdl.find_sync_word = 0;
return -1;
}
} else {
while (search_index < pkt_len) {
if (data[search_index] == SYNCWORD1) {
spdif_slave_hdl.find_sync_word = 1;
}
if (++search_index >= pkt_len) {
return -1;
}
if (spdif_slave_hdl.find_sync_word) {
if ((data[search_index] == SYNCWORD2) && (data[search_index - 1] == SYNCWORD1)) {
break;
} else {
spdif_slave_hdl.find_sync_word = 0;
}
}
}
}
spdif_slave_hdl.find_sync_word = 0;
data_type = data[++search_index];
spdif_slave_hdl.decoder_type = data_type & 0xff;
pkt_size_bits = data[++search_index];
spdif_slave_hdl.length_code = (pkt_size_bits >> 3) >> 1; //16bit
if (pkt_size_bits % 16) {
printf("packet not endinf at a 16-bit boundary %d-%d \n", pkt_size_bits, search_index);
for (int i = 0; i < pkt_len; i++) {
printf("%x ", data[i]);
}
}
++search_index;
data_cp_len = pkt_len - search_index;
skip_len = 2048 - (spdif_slave_hdl.length_code << 1) - BURST_HEADER_SZIE;
if (data_cp_len) {
spdif_dec_write_data(&data[search_index], data_cp_len * 2);
data_cp_len = 0;
}
return 0;
}
void reset_data_buf(void)
{
if (!spdif_dec_hdl) {
return;
}
cbuf_clear(&spdif_dec_hdl->dec_cbuf);
}
#define SAMPLE_RATE_TABLE_SIZE 14
static u8 old_samplerate_index = 6; /*位置记得要跟默认采样率对应*/
u16 spdif_sample_rate_table[SAMPLE_RATE_TABLE_SIZE] = {
80,
110,
160,
221,
240,
320,
441,
480,
504,
640,
882,
960,
1764,
1920,
};
#define SPDIF_DEFAULT_OUT_SAMPLE_RATE 44100
static u32 cal_samplerate(void)
{
static u32 pre_sr_cnt = 0;
static u32 sr_cnt = 0;
sr_cnt = JL_SS->SR_CNT;
u8 search_index = 0, i = 0;
u32 tick_result = 0 ;
tick_result = (((clk_get("lsb") / 100 * SPDIF_DATA_DAM_LEN)) / sr_cnt);
for (i = 0; i < SAMPLE_RATE_TABLE_SIZE; i++) {
if ((tick_result > (spdif_sample_rate_table[i] - 20)) && (tick_result < (spdif_sample_rate_table[i] + 20))) {
search_index = i;
}
}
if ((search_index != 0) && (old_samplerate_index != search_index)) {
printf("\n\n spdif SET src param %d %d--- \n\n", spdif_sample_rate_table[search_index], tick_result);
reset_data_buf();
reset_pcm_sample_rate(spdif_sample_rate_table[search_index] * 100);
old_samplerate_index = search_index;
}
return 0;
}
___interrupt
static void spdif_isr_handler()
{
int index = 0;
s32 *ptr;
u8 *info_ptr = NULL;
s16 data_ptr[SPDIF_DATA_DAM_LEN * SPDIF_CHANNEL_NUMBER];
u16 *u_data_ptr = (u16 *)data_ptr;
/* putchar('A'); */
if (I_PND) { //information pending
I_PND_CLR;
index = !(USING_INF_BUF_INDEX >> 13);
info_ptr = (u8 *) &spdif_slave_hdl.p_spdif_info_buf[index];
for (int i = 0; i < SPDIF_INFO_LEN; i++) {
if (!(info_ptr[0]&INFO_VALIDITY_BIT)) {
break;
}
spdif_slave_hdl.validity_bit_flag = 1;
}
}
if (ERROR_VALUE) { // some error flag
if (ERROR_VALUE & (BIT(8) | BIT(9))) {//块/帧错误
memset(&spdif_slave_hdl.p_spdif_data_buf[0], 0x0, SPDIF_DATA_DAM_LEN * SPDIF_CHANNEL_NUMBER);
memset(&spdif_slave_hdl.p_spdif_data_buf[1], 0x0, SPDIF_DATA_DAM_LEN * SPDIF_CHANNEL_NUMBER);
}
if (JL_SS->CON & BIT(11)) {//电平长度接收错误
//模块复位
putchar('E');
audio_spdif_slave_close(&spdif_slave_hdl);
spdif_slave_hdl.error_flag = 1;
ERR_CLR;
return;
}
ERR_CLR;
}
if (spdif_slave_hdl.error_flag) {
return;
}
if (D_PND) { //data pending
D_PND_CLR;
if (spdif_slave_hdl.validity_bit_flag) { //DST
spdif_slave_hdl.validity_bit_flag = 0;
index = !(USING_BUF_INDEX >> 12);
ptr = (s32 *)spdif_slave_hdl.p_spdif_data_buf[index];
for (int i = 0; i < SPDIF_DATA_DAM_LEN * 2; i += 2) {
u_data_ptr[i] = (u16)(ptr[i] >> 8);
u_data_ptr[i + 1] = (u16)(ptr[i + 1] >> 8);
}
if (!spdif_dec_hdl) {
#if 0
struct audio_fmt fmt;
fmt.channel = 2;
fmt.coding_type = AUDIO_CODING_DTS;
fmt.sample_rate = SPDIF_DEFAULT_OUT_SAMPLE_RATE;
spdif_dec_open(fmt);
#endif
audio_spdif_slave_close(&spdif_slave_hdl);
spdif_slave_hdl.error_flag = 2;
} else if (spdif_dec_hdl->fmt.coding_type != AUDIO_CODING_DTS) {
putchar('d');
//模块复位
audio_spdif_slave_close(&spdif_slave_hdl);
spdif_slave_hdl.error_flag = 2;
return;
}
if (spdif_dec_hdl && (spdif_slave_hdl.status == SPDIF_STATE_START)) {
spdif_non_linear_packet(u_data_ptr, SPDIF_DATA_DAM_LEN * 2);
}
/* putchar('D'); */
return;
} else { //PCM
if (!spdif_dec_hdl) {
#if 0
putchar('p');
struct audio_fmt fmt;
fmt.channel = 2;
fmt.coding_type = AUDIO_CODING_PCM;
fmt.sample_rate = SPDIF_DEFAULT_OUT_SAMPLE_RATE;
spdif_dec_open(fmt);
#endif
audio_spdif_slave_close(&spdif_slave_hdl);
spdif_slave_hdl.error_flag = 1;
return;
} else if (spdif_dec_hdl->fmt.coding_type != AUDIO_CODING_PCM) {
putchar('p');
audio_spdif_slave_close(&spdif_slave_hdl);
spdif_slave_hdl.error_flag = 1;
return;
}
/* putchar('D'); */
cal_samplerate();
index = !(USING_BUF_INDEX >> 12);
ptr = (s32 *) spdif_slave_hdl.p_spdif_data_buf[index];
for (int i = 0; i < SPDIF_DATA_DAM_LEN * 2; i += 2) {
data_ptr[i] = (s16)(ptr[i] >> 8);
data_ptr[i + 1] = (s16)(ptr[i + 1] >> 8);
}
if ((spdif_dec_hdl) && (spdif_slave_hdl.status == SPDIF_STATE_START)) {
int wlen = spdif_dec_write_data(data_ptr, SPDIF_DATA_DAM_LEN * SPDIF_CHANNEL_NUMBER * 2);
if (wlen == 0) {
/* printf(" wlen = 0"); */
}
}
memset(spdif_slave_hdl.p_spdif_data_buf[index], 0, SPDIF_DATA_DAM_LEN * SPDIF_CHANNEL_NUMBER * 2);
}
}
if (CSB_PND) {
CSB_PND_CLR;
}
}
// 写入spdif数据
/* int spdif_dec_write_data(s16 *data, int len) */
int spdif_dec_write_data(void *data, int len)
{
if (!spdif_dec_hdl) {
return 0;
}
u16 wlen = cbuf_write(&spdif_dec_hdl->dec_cbuf, data, len);
if (wlen) {
audio_decoder_resume(&spdif_dec_hdl->pcm_dec.decoder);
}
/* printf("wl:%d ", wlen); */
return wlen;
}
static void spdif_dec_release(void)
{
audio_decoder_task_del_wait(&decode_task, &spdif_dec_hdl->wait);
if (spdif_dec_hdl) {
clock_remove(SPDIF_CLK);
free(spdif_dec_hdl);
spdif_dec_hdl = NULL;
}
}
static void file_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv)
{
switch (argv[0]) {
case AUDIO_DEC_EVENT_END:
printf("\n--func=%s\n", __FUNCTION__);
spdif_dec_close();
break;
}
}
/*----------------------------------------------------------------------------*/
/**@brief 文件指针定位
@param *decoder: 解码器句柄
@param offset: 定位偏移
@param seek_mode: 定位类型
@return 0成功
@return 非0错误
@note
*/
/*----------------------------------------------------------------------------*/
static int spdif_file_seek(struct audio_decoder *decoder, u32 offset, int seek_mode)
{
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 读取文件数据
@param *decoder: 解码器句柄
@param *buf: 数据
@param len: 数据长度
@return >=0读到的数据长度
@return <0错误
@note
*/
/*----------------------------------------------------------------------------*/
static int spdif_file_read(struct audio_decoder *decoder, void *buf, u32 len)
{
int rlen;
rlen = cbuf_read(&spdif_dec_hdl->dec_cbuf, buf, len);
return rlen;
}
static const struct audio_dec_input file_input = {
.coding_type = AUDIO_CODING_DTS,
.data_type = AUDIO_INPUT_FILE,
.ops = {
.file = {
.fread = spdif_file_read,
.fseek = spdif_file_seek,
}
}
};
static int spdif_dec_read(void *hdl, void *buf, int len)
{
int rlen = 0;
rlen = cbuf_read(&spdif_dec_hdl->dec_cbuf, buf, len);
/* printf("rlen:%d\n",rlen); */
return rlen;
}
int spdif_data_size(void *hdl)
{
struct s_spdif_decode *spdif_hdl = (struct s_spdif_decode *)hdl;
return cbuf_get_data_size(&spdif_hdl->dec_cbuf);
}
int spdif_data_total(void *hdl)
{
struct s_spdif_decode *spdif_hdl = (struct s_spdif_decode *)hdl;
return spdif_hdl->dec_cbuf.total_len;
}
static void reset_pcm_sample_rate(u32 sr)
{
spdif_dec_hdl->pcm_sr = sr;
}
static u32 get_pcm_sample_rate(void)
{
/* printf("[%d]",spdif_dec_hdl->pcm_sr); */
return spdif_dec_hdl->pcm_sr;
}
/*----------------------------------------------------------------------------*/
/**@brief pcm解码数据输出
@param *entry: 音频流句柄
@param *in: 输入信息
@param *out: 输出信息
@return 输出长度
@note *out未使用
*/
/*----------------------------------------------------------------------------*/
static int pcm_dec_data_handler(struct audio_stream_entry *entry,
struct audio_data_frame *in,
struct audio_data_frame *out)
{
struct audio_decoder *decoder = container_of(entry, struct audio_decoder, entry);
struct pcm_decoder *pcm_dec = container_of(decoder, struct pcm_decoder, decoder);
if (in->offset == 0) {
in->sample_rate = get_pcm_sample_rate();
}
audio_stream_run(&decoder->entry, in);
return decoder->process_len;
}
static void pcm_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv)
{
}
/*----------------------------------------------------------------------------*/
/**@brief pcm解码数据流激活
@param *p: 私有句柄
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void dec_out_stream_resume(void *p)
{
struct s_spdif_decode *dec = (struct s_spdif_decode *)p;
audio_decoder_resume(&dec->pcm_dec.decoder);
}
int spdif_dec_start(void)
{
int err = 0;
u8 ch_num = 0;
struct audio_fmt f;
if (!spdif_dec_hdl) {
return -EINVAL;
}
struct s_spdif_decode *dec = spdif_dec_hdl;
if (dec->fmt.coding_type == AUDIO_CODING_DTS) {
puts("dts \n");//DTS未测试
return -EINVAL;
err = file_decoder_open(&dec->file_dec, &file_input, &decode_task, NULL, 0);
if (err) {
return err;
}
file_decoder_set_event_handler(&dec->file_dec, file_dec_event_handler, 0);
} else {
puts("pcm \n");
err = pcm_decoder_open(&dec->pcm_dec, &decode_task);
if (err) {
return err;
}
pcm_decoder_set_event_handler(&dec->pcm_dec, pcm_dec_event_handler, 0);
pcm_decoder_set_read_data(&dec->pcm_dec, spdif_dec_read, dec);
pcm_decoder_set_data_handler(&dec->pcm_dec, pcm_dec_data_handler);
}
printf("\n--func=%s\n", __FUNCTION__);
audio_mode_main_dec_open(AUDIO_MODE_MAIN_STATE_DEC_SPDIF);
audio_mixer_ch_open_head(&dec->mix_ch, &mixer);
audio_mixer_ch_set_no_wait(&dec->mix_ch, 1, 10); // 超时自动丢数
/* audio_mixer_ch_set_src(&dec->mix_ch, 1, 0); */
#if 1
struct audio_mixer_ch_sync_info info = {0};
info.priv = dec;
info.get_total = spdif_data_total;
info.get_size = spdif_data_size;
audio_mixer_ch_set_sync(&dec->mix_ch, &info, 1, 1);
#endif
ch_num = audio_output_channel_num();
u16 sample_rate = dec->fmt.sample_rate;
#if AUDIO_SURROUND_CONFIG
//环绕音效
dec->surround = surround_open_demo(AEID_MUSIC_SURROUND, dec->pcm_dec.output_ch_type);
#endif
#if AUDIO_VBASS_CONFIG
dec->vbass_prev_gain = audio_gain_open_demo(AEID_MUSIC_VBASS_PREV_GAIN, ch_num);
//虚拟低音
dec->vbass = audio_vbass_open_demo(AEID_MUSIC_VBASS, sample_rate, ch_num);
#endif
dec->high_bass = high_bass_eq_open(sample_rate, ch_num);
dec->hb_drc = high_bass_drc_open(sample_rate, ch_num);
if (dec->hb_drc && dec->hb_drc->run32bit) {
dec->hb_convert = convet_data_open(0, 512);
}
#if TCFG_EQ_ENABLE && TCFG_SPDIF_MODE_EQ_ENABLE
dec->eq = music_eq_open(sample_rate, ch_num);// eq
#if TCFG_DRC_ENABLE && TCFG_SPDIF_MODE_DRC_ENABLE
dec->drc = music_drc_open(sample_rate, ch_num);//drc
#endif/*TCFG_SPDIF_MODE_DRC_ENABLE*/
if (dec->eq && dec->eq->out_32bit) {
dec->convert = convet_data_open(0, 512);
}
#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE
dec->eq2 = music_eq2_open(sample_rate, ch_num);// eq
dec->dy_eq = audio_dynamic_eq_ctrl_open(sample_rate, ch_num);//动态eq
dec->convert2 = convet_data_open(0, 512);
#endif/*TCFG_DYNAMIC_EQ_ENABLE*/
dec->gain = audio_gain_open_demo(AEID_MUSIC_GAIN, dec->file_dec.output_ch_num);
#endif/*TCFG_SPDIF_MODE_EQ_ENABLE*/
#if TCFG_EQ_DIVIDE_ENABLE
dec->eq_rl_rr = music_eq_rl_rr_open(sample_rate, ch_num);// eq
#if TCFG_DRC_ENABLE && TCFG_BT_MUSIC_DRC_ENABLE
dec->drc_rl_rr = music_drc_rl_rr_open(sample_rate, ch_num);//drc
#endif
if (dec->eq_rl_rr && dec->eq_rl_rr->out_32bit) {
dec->convert_rl_rr = convet_data_open(0, 512);
}
#if defined(SOUND_TRACK_2_P_X_CH_CONFIG) && SOUND_TRACK_2_P_X_CH_CONFIG
#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH)
dec->rl_rr_mix = stream_entry_open(NULL, stream_rl_rr_mix_data_handler, 0);
#endif
#endif
dec->gain_rl_rr = audio_gain_open_demo(AEID_MUSIC_RL_GAIN, ch_num);
if (dec->eq_rl_rr) {
audio_vocal_tract_open(&dec->vocal_tract, AUDIO_SYNTHESIS_LEN);
{
u8 entry_cnt = 0;
struct audio_stream_entry *entries[8] = {NULL};
entries[entry_cnt++] = &dec->vocal_tract.entry;
entries[entry_cnt++] = &dec->mix_ch.entry;
dec->vocal_tract.stream = audio_stream_open(&dec->vocal_tract, audio_vocal_tract_stream_resume);
audio_stream_add_list(dec->vocal_tract.stream, entries, entry_cnt);
}
audio_vocal_tract_synthesis_open(&dec->synthesis_ch_fl_fr, &dec->vocal_tract, FL_FR);
audio_vocal_tract_synthesis_open(&dec->synthesis_ch_rl_rr, &dec->vocal_tract, RL_RR);
} else {
dec->ch_switch = channel_switch_open(AUDIO_CH_QUAD, AUDIO_SYNTHESIS_LEN / 2);
}
#ifdef CONFIG_MIXER_CYCLIC
audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 0, BIT(0));
audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 1, BIT(1));
audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 2, BIT(2));
audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 3, BIT(3));
#endif
#endif
// 数据流串联
struct audio_stream_entry *entries[32] = {NULL};
u8 entry_cnt = 0;
u8 rl_rr_entry_start = 0;
if (dec->fmt.coding_type == AUDIO_CODING_DTS) {
entries[entry_cnt++] = &dec->file_dec.decoder.entry;
} else {
entries[entry_cnt++] = &dec->pcm_dec.decoder.entry;
}
#if AUDIO_SURROUND_CONFIG
if (dec->surround) {
entries[entry_cnt++] = &dec->surround->entry;
}
#endif
#if AUDIO_VBASS_CONFIG
if (dec->vbass_prev_gain) {
entries[entry_cnt++] = &dec->vbass_prev_gain->entry;
}
if (dec->vbass) {
entries[entry_cnt++] = &dec->vbass->entry;
}
#endif
if (dec->high_bass) { //高低音
entries[entry_cnt++] = &dec->high_bass->entry;
}
if (dec->hb_drc) { //高低音后drc
entries[entry_cnt++] = &dec->hb_drc->entry;
if (dec->hb_convert) {
entries[entry_cnt++] = &dec->hb_convert->entry;
}
}
rl_rr_entry_start = entry_cnt - 1;//记录eq的上一个节点
#if TCFG_EQ_ENABLE && TCFG_SPDIF_MODE_EQ_ENABLE
if (dec->eq) {
entries[entry_cnt++] = &dec->eq->entry;
if (dec->drc) {
entries[entry_cnt++] = &dec->drc->entry;
}
if (dec->convert) {
entries[entry_cnt++] = &dec->convert->entry;
}
#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE
if (dec->eq2) {
entries[entry_cnt++] = &dec->eq2->entry;
}
if (dec->dy_eq && dec->dy_eq->dy_eq) {
entries[entry_cnt++] = &dec->dy_eq->dy_eq->entry;
}
if (dec->convert2) {
entries[entry_cnt++] = &dec->convert2->entry;
}
#endif
if (dec->gain) {
entries[entry_cnt++] = &dec->gain->entry;
}
}
#endif
#if TCFG_EQ_DIVIDE_ENABLE
if (dec->eq_rl_rr) {
entries[entry_cnt++] = &dec->synthesis_ch_fl_fr.entry;//四声道eq独立时该节点后不接节点
} else {
if (dec->ch_switch) {
entries[entry_cnt++] = &dec->ch_switch->entry;
}
entries[entry_cnt++] = &dec->mix_ch.entry;
}
#else
entries[entry_cnt++] = &dec->mix_ch.entry;
#endif
dec->audio_stream = audio_stream_open(dec, dec_out_stream_resume);
audio_stream_add_list(dec->audio_stream, entries, entry_cnt);
#if TCFG_EQ_DIVIDE_ENABLE
struct audio_stream_entry *rl_rr_entries[8] = {NULL};
entry_cnt = 0;
if (dec->eq_rl_rr) { //接在eq_drc的上一个节点
rl_rr_entries[entry_cnt++] = entries[rl_rr_entry_start];
rl_rr_entries[entry_cnt++] = &dec->eq_rl_rr->entry;
if (dec->drc_rl_rr) {
rl_rr_entries[entry_cnt++] = &dec->drc_rl_rr->entry;
}
if (dec->convert_rl_rr) {
rl_rr_entries[entry_cnt++] = &dec->convert_rl_rr->entry;
}
#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH)
if (dec->rl_rr_mix) {
rl_rr_entries[entry_cnt++] = &dec->rl_rr_mix->entry;
}
#endif
if (dec->gain_rl_rr) {
rl_rr_entries[entry_cnt++] = &dec->gain_rl_rr->entry;
}
rl_rr_entries[entry_cnt++] = &dec->synthesis_ch_rl_rr.entry;//必须是最后一个
for (int i = 0; i < (entry_cnt - 1); i++) {
audio_stream_add_entry(rl_rr_entries[i], rl_rr_entries[i + 1]);
}
}
#endif
audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC);
err = audio_decoder_start(&dec->pcm_dec.decoder);
if (err) {
#if AUDIO_SURROUND_CONFIG
surround_close_demo(dec->surround);
#endif
#if AUDIO_VBASS_CONFIG
audio_gain_close_demo(dec->vbass_prev_gain);
audio_vbass_close_demo(dec->vbass);
#endif
high_bass_eq_close(dec->high_bass);
high_bass_drc_close(dec->hb_drc);
convet_data_close(dec->hb_convert);
#if TCFG_EQ_ENABLE && TCFG_SPDIF_MODE_EQ_ENABLE
music_eq_close(dec->eq);
#if TCFG_DRC_ENABLE && TCFG_SPDIF_MODE_DRC_ENABLE
music_drc_close(dec->drc);
#endif
convet_data_close(dec->convert);
#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE
music_eq2_close(dec->eq2);
audio_dynamic_eq_ctrl_close(dec->dy_eq);
convet_data_close(dec->convert2);
#endif
audio_gain_close_demo(dec->gain);
#endif
#if TCFG_EQ_DIVIDE_ENABLE
music_eq_rl_rr_close(dec->eq_rl_rr);
music_drc_rl_rr_close(dec->drc_rl_rr);
convet_data_close(dec->convert_rl_rr);
#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH)
stream_entry_close(&dec->rl_rr_mix);
#endif
audio_gain_close_demo(dec->gain_rl_rr);
audio_vocal_tract_synthesis_close(&dec->synthesis_ch_fl_fr);
audio_vocal_tract_synthesis_close(&dec->synthesis_ch_rl_rr);
audio_vocal_tract_close(&dec->vocal_tract);
channel_switch_close(&dec->ch_switch);
#endif
return err;
}
clock_set_cur();
dec->status = SPDIF_STATE_START;
return 0;
}
int spdif_dec_stop(void)
{
if (spdif_dec_hdl) {
spdif_dec_hdl->status = SPDIF_STATE_STOP;
pcm_decoder_close(&spdif_dec_hdl->pcm_dec);
struct s_spdif_decode *dec = spdif_dec_hdl;
#if AUDIO_SURROUND_CONFIG
surround_close_demo(dec->surround);
#endif
#if AUDIO_VBASS_CONFIG
audio_gain_close_demo(dec->vbass_prev_gain);
audio_vbass_close_demo(dec->vbass);
#endif
high_bass_eq_close(dec->high_bass);
high_bass_drc_close(dec->hb_drc);
convet_data_close(dec->hb_convert);
#if TCFG_EQ_ENABLE && TCFG_SPDIF_MODE_EQ_ENABLE
music_eq_close(dec->eq);
#if TCFG_DRC_ENABLE && TCFG_SPDIF_MODE_DRC_ENABLE
music_drc_close(dec->drc);
#endif
convet_data_close(dec->convert);
#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE
music_eq2_close(dec->eq2);
audio_dynamic_eq_ctrl_close(dec->dy_eq);
convet_data_close(dec->convert2);
#endif
audio_gain_close_demo(dec->gain);
#endif
#if TCFG_EQ_DIVIDE_ENABLE
music_eq_rl_rr_close(spdif_dec_hdl->eq_rl_rr);
music_drc_rl_rr_close(spdif_dec_hdl->drc_rl_rr);
convet_data_close(spdif_dec_hdl->convert_rl_rr);
#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH)
stream_entry_close(&spdif_dec_hdl->rl_rr_mix);
#endif
audio_gain_close_demo(spdif_dec_hdl->gain_rl_rr);
audio_vocal_tract_synthesis_close(&spdif_dec_hdl->synthesis_ch_fl_fr);
audio_vocal_tract_synthesis_close(&spdif_dec_hdl->synthesis_ch_rl_rr);
audio_vocal_tract_close(&spdif_dec_hdl->vocal_tract);
channel_switch_close(&spdif_dec_hdl->ch_switch);
#endif
audio_mixer_ch_close(&spdif_dec_hdl->mix_ch);
if (spdif_dec_hdl->audio_stream) {
audio_stream_close(spdif_dec_hdl->audio_stream);
spdif_dec_hdl->audio_stream = 0;
}
}
return 0;
}
static int spdif_wait_res_handler(struct audio_res_wait *wait, int event)
{
int err = 0;
if (event == AUDIO_RES_GET) {
err = spdif_dec_start();
} else if (event == AUDIO_RES_PUT) {
err = spdif_dec_stop();
}
return err;
}
static void spdif_status_check(void *priv)
{
static u8 cnt = 0;
if (spdif_dec_hdl && (spdif_slave_hdl.status == SPDIF_STATE_START || spdif_slave_hdl.status == SPDIF_STATE_STOP)) {
/* printf("spdif status \n"); */
if (spdif_slave_hdl.error_flag == 1) {
printf("spdif reset \n");
/* audio_spdif_slave_close(&spdif_slave_hdl); */
spdif_dec_close();
struct audio_fmt fmt;
fmt.channel = 2;
fmt.coding_type = AUDIO_CODING_PCM;
fmt.sample_rate = SPDIF_DEFAULT_OUT_SAMPLE_RATE;
spdif_dec_open(fmt);
audio_spdif_slave_open(&spdif_slave_hdl);
audio_spdif_slave_start(&spdif_slave_hdl);
spdif_slave_hdl.error_flag = 0;
} else if (spdif_slave_hdl.error_flag == 2) {
printf("spdif reset \n");
/* audio_spdif_slave_close(&spdif_slave_hdl); */
spdif_dec_close();
struct audio_fmt fmt;
fmt.channel = 2;
fmt.coding_type = AUDIO_CODING_DTS;
fmt.sample_rate = SPDIF_DEFAULT_OUT_SAMPLE_RATE;
spdif_dec_open(fmt);
audio_spdif_slave_open(&spdif_slave_hdl);
audio_spdif_slave_start(&spdif_slave_hdl);
spdif_slave_hdl.error_flag = 0;
} else {
#if 10
if (spdif_dec_hdl->status == SPDIF_STATE_START) {
if (spdif_data_size(spdif_dec_hdl) == 0) {
if (cnt < 6) {
cnt++;
}
if (cnt == 5) {
audio_mixer_ch_pause(&spdif_dec_hdl->mix_ch, 1);
audio_decoder_resume_all(&decode_task);
}
} else {
if (cnt > 4) {
audio_mixer_ch_pause(&spdif_dec_hdl->mix_ch, 0);
audio_decoder_resume_all(&decode_task);
}
cnt = 0;
}
}
#endif
}
}
}
///*----------------------------------------------------------------------------*/
/**@brief spdif 硬件设置
@param 无
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
static void _spdif_open(void)
{
#if TCFG_SPDIF_OUTPUT_ENABLE
spdif_slave_hdl.output_port = SPDIF_OUT_PORT_A;//PB11
#endif
spdif_slave_hdl.input_port = SPDIF_IN_PORT_A;//PA9
audio_spdif_slave_open(&spdif_slave_hdl);
audio_spdif_slave_start(&spdif_slave_hdl);
#if TCFG_HDMI_ARC_ENABLE
extern void hdmi_cec_init(void);
hdmi_cec_init();
#endif
}
void spdif_init(void)
{
audio_spdif_slave_init(&spdif_slave_hdl);
request_irq(IRQ_SPDIF_IDX, 2, spdif_isr_handler, 0);
sys_timer_add(NULL, spdif_status_check, 250);
#if (TCFG_APP_SPDIF_EN == 0)
spdif_dec_init();
_spdif_open(); //for test
#endif
}
void spdif_dec_init(void)
{
struct audio_fmt fmt;
fmt.channel = 2;
fmt.coding_type = AUDIO_CODING_PCM;
fmt.sample_rate = SPDIF_DEFAULT_OUT_SAMPLE_RATE;
spdif_dec_open(fmt);
}
int spdif_dec_open(struct audio_fmt fmt)
{
int err;
if (spdif_dec_hdl) {
return -1;
}
spdif_dec_hdl = zalloc(sizeof(struct s_spdif_decode));
if (!spdif_dec_hdl) {
return -ENOMEM;
}
clock_add(SPDIF_CLK);
cbuf_init(&spdif_dec_hdl->dec_cbuf, spdif_dec_hdl->dec_data_buf, SPDIF_DEC_DATA_BUF_LEN);
spdif_dec_hdl->fmt.channel = fmt.channel;
spdif_dec_hdl->fmt.coding_type = fmt.coding_type;
spdif_dec_hdl->fmt.sample_rate = fmt.sample_rate;
spdif_dec_hdl->fmt.coding_type = fmt.coding_type;
spdif_dec_hdl->coding_type = fmt.coding_type;
if (fmt.coding_type == AUDIO_CODING_DTS) {
spdif_dec_hdl->file_dec.ch_type = AUDIO_CH_MAX;
spdif_dec_hdl->file_dec.output_ch_num = audio_output_channel_num();
spdif_dec_hdl->file_dec.output_ch_type = audio_output_channel_type();
} else {
old_samplerate_index = 6;
spdif_dec_hdl->pcm_dec.ch_num = fmt.channel;
spdif_dec_hdl->pcm_dec.output_ch_num = audio_output_channel_num();
spdif_dec_hdl->pcm_dec.output_ch_type = audio_output_channel_type();
spdif_dec_hdl->pcm_dec.sample_rate = fmt.sample_rate;
spdif_dec_hdl->pcm_sr = fmt.sample_rate;
}
spdif_dec_hdl->wait.priority = 4;
spdif_dec_hdl->wait.preemption = 0;
spdif_dec_hdl->wait.protect = 1;//1 叠加模式
spdif_dec_hdl->wait.snatch_same_prio = 1;
spdif_dec_hdl->wait.handler = spdif_wait_res_handler;
spdif_dec_hdl->status = SPDIF_STATE_OPEN;
err = audio_decoder_task_add_wait(&decode_task, &spdif_dec_hdl->wait);
return err;
}
void spdif_dec_close(void)
{
printf("\n--func1=%s\n", __FUNCTION__);
if (!spdif_dec_hdl) {
return;
}
spdif_dec_stop();
spdif_dec_release();
clock_set_cur();
}
bool spdif_dec_check(void)
{
if (spdif_dec_hdl) {
return true;
}
return false;
}
#endif // TCFG_SPDIF_ENABLE
/***********************spdif dec end*****************************/