287 lines
6.7 KiB
C
287 lines
6.7 KiB
C
#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_dec_pcm.h"
|
|
|
|
struct pcm_dec_hdl {
|
|
struct audio_decoder decoder;
|
|
struct audio_res_wait wait;
|
|
struct audio_mixer_ch mix_ch;
|
|
u8 start;
|
|
u8 remain;
|
|
u8 channel;
|
|
u8 output_ch;
|
|
int sample_rate;
|
|
int (*pcm_read_cb)(void *, void *, int);
|
|
};
|
|
static struct pcm_dec_hdl *pcm_dec = NULL;
|
|
extern struct audio_decoder_task decode_task;
|
|
extern struct audio_dac_hdl dac_hdl;
|
|
|
|
|
|
void pcm_dec_set_read_cb(int (*pcm_read_func)(void *, void *, int))
|
|
{
|
|
local_irq_disable();
|
|
if (pcm_dec && pcm_dec->start == 1) {
|
|
pcm_dec->pcm_read_cb = pcm_read_func;
|
|
} else {
|
|
y_printf(">>> %s, %d, pcm_dec set read cb failed!\n", __func__, __LINE__);
|
|
}
|
|
local_irq_enable();
|
|
}
|
|
|
|
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 int pcm_stream_read(struct audio_decoder *decoder, void *buf, u32 len)
|
|
{
|
|
int rlen = 0;
|
|
struct pcm_dec_hdl *dec = container_of(decoder, struct pcm_dec_hdl, decoder);
|
|
|
|
local_irq_disable();
|
|
if (dec) {
|
|
if (dec->pcm_read_cb) {
|
|
rlen = dec->pcm_read_cb(NULL, (void *)buf, len);
|
|
}
|
|
if (dec->channel == 2 && dec->output_ch == 1) {
|
|
/* pcm_LR_to_mono((s16 *)buf, (s16 *)buf, rlen >> 2); */
|
|
/* rlen >>= 1; */
|
|
}
|
|
}
|
|
local_irq_enable();
|
|
if (!rlen) {
|
|
return -1;
|
|
}
|
|
return rlen;
|
|
}
|
|
|
|
static const struct audio_dec_input pcm_input = {
|
|
.coding_type = AUDIO_CODING_PCM,
|
|
.data_type = AUDIO_INPUT_FILE,
|
|
.ops = {
|
|
.file = {
|
|
.fread = pcm_stream_read,
|
|
}
|
|
}
|
|
};
|
|
|
|
static int pcm_dec_probe_handler(struct audio_decoder *decoder)
|
|
{
|
|
struct pcm_dec_hdl *dec = container_of(decoder, struct pcm_dec_hdl, decoder);
|
|
return 0;
|
|
}
|
|
|
|
static int pcm_dec_output_handler(struct audio_decoder *decoder, s16 *data, int len, void *priv)
|
|
{
|
|
struct pcm_dec_hdl *dec = container_of(decoder, struct pcm_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 pcm_dec_handler = {
|
|
.dec_probe = pcm_dec_probe_handler,
|
|
.dec_output = pcm_dec_output_handler,
|
|
};
|
|
|
|
static void pcm_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv)
|
|
{
|
|
switch (argv[0]) {
|
|
case AUDIO_DEC_EVENT_END:
|
|
/*pcm_audio_close();*/
|
|
break;
|
|
}
|
|
}
|
|
|
|
void pcm_dec_resume(void)
|
|
{
|
|
local_irq_disable();
|
|
if (pcm_dec && pcm_dec->start) {
|
|
audio_decoder_resume(&pcm_dec->decoder);
|
|
}
|
|
local_irq_enable();
|
|
}
|
|
|
|
static int pcm_audio_play_start(void)
|
|
{
|
|
int err;
|
|
y_printf(">>>>>>>> Enter Func: %s \n", __func__);
|
|
struct audio_fmt f = {0};
|
|
struct pcm_dec_hdl *dec = pcm_dec;
|
|
|
|
if (!pcm_dec) {
|
|
return -EINVAL;
|
|
}
|
|
|
|
err = audio_decoder_open(&dec->decoder, &pcm_input, &decode_task);
|
|
if (err) {
|
|
goto __err;
|
|
}
|
|
|
|
audio_decoder_set_handler(&dec->decoder, &pcm_dec_handler);
|
|
audio_decoder_set_event_handler(&dec->decoder, pcm_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;
|
|
|
|
err = audio_decoder_set_fmt(&dec->decoder, &f);
|
|
|
|
printf(">>>>>>>> %s, dec->output_ch : %d\n", __func__, dec->output_ch);
|
|
|
|
#if TCFG_AUDIO_OUTPUT_IIS
|
|
sound_pcm_dev_channel_mapping(dec->output_ch);
|
|
#endif
|
|
|
|
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/*SYS_VOL_TYPE == VOL_TYPE_DIGITAL*/
|
|
|
|
// 设置叠加功能
|
|
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, 0);
|
|
|
|
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;
|
|
}
|
|
|
|
static int pcm_audio_play_stop(void)
|
|
{
|
|
if (!pcm_dec || !pcm_dec->start) {
|
|
return 0;
|
|
}
|
|
pcm_dec->start = 0;
|
|
audio_decoder_close(&pcm_dec->decoder);
|
|
audio_mixer_ch_close(&pcm_dec->mix_ch);
|
|
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
|
|
audio_digital_vol_close(MUSIC_DVOL);
|
|
#endif/*SYS_VOL_TYPE == VOL_TYPE_DIGITAL*/
|
|
return 0;
|
|
}
|
|
|
|
static int pcm_wait_res_handler(struct audio_res_wait *wait, int event)
|
|
{
|
|
int err = 0;
|
|
|
|
if (event == AUDIO_RES_GET) {
|
|
err = pcm_audio_play_start();
|
|
} else if (event == AUDIO_RES_PUT) {
|
|
/* pcm_audio_play_stop(); */
|
|
}
|
|
return err;
|
|
}
|
|
|
|
|
|
int pcm_audio_play_open(int sr, u8 ch)
|
|
{
|
|
struct pcm_dec_hdl *dec;
|
|
|
|
if (pcm_dec) {
|
|
return 0;
|
|
}
|
|
|
|
dec = zalloc(sizeof(*dec));
|
|
if (!dec) {
|
|
return -ENOMEM;
|
|
}
|
|
|
|
pcm_dec = dec;
|
|
|
|
dec->sample_rate = sr;
|
|
dec->channel = ch;
|
|
y_printf(">>> pcm_audio_play_open sr:%d ch:%d\n", dec->sample_rate, dec->channel); //通道是2个
|
|
dec->wait.priority = 2;
|
|
dec->wait.preemption = 1;
|
|
dec->wait.handler = pcm_wait_res_handler;
|
|
audio_decoder_task_add_wait(&decode_task, &dec->wait);
|
|
|
|
clock_add(DEC_PCM_CLK);
|
|
return 0;
|
|
}
|
|
|
|
|
|
void pcm_audio_play_close(void)
|
|
{
|
|
if (!pcm_dec) {
|
|
return;
|
|
}
|
|
pcm_audio_play_stop();
|
|
audio_decoder_task_del_wait(&decode_task, &pcm_dec->wait);
|
|
clock_remove(DEC_PCM_CLK);
|
|
local_irq_disable();
|
|
free(pcm_dec);
|
|
pcm_dec = NULL;
|
|
local_irq_enable();
|
|
}
|
|
|