KT26-0607_AC695n-BTE-SDK312/cpu/br23/audio_dec/audio_dec_midi_file.c
2026-06-07 19:38:16 +08:00

432 lines
12 KiB
C
Raw 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_dec_midi_file.c
*Note :
*
****************************************************************
*/
//////////////////////////////////////////////////////////////////////////////
#include "asm/includes.h"
#include "media/includes.h"
#include "system/includes.h"
#include "effectrs_sync.h"
#include "app_config.h"
#include "audio_config.h"
#include "audio_dec.h"
#include "app_config.h"
#include "app_main.h"
#include "MIDI_DEC_API.h"
#include "audio_dec_file.h"
#include "lfwordana_enc_api.h"
#if defined(TCFG_DEC_MIDI_ENABLE) && TCFG_DEC_MIDI_ENABLE
//midi文件播放时对应的音色文件路径(用户可修改路径)
#define MIDI_FILE_PATH SDFILE_RES_ROOT_PATH"MIDI.bin\0"
//替换主旋律的音色库,由录音得到(用户可修改路径)
int *MIDI_W2S_FILE_PATH = "storage/sd0/C/W2S/W2S.raw\0";
//替换主旋律音色库对应的参数文件,录音时生成(用户可修改路径)
#define MIDI_W2S_PARM_PATH "storage/sd0/C/W2S/parmout.raw\0"
static const u16 midi_samplerate_tab[9] = {
48000,
44100,
32000,
24000,
22050,
16000,
12000,
11025,
8000
};
static u32 get_sr_tab_num(u32 sr)
{
int i = 0;
for (i = 0; i < ARRAY_SIZE(midi_samplerate_tab); i++) {
if (sr == midi_samplerate_tab[i]) {
return i;
}
}
return 4;
}
u32 tmark_trigger(void *priv, u8 *val, u8 len)
{
return 0;
}
u32 melody_trigger(void *priv, u8 key, u8 vel)
{
return 0;
}
u32 melody_stop_trigger(void *priv, u8 key)
{
return 0;
}
u32 timDiv_trigger(void *priv)
{
return 0;
}
u32 beat_trigger(void *priv, u8 val1/*一节多少拍*/, u8 val2/*每拍多少分音符*/)
{
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief midi音色文件读
@param
@return
@note 内部调用
*/
/*----------------------------------------------------------------------------*/
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 内部调用
*/
/*----------------------------------------------------------------------------*/
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初始化函数由midi_init调用
@param midi_init_info_v:midi信息
@param addr:音色文件句柄
@return
@note
*/
/*----------------------------------------------------------------------------*/
void init_midi_info_val(MIDI_INIT_STRUCT *midi_init_info_v, void *addr)
{
//midi初始化表
midi_init_info_v->init_info.player_t = 8;
midi_init_info_v->init_info.sample_rate = get_sr_tab_num(22050);
midi_init_info_v->init_info.spi_pos = (u32)addr;
midi_init_info_v->init_info.fread = midi_fread;
midi_init_info_v->init_info.fseek = midi_fseek;
//midi的模式初始化
midi_init_info_v->mode_info.mode = CMD_MIDI_CTRL_MODE_0; //CMD_MIDI_CTRL_MODE_2;
//midi节奏初始化
midi_init_info_v->tempo_info.tempo_val = 1042;
for (u32 tmp_i = 0; tmp_i < 16; tmp_i++) {
midi_init_info_v->tempo_info.decay_val[tmp_i] = ((u16)31 << 11) | 1024;
}
midi_init_info_v->tempo_info.mute_threshold = (u16)1L << 29;
//midi主轨道初始化
midi_init_info_v->mainTrack_info.chn = 17; //把哪个轨道当成主轨道 , 17:库内自动分配
//midi外部音量初始化
for (u32 tmp_i = 0; tmp_i < 16; tmp_i++) {
midi_init_info_v->vol_info.cc_vol[tmp_i] = 4096; //4096即原来的音量
}
midi_init_info_v->vol_info.ex_vol_use_chn = 1;
//midi的主轨道乐器设置
midi_init_info_v->prog_info.prog = 0;
midi_init_info_v->prog_info.ex_vol = 1024;
midi_init_info_v->prog_info.replace_mode = 0;
//OKON 模式设置
midi_init_info_v->okon_info.Melody_Key_Mode = CMD_MIDI_MELODY_KEY_0;
midi_init_info_v->okon_info.OKON_Mode = CMD_MIDI_OKON_MODE_0;
//midi的mark控制初始化
midi_init_info_v->mark_info.priv = NULL; //&file_mark;
midi_init_info_v->mark_info.mark_trigger = tmark_trigger;
//midi的melody控制初始化
midi_init_info_v->moledy_info.priv = NULL; //&file_melody;
midi_init_info_v->moledy_info.melody_trigger = melody_trigger;
//midi的melody stop控制初始化
midi_init_info_v->moledy_stop_info.priv = NULL;
midi_init_info_v->moledy_stop_info.melody_stop_trigger = melody_stop_trigger;//主旋律音符停止播放回调
//midi的小节回调控制初始化
midi_init_info_v->tmDiv_info.priv = NULL;
midi_init_info_v->tmDiv_info.timeDiv_trigger = timDiv_trigger;
//midi的小拍回调控制初始化
midi_init_info_v->beat_info.priv = NULL;
midi_init_info_v->beat_info.beat_trigger = beat_trigger;
//使能位控制
midi_init_info_v->switch_info = MELODY_PLAY_ENABLE;// | MELODY_ENABLE | EX_VOL_ENABLE; //主轨道播放使能
#if defined(MIDI_SUPPORT_W2S) && MIDI_SUPPORT_W2S
//设置替换主轨道的声音的音源
void *cache_addr;
extern int midi_w2s_get_cfg_addr(void **addr);
if (midi_w2s_get_cfg_addr(&cache_addr)) {
log_e("get midi w2s addr err\n");
return;
}
midi_w2s_parm_get(&midi_init_info_v->w2s_info);
midi_init_info_v->w2s_info.key_diff = -7;////与音高成反比
midi_init_info_v->w2s_info.rec_data = (u32)cache_addr;
#endif/*MIDI_SUPPORT_W2S*/
return;
}
FILE *midi_w2s_file = NULL;
int midi_w2s_get_cfg_addr(void **addr)
{
#ifndef CONFIG_MIDI_DEC_ADDR
//音色文件支持在外部存储卡或者外挂flash,sdk默认使用本方式
//获取音色文件
FILE *file = fopen(MIDI_W2S_FILE_PATH, "r");
if (!file) {
log_e("MIDI.bin open err\n");
return -1;
}
*addr = (void *)file;
midi_w2s_file = file;
log_i("midi_w2s_file %x\n", midi_w2s_file);
#else
//音色文件仅支持在内置flash
FILE *file = fopen(MIDI_W2S_FILE_PATH, "r");
if (!file) {
log_e("MIDI.bin open err\n");
return -1;
}
struct vfs_attr attr = {0};
fget_attrs(file, &attr);
*addr = (void *)attr.sclust;
fclose(file);
#endif
return 0;
}
FILE *midi_file = NULL;
int midi_get_cfg_addr(void **addr)
{
#ifndef CONFIG_MIDI_DEC_ADDR
//音色文件支持在外部存储卡或者外挂flash,sdk默认使用本方式
//获取音色文件
FILE *file = fopen(MIDI_FILE_PATH, "r");
if (!file) {
log_e("MIDI.bin open err\n");
return -1;
}
*addr = (void *)file;
midi_file = file;
log_i("midi_file %x\n", midi_file);
#else
//音色文件仅支持在内置flash
FILE *file = fopen(MIDI_FILE_PATH, "r");
if (!file) {
log_e("MIDI.bin open err\n");
return -1;
}
struct vfs_attr attr = {0};
fget_attrs(file, &attr);
*addr = (void *)attr.sclust;
fclose(file);
#endif
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief midi音色文件关闭
@param
@return
@note 该函数在midi关闭时调用,该函数是弱定义函数,不可修改定义
*/
/*----------------------------------------------------------------------------*/
int midi_uninit()
{
#ifndef CONFIG_MIDI_DEC_ADDR
if (midi_file) {
fclose(midi_file);
midi_file = NULL;
}
if (midi_w2s_file) {
fclose(midi_w2s_file);
midi_w2s_file = NULL;
}
#endif
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief midi初始化函数该函数由库调用
@param 参数返回地址
@return 0
@note 该函数是弱定义函数,不可修改定义
*/
/*----------------------------------------------------------------------------*/
int midi_init(void *info)
{
void *cache_addr;
if (midi_get_cfg_addr(&cache_addr)) {
log_e("get midi addr err\n");
return -1;
}
//初始化midi参数
init_midi_info_val(info, cache_addr); //需要外部写
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief midi控制函数
@param cmd:
CMD_MIDI_SET_CHN_PROG, //更改乐器,参数结构对应 MIDI_PROG_CTRL_STRUCT
CMD_MIDI_CTRL_TEMPO, //改变节奏,参数结构对应 MIDI_PLAY_CTRL_TEMPO
CMD_MIDI_GOON, //one key one note的时候接着播放使用,参数为空
CMD_MIDI_CTRL_MODE, //改变模式,参数结构对应 MIDI_PLAY_CTRL_MO
CMD_MIDI_SET_SWITCH, //配置开关使能,要不要替换乐器,使用外部音量,参数对应 MIDI_SET_SWITCH
CMD_MIDI_SET_EX_VOL, //设置外部声道音量,参数结构对应 EX_CH_VOL_PARM
@param priv:对应cmd的参数地址
@return 0
@note midi解码控制例程
*/
/*----------------------------------------------------------------------------*/
void midi_ioctrl(u32 cmd, void *priv)
{
struct file_dec_hdl *dec = get_file_dec_hdl(); // 文件解码句柄
if (dec) {
log_e("file dec NULL\n");
return ;
}
int status = file_dec_get_status();
if (status == FILE_DEC_STATUS_STOP) {
if (tone_get_dec_status()) {
audio_decoder_ioctrl(get_tone_dec_file_decoder(), cmd, priv);
} else {
log_w("file dec is stop\n");
}
return ;
}
log_i("midi cmd %x", cmd);
audio_decoder_ioctrl(&dec->file_dec.decoder, cmd, priv);
}
#if 0
//测试例子
void *ex_vol_test()
{
static int val = 4096;
EX_CH_VOL_PARM ex_vol;
for (int test_ci = 0; test_ci < CTRL_CHANNEL_NUM; test_ci++) {
ex_vol.cc_vol[test_ci] = val;
}
val -= 64;
if (val <= 0) {
val = 4096;
}
midi_ioctrl(CMD_MIDI_SET_EX_VOL, &ex_vol);
return NULL;
}
#endif
#if defined(MIDI_SUPPORT_W2S) && MIDI_SUPPORT_W2S
int midi_w2s_init(void *info)
{
struct _AUDIO_DECODE_PARA {
u32 mode;
};
struct _AUDIO_DECODE_PARA *mode_parm = (struct _AUDIO_DECODE_PARA *)info;
mode_parm->mode = CMD_MIDI_CTRL_MODE_W2S;
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief midi主旋律是否用录音文件替换主旋律
@param flag:1(替换主旋律) 0(不替换主旋律)
@return 无
@note
*/
/*----------------------------------------------------------------------------*/
void midi_mode_change(u8 flag)
{
struct _AUDIO_DECODE_PARA {
u32 mode;
};
struct _AUDIO_DECODE_PARA mode_parm = {0};
if (flag) {
mode_parm.mode = CMD_MIDI_CTRL_MODE_W2S;
} else {
mode_parm.mode = CMD_MIDI_CTRL_MODE_0;
}
midi_ioctrl(CMD_MIDI_CTRL_MODE, &mode_parm);
}
void midi_mode_test(void *p)
{
static u8 flag = 0;
midi_mode_change(flag);
flag = !flag;
}
#endif/*MIDI_SUPPORT_W2S*/
/*----------------------------------------------------------------------------*/
/**@brief midi预处理的音色对应的输出的参数
@param data:参数地址
@param len:参数长度
@return
@note
*/
/*----------------------------------------------------------------------------*/
void midi_w2s_parm_set(void *data, u32 len)
{
MIDI_W2S_STRUCT *w2s_parmOut;
void *fp = fopen(MIDI_W2S_PARM_PATH, "wb");
if (fp) {
fwrite(fp, data, len);
fclose(fp);
fp = NULL;
}
}
/*----------------------------------------------------------------------------*/
/**@brief 获取midi预处理的音色对应的参数
@param parm:参数返回地址
@return
@note
*/
/*----------------------------------------------------------------------------*/
void midi_w2s_parm_get(void *parm)
{
void *fp = fopen(MIDI_W2S_PARM_PATH, "r");
if (fp) {
fread(fp, parm, sizeof(MIDI_W2S_STRUCT));
fclose(fp);
fp = NULL;
}
}
#endif /*TCFG_DEC_MIDI_ENABLE*/