KT24-1110_65E-HA-651B/cpu/br25/audio_dec/audio_dec_midi_ctrl.c

617 lines
18 KiB
C
Raw Normal View History

2024-11-10 10:44:17 +00:00
#include "audio_dec_midi_ctrl.h"
#if AUDIO_MIDI_CTRL_CONFIG
/*
*
*1MIDI_KEY_NUM
* 2flash的 60M90M,spi读线宽的为2线模式或4线
* 3
* */
extern struct audio_dac_hdl dac_hdl;
#define MIDI_KEY_NUM (18)//(支持多少个key同时发声(1~18) 越大,需要的时钟越大)
const u16 midi_samplerate_tab[9] = {
48000,
44100,
32000,
24000,
22050,
16000,
12000,
11025,
8000
};
struct _midi_obj {
u8 channel;
u32 sample_rate;
u32 id; // 唯一标识符,随机值
u32 start : 1; // 正在解码
char *path; //音色文件路径
struct audio_res_wait wait; // 资源等待句柄
struct midi_ctrl_decoder midi_ctrl_dec;
struct audio_mixer_ch mix_ch; // 叠加句柄
struct audio_stream *stream; // 音频流
};
struct _midi_obj *midi_ctrl_dec_hdl = NULL;
void midi_ctrl_ioctrl(u32 cmd, void *priv);
/*----------------------------------------------------------------------------*/
/**@brief midi ctrl解码释放
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void midi_ctrl_dec_relaese()
{
if (midi_ctrl_dec_hdl) {
audio_decoder_task_del_wait(&decode_task, &midi_ctrl_dec_hdl->wait);
clock_remove(DEC_MIDI_CLK);
local_irq_disable();
free(midi_ctrl_dec_hdl);
midi_ctrl_dec_hdl = NULL;
local_irq_enable();
}
}
/*----------------------------------------------------------------------------*/
/**@brief midi音色文件获取
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
static int midi_get_cfg_addr(u8 **addr)
{
if (!midi_ctrl_dec_hdl) {
return -1;
}
#ifndef CONFIG_MIDI_DEC_ADDR
//音色文件支持在外部存储卡或者外挂flash,sdk默认使用本方式
/* FILE *file = fopen("storage/sd0/C/MIDI.bin\0", "r"); */
FILE *file = fopen(midi_ctrl_dec_hdl->path, "r");
/* FILE *file = fopen(SDFILE_RES_ROOT_PATH"MIDI.bin\0", "r"); */
if (!file) {
log_e("MIDI.bin open err\n");
return -1;
}
*addr = (u8 *)file;
log_i("midi_file %x\n", file);
#else
//音色文件仅支持在内置flash
/* FILE *file = fopen(SDFILE_RES_ROOT_PATH"MIDI.bin\0", "r"); */
FILE *file = fopen(midi_ctrl_dec_hdl->path, "r");
if (!file) {
log_e("MIDI.bin open err\n");
return -1;
}
struct vfs_attr attr = {0};
fget_attrs(file, &attr);
*addr = (u8 *)attr.sclust;
fclose(file);
#endif
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief midi音色文件读
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
static int midi_fread(void *file, void *buf, u32 len)
{
#ifndef CONFIG_MIDI_DEC_ADDR
FILE *hd = (FILE *)file;
if (hd) {
len = fread(hd, buf, len);
}
#endif
return len;
}
/*----------------------------------------------------------------------------*/
/**@brief midi音色文件seek
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
static int midi_fseek(void *file, u32 offset, int seek_mode)
{
#ifndef CONFIG_MIDI_DEC_ADDR
FILE *hd = (FILE *)file;
if (hd) {
fseek(hd, offset, seek_mode);
}
#endif
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief midi ctrl初始化函数该函数由库调用
@param
@return 0
@note
*/
/*----------------------------------------------------------------------------*/
int midi_ctrl_init(void *info)
{
if (!midi_ctrl_dec_hdl) {
return -1;
}
u8 *cache_addr;
if (midi_get_cfg_addr(&cache_addr)) {
return -1;
}
midi_ctrl_open_parm *parm = (midi_ctrl_open_parm *)info;
parm->ctrl_parm.tempo = 1024;//解码会改变播放速度,1024是正常值
parm->ctrl_parm.track_num = 1;//支持音轨的最大个数0~15
parm->sample_rate = midi_ctrl_dec_hdl->midi_ctrl_dec.sample_rate;//midi_samplerate_tab[5];
parm->cfg_parm.player_t = MIDI_KEY_NUM; //(支持多少个key同时发声,用户可修改)
parm->cfg_parm.spi_pos = (unsigned int)cache_addr;
parm->cfg_parm.fread = midi_fread;
parm->cfg_parm.fseek = midi_fseek;
for (int i = 0; i < ARRAY_SIZE(midi_samplerate_tab); i++) {
if (parm->sample_rate == midi_samplerate_tab[i]) {
parm->cfg_parm.sample_rate = i;
break;
}
}
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief midi ctrl音色文件关闭
@param
@return
@note midi关闭时调用,
*/
/*----------------------------------------------------------------------------*/
int midi_ctrl_uninit(void *priv)
{
#ifndef CONFIG_MIDI_DEC_ADDR
if (priv) {
fclose((FILE *)priv);
priv = NULL;
}
#endif
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 乐器更新
@param prog:
@param trk_num : (0~15)
@return
@note
*/
/*----------------------------------------------------------------------------*/
void midi_ctrl_set_porg(u8 prog, u8 trk_num)
{
struct set_prog_parm parm = {0};
parm.prog = prog;
parm.trk_num = trk_num;
midi_ctrl_ioctrl(MIDI_CTRL_SET_PROG, &parm);
}
/*----------------------------------------------------------------------------*/
/**@brief 按键按下
@param nkey:0~127
@param nvel:0~127
@param chn :(0~15)
@return
@note
*/
/*----------------------------------------------------------------------------*/
void midi_ctrl_note_on(u8 nkey, u8 nvel, u8 chn)
{
struct note_on_parm parm = {0};
parm.nkey = nkey;
parm.nvel = nvel;
parm.chn = chn;
midi_ctrl_ioctrl(MIDI_CTRL_NOTE_ON, &parm);
}
/*----------------------------------------------------------------------------*/
/**@brief 按键松开
@param nkey:0~127
@param chn :(0~15)
@return
@note
*/
/*----------------------------------------------------------------------------*/
void midi_ctrl_note_off(u8 nkey, u8 chn)
{
struct note_off_parm parm = {0};
parm.nkey = nkey;
parm.chn = chn;
midi_ctrl_ioctrl(MIDI_CTRL_NOTE_OFF, &parm);
}
/*----------------------------------------------------------------------------*/
/**@brief midi 配置接口
@param cmd:
@param priv:cmd的结构体
@return
@note
*/
/*----------------------------------------------------------------------------*/
void midi_ctrl_confing(u32 cmd, void *priv)
{
midi_ctrl_ioctrl(cmd, priv);
}
/*----------------------------------------------------------------------------*/
/**@brief midi keyboard 设置按键按下音符发声的衰减系数
@param obj:
@param samp:samplerate_tab坐标
@return
@note 11bit为调节衰减系数 1024 0~1024
11bit为延时系数0,311s,0~31()
@example midi_ctrl_confing_set_melody_decay((&0x7fff) | (&0x1f <<11));
*/
/*----------------------------------------------------------------------------*/
void midi_ctrl_confing_set_melody_decay(u16 val)
{
u32 cmd = CMD_MIDI_CTRL_TEMPO;
MIDI_PLAY_CTRL_TEMPO tempo = {0};
tempo.decay_val = val;
tempo.tempo_val = 1024;//设置为固定1024即可
midi_ctrl_confing(cmd, (void *)&tempo);
}
/*----------------------------------------------------------------------------*/
/**@brief 弯音轮配置
@param pitch_val:,1 - 65535 256,
@param chn :(0~15)
@return
@note
*/
/*----------------------------------------------------------------------------*/
void midi_ctrl_pitch_bend(u16 pitch_val, u8 chn)
{
struct pitch_bend_parm parm = {0};
parm.pitch_val = pitch_val;
parm.chn = chn;
midi_ctrl_ioctrl(MIDI_CTRL_PITCH_BEND, &parm);
}
/*----------------------------------------------------------------------------*/
/**@brief midi ctrl解码数据流激活
@param *p:
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void midi_ctrl_dec_out_stream_resume(void *p)
{
struct _midi_obj *dec = p;
#if FILE_DEC_USE_OUT_TASK
if (dec->midi_ctrl_dec.dec_no_out_sound == 0) {
audio_decoder_resume_out_task(&dec->midi_ctrl_dec.decoder);
return ;
}
#endif
audio_decoder_resume(&dec->midi_ctrl_dec.decoder);
}
/*----------------------------------------------------------------------------*/
/**@brief midi ctrl解码事件处理
@param *decoder:
@param argc:
@param *argv:
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void midi_ctrl_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv)
{
switch (argv[0]) {
case AUDIO_DEC_EVENT_END:
if (!midi_ctrl_dec_hdl) {
log_i("midi_ctrl_dec_hdl handle err ");
break;
}
if (midi_ctrl_dec_hdl->id != argv[1]) {
log_w("midi_ctrl_dec_hdl id err : 0x%x, 0x%x \n", midi_ctrl_dec_hdl->id, argv[1]);
break;
}
midi_ctrl_dec_close();
//audio_decoder_resume_all(&decode_task);
break;
}
}
/*----------------------------------------------------------------------------*/
/**@brief midi ctrl解码开始
@param
@return 0
@return 0
@note
*/
/*----------------------------------------------------------------------------*/
int midi_ctrl_dec_start()
{
int err;
struct _midi_obj *dec = midi_ctrl_dec_hdl;
struct audio_mixer *p_mixer = &mixer;
if (!dec) {
return -EINVAL;
}
log_i("midi_ctrl dec start: in\n");
// 打开midi ctrl解码器
err = midi_ctrl_decoder_open(&dec->midi_ctrl_dec, &decode_task);
if (err) {
goto __err1;
}
midi_ctrl_decoder_set_event_handler(&dec->midi_ctrl_dec, midi_ctrl_dec_event_handler, dec->id);
// 设置叠加功能
audio_mixer_ch_open_head(&dec->mix_ch, p_mixer);
audio_mixer_ch_set_src(&dec->mix_ch, 1, 0);
#if FILE_DEC_USE_OUT_TASK
if (dec->midi_ctrl_dec.dec_no_out_sound == 0) {
audio_decoder_out_task_ch_enable(&dec->midi_ctrl_dec.decoder);
}
#endif
// 数据流串联
struct audio_stream_entry *entries[8] = {NULL};
u8 entry_cnt = 0;
entries[entry_cnt++] = &dec->midi_ctrl_dec.decoder.entry;
entries[entry_cnt++] = &dec->mix_ch.entry;
// 创建数据流,把所有节点连接起来
dec->stream = audio_stream_open(dec, midi_ctrl_dec_out_stream_resume);
audio_stream_add_list(dec->stream, entries, entry_cnt);
// 设置音频输出音量
audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC);
// 设置时钟
clock_set_cur();
// 开始解码
dec->midi_ctrl_dec.status = FILE_DEC_STATUS_PLAY;
err = audio_decoder_start(&dec->midi_ctrl_dec.decoder);
dec->start = 1;
if (err) {
goto __err3;
}
return 0;
__err3:
audio_mixer_ch_close(&dec->mix_ch);
midi_ctrl_decoder_close(&dec->midi_ctrl_dec);
if (dec->stream) {
audio_stream_close(dec->stream);
dec->stream = NULL;
}
__err1:
log_w(" start err close\n");
midi_ctrl_dec_relaese();
return -1;
}
/*----------------------------------------------------------------------------*/
/**@brief midi ctrl解码关闭
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
static void __midi_ctrl_dec_close(void)
{
if (midi_ctrl_dec_hdl && midi_ctrl_dec_hdl->start) {
midi_ctrl_dec_hdl->start = 0;
midi_ctrl_decoder_close(&midi_ctrl_dec_hdl->midi_ctrl_dec);
audio_mixer_ch_close(&midi_ctrl_dec_hdl->mix_ch);
// 先关闭各个节点最后才close数据流
if (midi_ctrl_dec_hdl->stream) {
audio_stream_close(midi_ctrl_dec_hdl->stream);
midi_ctrl_dec_hdl->stream = NULL;
}
}
}
/*----------------------------------------------------------------------------*/
/**@brief 关闭midi ctrl解码
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void midi_ctrl_dec_close(void)
{
if (!midi_ctrl_dec_hdl) {
return;
}
__midi_ctrl_dec_close();
midi_ctrl_dec_relaese();
clock_set_cur();
log_i("midi ctrl dec close \n\n ");
}
/*----------------------------------------------------------------------------*/
/**@brief midi ctrl解码资源等待
@param *wait:
@param event:
@return 0
@note
*/
/*----------------------------------------------------------------------------*/
static void __midi_ctrl_dec_close(void);
static int midi_ctrl_wait_res_handler(struct audio_res_wait *wait, int event)
{
int err = 0;
log_i("midi_ctrl_wait_res_handler, event:%d\n", event);
if (event == AUDIO_RES_GET) {
// 启动解码
err = midi_ctrl_dec_start();
} else if (event == AUDIO_RES_PUT) {
// 被打断
__midi_ctrl_dec_close();
}
return err;
}
/*----------------------------------------------------------------------------*/
/**@brief 打开midi ctrl解码
@param sample_rate:
@param *path:
@return 0
@return 0
@note
*/
/*----------------------------------------------------------------------------*/
int midi_ctrl_dec_open(u32 sample_rate, char *path)
{
int err = 0;
int i = 0;
struct _midi_obj *dec;
dec = zalloc(sizeof(*dec));
if (!dec) {
return -ENOMEM;
}
midi_ctrl_dec_hdl = dec;
dec->id = rand32();
dec->path = path;
dec->midi_ctrl_dec.ch_num = 2;
dec->midi_ctrl_dec.output_ch_num = audio_output_channel_num();
dec->midi_ctrl_dec.output_ch_type = audio_output_channel_type();
#if TCFG_MIC_EFFECT_ENABLE
dec->midi_ctrl_dec.sample_rate = MIC_EFFECT_SAMPLERATE;
#else
for (i = 0; i < ARRAY_SIZE(midi_samplerate_tab); i++) {
if (sample_rate == midi_samplerate_tab[i]) {
dec->midi_ctrl_dec.sample_rate = midi_samplerate_tab[i];
break;
}
}
if (i >= ARRAY_SIZE(midi_samplerate_tab)) {
dec->midi_ctrl_dec.sample_rate = 16000;
log_e("midi sample_rate check err ,will set default 16000 Hz\n");
}
#endif
dec->wait.priority = 2;
dec->wait.preemption = 0;
dec->wait.snatch_same_prio = 1;
/* dec->wait.protect = 1; */
dec->wait.handler = midi_ctrl_wait_res_handler;
clock_add(DEC_MIDI_CLK);
err = audio_decoder_task_add_wait(&decode_task, &dec->wait);
return err;
}
/*----------------------------------------------------------------------------*/
/**@brief midi ctrl控制函数
@param cmd:
MIDI_CTRL_NOTE_ON, //按键按下参数结构对应struct note_on_parm
MIDI_CTRL_NOTE_OFF, //按键松开参数结构对应struct note_off_parm
MIDI_CTRL_SET_PROG, //更改乐器参数结构对应struct set_prog_parm
MIDI_CTRL_PITCH_BEND, //弯音轮参数结构对应struct pitch_bend_parm
CMD_MIDI_CTRL_TEMPO, //改变节奏,参数结构对应 MIDI_PLAY_CTRL_TEMPO
@param priv:cmd的参数地址
@return 0
@note midi解码控制例程
*/
/*----------------------------------------------------------------------------*/
void midi_ctrl_ioctrl(u32 cmd, void *priv)
{
struct _midi_obj *dec = midi_ctrl_dec_hdl;
if (!dec) {
log_e("midi ctrl dec NULL\n");
return ;
}
log_i("midi ctrl cmd %x", cmd);
audio_decoder_ioctrl(&dec->midi_ctrl_dec.decoder, cmd, priv);
}
#if 0
/*----------------------------------------------------------------------------*/
/**@brief midi key 测试样例
@param
@return
@note
*/
/*----------------------------------------------------------------------------*/
void midi_paly_test(u32 key)
{
static u8 open_close = 0;
static u8 change_prog = 0;
static u8 note_on_off = 0;
switch (key) {
case KEY_IR_NUM_0:
if (!open_close) {
/* midi_ctrl_dec_open(16000);//启动midi key */
/* midi_ctrl_dec_open(16000, "storage/sd0/C/MIDI.bin\0");//启动midi key */
midi_ctrl_dec_open(16000, SDFILE_RES_ROOT_PATH"MIDI.bin\0");//启动midi key
} else {
midi_ctrl_dec_close();//关闭midi key
}
open_close = !open_close;
break;
case KEY_IR_NUM_1:
if (!change_prog) {
midi_ctrl_set_porg(0, 0);//设置0号乐器音轨0
} else {
midi_ctrl_set_porg(22, 0);//设置22号乐器音轨0
}
change_prog = !change_prog;
break;
case KEY_IR_NUM_2:
if (!note_on_off) {
//模拟按键57、58、59、60、61、62,以力度127通道0按下测试
midi_ctrl_note_on(57, 127, 0);
midi_ctrl_note_on(58, 127, 0);
midi_ctrl_note_on(59, 127, 0);
midi_ctrl_note_on(60, 127, 0);
midi_ctrl_note_on(61, 127, 0);
midi_ctrl_note_on(62, 127, 0);
} else {
//模拟按键57、58、59、60、61、62松开测试
midi_ctrl_note_off(57, 0);
midi_ctrl_note_off(58, 0);
midi_ctrl_note_off(59, 0);
midi_ctrl_note_off(60, 0);
midi_ctrl_note_off(61, 0);
midi_ctrl_note_off(62, 0);
}
note_on_off = !note_on_off;
break;
default:
break;
}
}
#endif
#endif