⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 midi.c

📁 这个是录音琴的程序,用光电感应器来检测琴键的动作.并且将他记录下来,可以回放.
💻 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 + -