first
This commit is contained in:
391
cpu/br28/audio_dec/audio_dec_iis.c
Normal file
391
cpu/br28/audio_dec/audio_dec_iis.c
Normal file
@ -0,0 +1,391 @@
|
||||
#include "audio_dec_iis.h"
|
||||
#include "app_config.h"
|
||||
#include "audio_decoder.h"
|
||||
#include "media/includes.h"
|
||||
#include "audio_config.h"
|
||||
#include "system/includes.h"
|
||||
#include "audio_enc.h"
|
||||
#include "application/audio_eq.h"
|
||||
#include "application/audio_drc.h"
|
||||
#include "app_config.h"
|
||||
#include "audio_config.h"
|
||||
#include "audio_dec.h"
|
||||
#include "app_main.h"
|
||||
#include "clock_cfg.h"
|
||||
#include "audio_dec_eff.h"
|
||||
#include "audio_codec_clock.h"
|
||||
#include "audio_dvol.h"
|
||||
#include "audio_link.h"
|
||||
#include "circular_buf.h"
|
||||
#include "sound_device.h"
|
||||
|
||||
|
||||
#if (TCFG_AUDIO_INPUT_IIS)
|
||||
|
||||
extern ALINK_PARM alink0_platform_data;
|
||||
extern struct audio_dac_hdl dac_hdl;
|
||||
extern struct audio_decoder_task decode_task;
|
||||
extern struct audio_mixer mixer;
|
||||
/* extern void *hw_alink; //alink初始化句柄 */
|
||||
#define IIS_IN_STORE_PCM_SIZE (4 * 1024)
|
||||
|
||||
//iis 驱动结构体
|
||||
struct iis_in_sample_hdl {
|
||||
OS_SEM sem;
|
||||
s16 *store_pcm_buf;
|
||||
cbuffer_t cbuf;
|
||||
int sample_rate;
|
||||
void *hw_alink;
|
||||
void *alink_ch;
|
||||
};
|
||||
|
||||
// iis 输入解码结构体
|
||||
struct iis_in_dec_hdl {
|
||||
struct audio_decoder decoder;
|
||||
struct audio_res_wait wait;
|
||||
struct audio_mixer_ch mix_ch;
|
||||
u8 channel;
|
||||
u8 start;
|
||||
u8 need_resume;
|
||||
u8 remain;
|
||||
u8 output_ch;
|
||||
int sample_rate;
|
||||
void *iis_in; //驱动句柄
|
||||
};
|
||||
static struct iis_in_dec_hdl *iis_in_dec = NULL;
|
||||
|
||||
// ********************** iis in 驱动 ************************* //
|
||||
static void iis_in_dec_resume(void)
|
||||
{
|
||||
if (iis_in_dec) {
|
||||
audio_decoder_resume(&iis_in_dec->decoder);
|
||||
}
|
||||
}
|
||||
|
||||
static void pcm_LR_to_mono(s16 *pcm_lr, s16 *pcm_mono, int points_len)
|
||||
{
|
||||
s16 pcm_L;
|
||||
s16 pcm_R;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < points_len; i++, pcm_lr += 2) {
|
||||
pcm_L = *pcm_lr;
|
||||
pcm_R = *(pcm_lr + 1);
|
||||
*pcm_mono++ = (s16)(((int)pcm_L + pcm_R) >> 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void iis_in_data_handler(void *priv, void *_data, int len)
|
||||
{
|
||||
struct iis_in_sample_hdl *iis_in = (struct iis_in_sample_hdl *)priv;
|
||||
s16 *data = (s16 *)_data;
|
||||
u16 temp_len = len;
|
||||
int wlen = 0;
|
||||
|
||||
if (iis_in_dec->start == 0) {
|
||||
goto __exit;
|
||||
}
|
||||
//iis 默认输入的是双声道数据
|
||||
if (iis_in_dec->output_ch == 1) {
|
||||
s16 *mono_data = data;
|
||||
for (int i = 0; i < len / 4; i++) {
|
||||
mono_data[i] = mono_data[i * 2];
|
||||
}
|
||||
len = len / 2;
|
||||
wlen = cbuf_write(&iis_in->cbuf, mono_data, len);
|
||||
if (wlen != len) {
|
||||
putchar('w');
|
||||
}
|
||||
} else if (iis_in_dec->output_ch == 2) {
|
||||
wlen = cbuf_write(&iis_in->cbuf, data, len);
|
||||
/* os_sem_post(&iis_in->sem); */
|
||||
if (wlen != len) {
|
||||
putchar('W');
|
||||
}
|
||||
} else {
|
||||
putchar('e');
|
||||
goto __exit;
|
||||
}
|
||||
|
||||
if (iis_in_dec && iis_in_dec->need_resume) {
|
||||
iis_in_dec->need_resume = 0;
|
||||
iis_in_dec_resume();
|
||||
}
|
||||
__exit:
|
||||
alink_set_shn(&alink0_platform_data.ch_cfg[1], temp_len / 4);
|
||||
}
|
||||
|
||||
static void *iis_in_open(int sr)
|
||||
{
|
||||
struct iis_in_sample_hdl *iis_in = NULL;
|
||||
iis_in = zalloc(sizeof(struct iis_in_sample_hdl));
|
||||
if (!iis_in) {
|
||||
return NULL;
|
||||
}
|
||||
iis_in->store_pcm_buf = malloc(IIS_IN_STORE_PCM_SIZE);
|
||||
if (!iis_in->store_pcm_buf) {
|
||||
free(iis_in);
|
||||
return NULL;
|
||||
}
|
||||
cbuf_init(&iis_in->cbuf, iis_in->store_pcm_buf, IIS_IN_STORE_PCM_SIZE);
|
||||
iis_in->hw_alink = (ALINK_PARM *)get_iis_alink_param();
|
||||
if (iis_in->hw_alink == NULL) {
|
||||
iis_in->hw_alink = alink_init(&alink0_platform_data);
|
||||
}
|
||||
iis_in->alink_ch = alink_channel_init(iis_in->hw_alink, 1, ALINK_DIR_RX, (void *)iis_in, iis_in_data_handler);
|
||||
alink_start(iis_in->hw_alink);
|
||||
iis_in->sample_rate = sr;
|
||||
return iis_in;
|
||||
}
|
||||
|
||||
|
||||
// *********************** iis in dec 解码 ***************************//
|
||||
static int iis_in_stream_read(struct audio_decoder *decoder, void *buf, u32 len)
|
||||
{
|
||||
int rlen = 0;
|
||||
struct iis_in_sample_hdl *iis_in = (struct iis_in_sample_hdl *)iis_in_dec->iis_in;
|
||||
if (!iis_in || iis_in_dec->start == 0) {
|
||||
goto __exit;
|
||||
}
|
||||
if (!iis_in->store_pcm_buf) {
|
||||
goto __exit;
|
||||
}
|
||||
int read_len = cbuf_get_data_size(&iis_in->cbuf);
|
||||
if (read_len) {
|
||||
read_len = read_len > len ? len : read_len;
|
||||
rlen = cbuf_read(&iis_in->cbuf, buf, read_len);
|
||||
/* printf("--- rlen : %d\n", rlen); */
|
||||
}
|
||||
__exit:
|
||||
if (!rlen) {
|
||||
iis_in_dec->need_resume = 1;
|
||||
return -1;
|
||||
}
|
||||
/* y_printf("--- rlen = %d\n",rlen); */
|
||||
return rlen;
|
||||
}
|
||||
|
||||
static int iis_in_dec_probe_handler(struct audio_decoder *decoder)
|
||||
{
|
||||
/* struct pcm_dec_hdl *dec = container_of(decoder, struct pcm_dec_hdl, decoder); */
|
||||
struct iis_in_dec_hdl *dec = container_of(decoder, struct iis_in_dec_hdl, decoder);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iis_in_dec_output_handler(struct audio_decoder *decoder, s16 *data, int len, void *priv)
|
||||
{
|
||||
struct iis_in_dec_hdl *dec = container_of(decoder, struct iis_in_dec_hdl, decoder);
|
||||
|
||||
if (!dec) {
|
||||
return 0;
|
||||
}
|
||||
int rlen = len;
|
||||
int wlen = 0;
|
||||
|
||||
if (!dec->remain) {
|
||||
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
|
||||
audio_digital_vol_run(MUSIC_DVOL, data, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
wlen = audio_mixer_ch_write(&dec->mix_ch, data, rlen);
|
||||
if (!wlen) {
|
||||
putchar('w');
|
||||
}
|
||||
rlen -= wlen;
|
||||
|
||||
if (rlen == 0) {
|
||||
dec->remain = 0;
|
||||
} else {
|
||||
dec->remain = 1;
|
||||
}
|
||||
return len - rlen;
|
||||
}
|
||||
|
||||
static const struct audio_dec_handler iis_in_dec_handler = {
|
||||
.dec_probe = iis_in_dec_probe_handler,
|
||||
.dec_output = iis_in_dec_output_handler,
|
||||
};
|
||||
|
||||
static const struct audio_dec_input iis_input = {
|
||||
.coding_type = AUDIO_CODING_PCM,
|
||||
.data_type = AUDIO_INPUT_FILE,
|
||||
.ops = {
|
||||
.file = {
|
||||
.fread = iis_in_stream_read,
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static void iis_in_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv)
|
||||
{
|
||||
switch (argv[0]) {
|
||||
case AUDIO_DEC_EVENT_END:
|
||||
/*pcm_audio_close();*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//开始 iis dec 解码
|
||||
static int iis_in_dec_start(void)
|
||||
{
|
||||
int err;
|
||||
y_printf(">>>>>>>> Enter Func: %s \n", __func__);
|
||||
struct audio_fmt f = {0};
|
||||
struct iis_in_dec_hdl *dec = iis_in_dec;
|
||||
|
||||
if (!iis_in_dec && iis_in_dec->start == 1) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = audio_decoder_open(&dec->decoder, &iis_input, &decode_task);
|
||||
if (err) {
|
||||
goto __err;
|
||||
}
|
||||
if (dec->iis_in == NULL) {
|
||||
y_printf("--> %s, %d, Init iis_in!\n", __func__, __LINE__);
|
||||
dec->iis_in = iis_in_open(dec->sample_rate);
|
||||
if (!dec->iis_in) {
|
||||
goto __err;
|
||||
}
|
||||
}
|
||||
|
||||
audio_decoder_set_handler(&dec->decoder, &iis_in_dec_handler);
|
||||
audio_decoder_set_event_handler(&dec->decoder, iis_in_dec_event_handler, 0);
|
||||
u8 dac_conn = audio_dac_get_channel(&dac_hdl);
|
||||
if (dac_conn == DAC_OUTPUT_LR) {
|
||||
dec->output_ch = 2;
|
||||
} else {
|
||||
dec->output_ch = 1;
|
||||
}
|
||||
|
||||
f.coding_type = AUDIO_CODING_PCM;
|
||||
f.sample_rate = dec->sample_rate;
|
||||
f.channel = dec->output_ch;
|
||||
|
||||
sound_pcm_dev_channel_mapping(dec->output_ch);
|
||||
|
||||
err = audio_decoder_set_fmt(&dec->decoder, &f);
|
||||
if (err) {
|
||||
goto __err;
|
||||
}
|
||||
|
||||
|
||||
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
|
||||
audio_digital_vol_open(MUSIC_DVOL, app_audio_get_volume(APP_AUDIO_STATE_MUSIC), MUSIC_DVOL_MAX, MUSIC_DVOL_FS, -1);
|
||||
#endif
|
||||
|
||||
// 设置叠加功能
|
||||
audio_mixer_ch_open(&dec->mix_ch, &mixer);
|
||||
audio_mixer_ch_set_sample_rate(&dec->mix_ch, audio_output_rate(f.sample_rate));
|
||||
app_audio_state_switch(APP_AUDIO_STATE_MUSIC, get_max_sys_vol());
|
||||
|
||||
int vol = app_audio_get_volume(APP_AUDIO_STATE_MUSIC);
|
||||
app_audio_set_volume(APP_AUDIO_STATE_MUSIC, vol, 1);
|
||||
|
||||
err = audio_decoder_start(&dec->decoder);
|
||||
if (err) {
|
||||
goto __err;
|
||||
}
|
||||
/* audio_codec_clock_set(AUDIO_PC_MODE, AUDIO_CODING_PCM, dec->wait.preemption); */
|
||||
dec->start = 1;
|
||||
return 0;
|
||||
|
||||
__err:
|
||||
return err;
|
||||
}
|
||||
|
||||
// iis in 解码资源等待
|
||||
void iis_in_dec_stop(void);
|
||||
|
||||
static int iis_in_wait_res_handler(struct audio_res_wait *wait, int event)
|
||||
{
|
||||
int err = 0;
|
||||
if (event == AUDIO_RES_GET) {
|
||||
// 启动解码
|
||||
err = iis_in_dec_start();
|
||||
} else if (event == AUDIO_RES_PUT) {
|
||||
// 被打断
|
||||
iis_in_dec_stop();
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int iis_in_dec_open(void)
|
||||
{
|
||||
int err;
|
||||
struct iis_in_dec_hdl *dec = NULL;;
|
||||
dec = zalloc(sizeof(*dec));
|
||||
if (!dec) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
iis_in_dec = dec;
|
||||
dec->sample_rate = TCFG_IIS_SR;
|
||||
dec->channel = 2; //iis 是双声道数据
|
||||
dec->wait.priority = 2;
|
||||
dec->wait.preemption = 1;
|
||||
dec->wait.handler = iis_in_wait_res_handler;
|
||||
|
||||
err = audio_decoder_task_add_wait(&decode_task, &dec->wait);
|
||||
clock_add(DEC_PCM_CLK);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
void iis_in_dec_stop(void)
|
||||
{
|
||||
if (iis_in_dec && iis_in_dec->start == 1) {
|
||||
struct iis_in_sample_hdl *iis_in = (struct iis_in_sample_hdl *)iis_in_dec->iis_in;
|
||||
iis_in_dec->start = 0;
|
||||
audio_decoder_close(&iis_in_dec->decoder);
|
||||
audio_mixer_ch_close(&iis_in_dec->mix_ch);
|
||||
app_audio_state_exit(APP_AUDIO_STATE_MUSIC);
|
||||
|
||||
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
|
||||
audio_digital_vol_close(MUSIC_DVOL);
|
||||
#endif/*SYS_VOL_TYPE == VOL_TYPE_DIGITAL*/
|
||||
|
||||
local_irq_disable();
|
||||
#if 1
|
||||
if (iis_in) {
|
||||
void *alink_p = (ALINK_PARM *)get_iis_alink_param();
|
||||
if (iis_in->hw_alink && !alink_p) {
|
||||
alink_uninit(iis_in->hw_alink);
|
||||
iis_in->hw_alink = NULL;
|
||||
} else {
|
||||
/* alink_uninit(iis_in->hw_alink); */
|
||||
alink_channel_close(iis_in->alink_ch);
|
||||
}
|
||||
if (iis_in->store_pcm_buf) {
|
||||
free(iis_in->store_pcm_buf);
|
||||
iis_in->store_pcm_buf = NULL;
|
||||
}
|
||||
free(iis_in);
|
||||
iis_in = NULL;
|
||||
iis_in_dec->iis_in = NULL;
|
||||
}
|
||||
#endif
|
||||
local_irq_enable();
|
||||
}
|
||||
}
|
||||
|
||||
void iis_in_dec_close(void)
|
||||
{
|
||||
if (!iis_in_dec) {
|
||||
return;
|
||||
}
|
||||
iis_in_dec_stop();
|
||||
audio_decoder_task_del_wait(&decode_task, &iis_in_dec->wait);
|
||||
clock_remove(DEC_PCM_CLK);
|
||||
local_irq_disable();
|
||||
free(iis_in_dec);
|
||||
iis_in_dec = NULL;
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user