📄 midi.c
字号:
/*******************************Copyright (c)***************************************
MIDI录放程序.
************************************************************************************/
#include "common.h"
#include "midi.h"
#include "hpi.h"
/*---------------------------------------------------------------------------------*/
UBYTE data RecEventCode = 0; //MIDI记录事件
UBYTE data RecCodeStatue = 0; //MIDI记录状态
UBYTE data TempoStatue = 0; //MIDI节拍器状态
UBYTE data TempoTimer = 0; //MIDI节拍器时间
UBYTE data TempoType = 0; //MIDI节拍器类型
UBYTE idata TempoCnt[4]; //MIDI节拍器计数
/*-----------------------------------------------------------------------------------
名称: unsigned char code TempoTable[];
功能: 节拍器列表.
-----------------------------------------------------------------------------------*/
unsigned char code TempoTable[]=
{
// 0 1 2 3
1, 0, 0, 0, //Tempo type1
1, 0, 1, 0, //Tempo type2
1, 0, 1, 1, //Tempo type3
1, 1, 1, 1, //Tempo type4
1, 0, 1, 1, //Tempo type5
1, 1, 0, 1, //Tempo type6
};
/*-----------------------------------------------------------------------------------
名称: unsigned char code MidiHead[80];
功能: MIDI头文件.
-----------------------------------------------------------------------------------*/
unsigned char code MidiHead[80]=
{
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0x4D,0x54,0x68,0x64,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x01,0x00,0x78,0x4D,0x54, //1
0x72,0x6B,0x00,0x00,0x00,0x00,0x00,0xFF,0x03,0x08,0x75,0x6E,0x74,0x69,0x74,0x6C, //2
0x65,0x64,0x00,0xFF,0x01,0x05,0xD2,0xDA,0xC4,0xDC,0x34,0x00,0xFF,0x58,0x04,0x04, //3
0x02,0x18,0x08,0x00,0xFF,0x59,0x02,0x00,0x00,0x00,0xFF,0x51,0x03,0x09,0x27,0xC0, //4
0x81,0x00,0xC0,0x00,0x00,0xB0,0x07,0x7F,0x08,0xB0,0x0A,0x40,0x08,0xE0,0x00,0x40 //5
};
/*-----------------------------------------------------------------------------------
名称: void SoundInital(void);
功能: 声卡初始化.
-----------------------------------------------------------------------------------*/
void SoundInital(void)
{
MidiSendData(0xF0); //GM Reset
MidiSendData(0x7E);
MidiSendData(0x7F);
MidiSendData(0x09);
MidiSendData(0x01);
MidiSendData(0xF7);
}
/*-----------------------------------------------------------------------------------
名称: void SoundVolumeAdj(void);
功能: 声卡音量调整.
-----------------------------------------------------------------------------------*/
void SoundVolumeAdj(void)
{
MidiSendData(0xF0);
MidiSendData(0x7F);
MidiSendData(0x7F);
MidiSendData(0x04);
MidiSendData(0x01);
MidiSendData(0x00);
MidiSendData(ParamaVolume);
MidiSendData(0xF7);
}
/*-----------------------------------------------------------------------------------
名称: void SoundOff(void);
功能: 声卡关闭.
-----------------------------------------------------------------------------------*/
void SoundOff(void)
{
MidiSendData(0xE0); //关闭滑音
MidiSendData(0x00);
MidiSendData(0x40);
MidiSendData(0xB0); //关闭颤音
MidiSendData(0x01);
MidiSendData(0x00);
MidiSendData(0xB0); //关闭踏板
MidiSendData(0x40);
MidiSendData(0x00);
MidiSendData(0xB0); //关闭音符
MidiSendData(0x7B);
MidiSendData(0x00);
MidiSendData(0xB0); //复位控制器
MidiSendData(0x79);
MidiSendData(0x00);
}
/*-----------------------------------------------------------------------------------
名称: void SoundSetTempo(void);
功能: 声卡节拍器设定.
-----------------------------------------------------------------------------------*/
void SoundSetTempo(void)
{
MidiSendData(0xC9); //Channel 10
MidiSendData(47); //定音鼓
MidiSendData(0xB9);
MidiSendData(0x07);
MidiSendData(0x7F);
MidiSendData(0xB9);
MidiSendData(0x0A);
MidiSendData(0x40);
}
/*-----------------------------------------------------------------------------------
名称: void SoundTempoOn(UBYTE Note);
功能: 声卡节拍器开启.
-----------------------------------------------------------------------------------*/
void SoundTempoOn(UBYTE Note)
{
MidiSendData(0x99);
MidiSendData(Note);
MidiSendData(127);
}
/*-----------------------------------------------------------------------------------
名称: void SoundTempoOff(UBYTE Note);
功能: 声卡节拍器关闭.
-----------------------------------------------------------------------------------*/
void SoundTempoOff(UBYTE Note)
{
MidiSendData(0x99);
MidiSendData(Note);
MidiSendData(0);
}
/*-----------------------------------------------------------------------------------
名称: void SoundTempoChange(void);
功能: 声卡节拍器修改.
-----------------------------------------------------------------------------------*/
void SoundTempoChange(void)
{
UHWORD Cycle = 12000/ParamaTempo;
switch(TempoType)
{
case 0:
TempoCnt[0] = Cycle;
TempoCnt[1] = 0;
TempoCnt[2] = 0;
TempoCnt[3] = 0;
break;
case 1:
TempoCnt[0] = Cycle;
TempoCnt[1] = 0;
TempoCnt[2] = Cycle;
TempoCnt[3] = 0;
break;
case 2:
TempoCnt[0] = Cycle;
TempoCnt[1] = 0;
TempoCnt[2] = Cycle;
TempoCnt[3] = Cycle;
break;
case 3:
case 4:
case 5:
TempoCnt[0] = Cycle;
TempoCnt[1] = Cycle;
TempoCnt[2] = Cycle;
TempoCnt[3] = Cycle;
break;
}
TempoTimer = 255;
TempoStatue = 0;
}
/*-----------------------------------------------------------------------------------
名称: void SoundTempoRun(void);
功能: 声卡节拍器运行.
-----------------------------------------------------------------------------------*/
void SoundTempoRun(void)
{
if(FlagTempo)
{
if(TempoStatue == 0)
{
if(TempoTimer==0)
{
if(TempoType)
{
SoundTempoOn(0x22);
SoundTempoOff(0x22);
}
else
{
SoundTempoOn(0x25);
SoundTempoOff(0x25);
}
TempoTimer = TempoCnt[0];
TempoStatue = 1;
}
}
else if(TempoStatue == 1)
{
if(TempoTimer==0)
{
if(TempoTable[TempoType*4+1])
{
SoundTempoOn(0x25);
SoundTempoOff(0x25);
}
TempoTimer = TempoCnt[1];
TempoStatue = 2;
}
}
else if(TempoStatue == 2)
{
if(TempoTimer==0)
{
if(TempoTable[TempoType*4+2])
{
SoundTempoOn(0x25);
SoundTempoOff(0x25);
}
TempoTimer = TempoCnt[2];
TempoStatue = 3;
}
}
else if(TempoStatue == 3)
{
if(TempoTimer==0)
{
if(TempoTable[TempoType*4+3])
{
SoundTempoOn(0x25);
SoundTempoOff(0x25);
}
TempoTimer = TempoCnt[3];
TempoStatue = 0;
}
}
}
}
/*-----------------------------------------------------------------------------------
名称: void RecPutByteCode(UBYTE ByteData);
功能: MIDI数据记录.
-----------------------------------------------------------------------------------*/
void RecPutByteCode(UBYTE ByteData)
{
InOutBuf[FileIndex++] = ByteData;
}
/*-----------------------------------------------------------------------------------
名称: void RecPutEventTick(UWORD DeltaTick);
功能: MIDI时间记录.
-----------------------------------------------------------------------------------*/
void RecPutEventTick(UWORD DeltaTick)
{
UBYTE a,b,c,d;
if(DeltaTick<0x80)
{
RecPutByteCode((UBYTE)DeltaTick);
}
else
{
a = DeltaTick&0x7F;
DeltaTick >>= 7;
if(DeltaTick<0x80)
{
RecPutByteCode(((UBYTE)DeltaTick)|0x80);
RecPutByteCode(a);
}
else
{
b = DeltaTick&0x7F;
DeltaTick >>= 7;
if(DeltaTick<0x80)
{
RecPutByteCode(((UBYTE)DeltaTick)|0x80);
RecPutByteCode(b|0x80);
RecPutByteCode(a);
}
else
{
c = DeltaTick&0x7F;
DeltaTick >>= 7;
if(DeltaTick<0x80)
{
RecPutByteCode(((UBYTE)DeltaTick)|0x80);
RecPutByteCode(c|0x80);
RecPutByteCode(b|0x80);
RecPutByteCode(a);
}
else
{
d = DeltaTick&0x7F;
DeltaTick >>= 7;
RecPutByteCode(((UBYTE)DeltaTick)|0x80);
RecPutByteCode(d|0x80);
RecPutByteCode(c|0x80);
RecPutByteCode(b|0x80);
RecPutByteCode(a);
}
}
}
}
}
/*-----------------------------------------------------------------------------------
名称: void RecMidiStart(void);
功能: MIDI记录开始.
-----------------------------------------------------------------------------------*/
void RecMidiStart(void)
{
Led_Off();
AUDIO_ON();
MidiPortSelect();
FlagRecEnd = false;
RxdHead = 0;
RxdTail = 0;
RecEvtTick = 0;
RecEventCode = 0;
RecCodeStatue = 0;
for(FileIndex=0;FileIndex<80;FileIndex++)
{
InOutBuf[FileIndex] = MidiHead[FileIndex];
}
SoundInital();
SoundSetTempo();
SoundVolumeAdj();
}
/*-----------------------------------------------------------------------------------
名称: UBYTE RecMidiRun(void);
功能: MIDI文件记录.
-----------------------------------------------------------------------------------*/
UBYTE RecMidiRun(void)
{
auto UBYTE TempTail;
static UBYTE Comnd = 0;
static UBYTE Notes = 0;
static UBYTE Value = 0;
UWORD EventTime;
if(RxdHead!=RxdTail)
{
TempTail = (RxdTail+1)&RXD_BUFFER_MASK;
RxdTail = TempTail;
Value = RxdBuf[TempTail];
switch(RecCodeStatue)
{
case 0:
if((Value==0x80)||(Value==0x90)||(Value==0xB0))
{
Comnd = Value;
RecCodeStatue = 1;
}
break;
case 1:
if(Value<128)
{
Notes = Value;
RecCodeStatue = 2;
}
else
{
RecCodeStatue = 0;
}
break;
case 2:
EventTime = RecEvtTick;
RecEvtTick = 0;
MidiSendData(Comnd);
MidiSendData(Notes);
MidiSendData(Value);
RecPutEventTick(EventTime);
if(!FlagRecRun)
FlagRecRun = ON;
if(RecEventCode != Comnd)
{
RecEventCode = Comnd;
RecPutByteCode(RecEventCode);
}
RecPutByteCode(Notes);
RecPutByteCode(Value);
Led_Flash();
RecCodeStatue = 0;
break;
}
}
if(FileIndex>=REC_SIZE)
return false;
else
return true;
}
/*-----------------------------------------------------------------------------------
名称: void RecMidiEnd(void);
功能: MIDI记录完成.
-----------------------------------------------------------------------------------*/
void RecMidiEnd(void)
{
RecPutEventTick(0);
RecPutByteCode(0xFF);
RecPutByteCode(0x2F);
RecPutByteCode(0x00);
FileIndex -= 22;
InOutBuf[18] = FileIndex >> 24;
InOutBuf[19] = FileIndex >> 16;
InOutBuf[20] = FileIndex >> 8;
InOutBuf[21] = FileIndex & 0xFF;
FileIndex += 22;
if(FlagRecRun)
FlagRecEnd = true;
SoundOff();
Led_Off();
FlagRecRun = OFF;
AUDIO_OFF();
}
/*-----------------------------------------------------------------------------------
名称: UWORD GetDeltaTimer(void);
功能: 获取MIDI时间.
-----------------------------------------------------------------------------------*/
UWORD GetDeltaTimer(void)
{
UBYTE DeltaByte = 0;
UWORD DeltaTimer = 0;
do
{
DeltaByte = InOutBuf[FileIndex ++];
DeltaTimer|= (DeltaByte & 0x7F);
DeltaByte &= 0x80;
if(DeltaByte == 0x80)
DeltaTimer <<= 7;
else
break;
}while(DeltaByte == 0x80);
return(DeltaTimer);
}
/*-----------------------------------------------------------------------------------
名称: void SendEventParamet(void)
功能: 传送MIDI参数.
-----------------------------------------------------------------------------------*/
void SendEventParamet(void)
{
bit Stop = 0;
UBYTE Lenth = 0;
UBYTE EventCode = 0;
static UBYTE Recoard = 0;
EventCode = InOutBuf[FileIndex];
if(EventCode < 0x80)
EventCode = Recoard;
else
FileIndex++;
switch(EventCode & 0xF0)
{
case 0xF0 :
switch(EventCode)
{
case 0xF0 : //系统事件
while(InOutBuf[FileIndex++] != 0xF7);
break;
case 0xFF :
if(InOutBuf[FileIndex] == 0x2F) //轨道结束
{
FileIndex+= 2;
Stop = true;
}
else
{
FileIndex++;
Lenth = InOutBuf[FileIndex++];
FileIndex += Lenth;
}
break;
case 0xF2 :
FileIndex++;
case 0xF1 :
case 0xF3 :
FileIndex++;
break;
}
break;
case 0xE0 :
case 0xB0 :
case 0xA0 :
case 0x90 :
case 0x80 :
Recoard = EventCode;
MidiSendData(EventCode);
MidiSendData(InOutBuf[FileIndex++]);
MidiSendData(InOutBuf[FileIndex++]);
Led_Flash();
break;
case 0xC0 :
case 0xD0 :
Recoard = EventCode;
MidiSendData(EventCode);
MidiSendData(InOutBuf[FileIndex++]);
break;
}
if(!Stop)
DeltaTick = GetDeltaTimer();
else
PlayerStop();
}
/*-----------------------------------------------------------------------------------
名称: void PlayerStart(void);
功能: MIDI播放开始.
-----------------------------------------------------------------------------------*/
void PlayerStart(void)
{
Led_Off();
AUDIO_ON();
MidiPortSelect();
SoundInital();
SoundVolumeAdj();
FileIndex = 22;
DeltaTick = GetDeltaTimer();
FlagPlayRun = ON;
}
/*-----------------------------------------------------------------------------------
名称: void PlayerRun(void);
功能: MIDI播放.
-----------------------------------------------------------------------------------*/
void PlayerRun(void)
{
if(DeltaTick==0)
{
SendEventParamet();
}
}
/*-----------------------------------------------------------------------------------
名称: void PlayerStop(void);
功能: MIDI播放停止.
-----------------------------------------------------------------------------------*/
void PlayerStop(void)
{
Led_Off();
SoundOff();
FlagPlayRun = OFF;
AUDIO_OFF();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -