927 lines
28 KiB
C
927 lines
28 KiB
C
|
/*
|
|||
|
****************************************************************
|
|||
|
*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;
|
|||
|
NOISEGATE_API_STRUCT *ns_gate;
|
|||
|
vbass_hdl *vbass; //虚拟低音句柄
|
|||
|
#endif
|
|||
|
|
|||
|
#if TCFG_EQ_ENABLE && TCFG_AUDIO_OUT_EQ_ENABLE
|
|||
|
struct audio_eq *high_bass;
|
|||
|
struct audio_drc *hb_drc;//高低音后的drc
|
|||
|
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
|
|||
|
struct convert_data *hb_convert;
|
|||
|
#endif
|
|||
|
#endif
|
|||
|
|
|||
|
struct audio_eq *eq; //eq drc句柄
|
|||
|
struct audio_drc *drc; // drc句柄
|
|||
|
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
|
|||
|
struct convert_data *convert;
|
|||
|
#endif
|
|||
|
#if defined(MUSIC_EXT_EQ_AFTER_DRC) && MUSIC_EXT_EQ_AFTER_DRC
|
|||
|
struct audio_eq *ext_eq; //eq drc句柄 扩展eq
|
|||
|
#endif
|
|||
|
#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE
|
|||
|
struct audio_eq *eq2; //eq drc句柄
|
|||
|
struct dynamic_eq_hdl *dy_eq;
|
|||
|
struct convert_data *convert2;
|
|||
|
#endif
|
|||
|
#if defined(TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE) && TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE
|
|||
|
struct aud_gain_process *gain;
|
|||
|
#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->ns_gate = audio_noisegate_open_demo(AEID_MUSIC_NS_GATE, sample_rate, ch_num);
|
|||
|
//虚拟低音
|
|||
|
dec->vbass = audio_vbass_open_demo(AEID_MUSIC_VBASS, sample_rate, ch_num);
|
|||
|
#endif
|
|||
|
|
|||
|
#if TCFG_EQ_ENABLE && TCFG_AUDIO_OUT_EQ_ENABLE
|
|||
|
dec->high_bass = high_bass_eq_open(sample_rate, ch_num);
|
|||
|
dec->hb_drc = high_bass_drc_open(sample_rate, ch_num);
|
|||
|
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
|
|||
|
if (dec->hb_drc && dec->hb_drc->run32bit) {
|
|||
|
dec->hb_convert = convet_data_open(0, 512);
|
|||
|
}
|
|||
|
#endif
|
|||
|
#endif
|
|||
|
|
|||
|
#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 defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
|
|||
|
if (dec->eq && dec->eq->out_32bit) {
|
|||
|
dec->convert = convet_data_open(0, 512);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
#if defined(MUSIC_EXT_EQ_AFTER_DRC) && MUSIC_EXT_EQ_AFTER_DRC
|
|||
|
dec->ext_eq = music_ext_eq_open(sample_rate, ch_num);
|
|||
|
#endif
|
|||
|
|
|||
|
#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(AEID_MUSIC_DYNAMIC_EQ, sample_rate, ch_num);//动态eq
|
|||
|
dec->convert2 = convet_data_open(0, 512);
|
|||
|
#endif/*TCFG_DYNAMIC_EQ_ENABLE*/
|
|||
|
#if defined(TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE) && TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE
|
|||
|
dec->gain = audio_gain_open_demo(AEID_MUSIC_GAIN, ch_num);
|
|||
|
#endif
|
|||
|
#endif/*TCFG_SPDIF_MODE_EQ_ENABLE*/
|
|||
|
|
|||
|
|
|||
|
|
|||
|
// 数据流串联
|
|||
|
struct audio_stream_entry *entries[8] = {NULL};
|
|||
|
// 数据流串联
|
|||
|
struct audio_stream_entry *entries[16] = {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_VBASS_CONFIG
|
|||
|
if (dec->vbass_prev_gain) {
|
|||
|
entries[entry_cnt++] = &dec->vbass_prev_gain->entry;
|
|||
|
}
|
|||
|
if (dec->ns_gate) {
|
|||
|
entries[entry_cnt++] = &dec->ns_gate->entry;
|
|||
|
}
|
|||
|
|
|||
|
if (dec->vbass) {
|
|||
|
entries[entry_cnt++] = &dec->vbass->entry;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
#if TCFG_EQ_ENABLE && TCFG_AUDIO_OUT_EQ_ENABLE
|
|||
|
if (dec->high_bass) { //高低音
|
|||
|
entries[entry_cnt++] = &dec->high_bass->entry;
|
|||
|
}
|
|||
|
if (dec->hb_drc) { //高低音后drc
|
|||
|
entries[entry_cnt++] = &dec->hb_drc->entry;
|
|||
|
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
|
|||
|
if (dec->hb_convert) {
|
|||
|
entries[entry_cnt++] = &dec->hb_convert->entry;
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
#endif
|
|||
|
rl_rr_entry_start = entry_cnt - 1;//记录eq的上一个节点
|
|||
|
#if defined(TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE) && TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE
|
|||
|
if (dec->gain) {
|
|||
|
entries[entry_cnt++] = &dec->gain->entry;
|
|||
|
}
|
|||
|
#endif
|
|||
|
#if AUDIO_SURROUND_CONFIG
|
|||
|
if (dec->surround) {
|
|||
|
entries[entry_cnt++] = &dec->surround->entry;
|
|||
|
}
|
|||
|
#endif
|
|||
|
#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 defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
|
|||
|
if (dec->convert) {
|
|||
|
entries[entry_cnt++] = &dec->convert->entry;
|
|||
|
}
|
|||
|
#endif
|
|||
|
#if defined(MUSIC_EXT_EQ_AFTER_DRC) && MUSIC_EXT_EQ_AFTER_DRC
|
|||
|
if (dec->ext_eq) {
|
|||
|
entries[entry_cnt++] = &dec->ext_eq->entry;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
#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
|
|||
|
}
|
|||
|
#endif
|
|||
|
entries[entry_cnt++] = &dec->mix_ch.entry;
|
|||
|
dec->audio_stream = audio_stream_open(dec, dec_out_stream_resume);
|
|||
|
audio_stream_add_list(dec->audio_stream, entries, entry_cnt);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
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_noisegate_close_demo(dec->ns_gate);
|
|||
|
audio_vbass_close_demo(dec->vbass);
|
|||
|
#endif
|
|||
|
|
|||
|
#if TCFG_EQ_ENABLE && TCFG_AUDIO_OUT_EQ_ENABLE
|
|||
|
high_bass_eq_close(dec->high_bass);
|
|||
|
high_bass_drc_close(dec->hb_drc);
|
|||
|
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
|
|||
|
convet_data_close(dec->hb_convert);
|
|||
|
#endif
|
|||
|
#endif
|
|||
|
|
|||
|
#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
|
|||
|
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
|
|||
|
convet_data_close(dec->convert);
|
|||
|
#endif
|
|||
|
#if defined(MUSIC_EXT_EQ_AFTER_DRC) && MUSIC_EXT_EQ_AFTER_DRC
|
|||
|
music_ext_eq_close(dec->ext_eq);
|
|||
|
#endif
|
|||
|
|
|||
|
#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
|
|||
|
#if defined(TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE) && TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE
|
|||
|
audio_gain_close_demo(dec->gain);
|
|||
|
#endif
|
|||
|
#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_noisegate_close_demo(dec->ns_gate);
|
|||
|
audio_vbass_close_demo(dec->vbass);
|
|||
|
#endif
|
|||
|
|
|||
|
#if TCFG_EQ_ENABLE && TCFG_AUDIO_OUT_EQ_ENABLE
|
|||
|
high_bass_eq_close(dec->high_bass);
|
|||
|
high_bass_drc_close(dec->hb_drc);
|
|||
|
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
|
|||
|
convet_data_close(dec->hb_convert);
|
|||
|
#endif
|
|||
|
#endif
|
|||
|
#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
|
|||
|
#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE
|
|||
|
convet_data_close(dec->convert);
|
|||
|
#endif
|
|||
|
#if defined(MUSIC_EXT_EQ_AFTER_DRC) && MUSIC_EXT_EQ_AFTER_DRC
|
|||
|
music_ext_eq_close(dec->ext_eq);
|
|||
|
#endif
|
|||
|
#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
|
|||
|
#if defined(TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE) && TCFG_PHASER_GAIN_AND_CH_SWAP_ENABLE
|
|||
|
audio_gain_close_demo(dec->gain);
|
|||
|
#endif
|
|||
|
#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;//PA0
|
|||
|
#endif
|
|||
|
spdif_slave_hdl.input_port = SPDIF_IN_PORT_D;//PA6
|
|||
|
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*****************************/
|