//MIDI ROUTINES
long midiInIdx,midiOutIdx,MIDIBUFLEN;	//data index and length
long midiDataLen;                       //amount of data in out buffer
UINT uMidiInDeviceID,uMidiOutDeviceID;	//Device ID for MIDI input
HMIDIIN hMidiIn; HMIDIOUT hMidiOut;	//midi In & Out handles
long *midiInBuffer;			//data in pointer
long *midiOutBuffer;			//data in pointer
long isMidiPlaying;			//is midi playing?
DWORD midiTimer;			//timer for midi playback
UINT timerRes;				//timer resolution

//timer callback for play
void PASCAL timerCallBack(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1,DWORD dw2)
{
    MMRESULT x;
    if (isMidiPlaying != 0){
        midiTimer += timerRes;
        while((midiOutIdx < midiDataLen) & (midiOutBuffer[midiOutIdx] < midiTimer)){
            x = midiOutShortMsg(hMidiOut,midiOutBuffer[midiOutIdx+1]);
            midiOutIdx +=2;
        }
        if (midiOutIdx >= midiDataLen){midiOutIdx = 0;midiTimer=0;}
    }
    else{x = timeKillEvent(wTimerID);}
    return;
}
long FAR PASCAL PlayMidi()
{
    UINT wTimerID;
    midiOutIdx = 0;
    isMidiPlaying = 1;
    midiTimer = 0;
    wTimerID = timeSetEvent((UINT) timerRes,(UINT) timerRes,(LPTIMECALLBACK) timerCallBack,(DWORD) timerRes,TIME_PERIODIC);
    return midiDataLen;
}
long FAR PASCAL AddMidi(const long timeVal,const long midiVal)
{
    midiOutBuffer[midiDataLen]=timeVal;
    midiOutBuffer[midiDataLen+1]=midiVal;
    midiDataLen += 2;
    return midiDataLen;
}
long FAR PASCAL MidiPlaying()
{
    return isMidiPlaying;
}
long FAR PASCAL GetMidiTimer()
{
    return midiTimer;
}
long FAR PASCAL StopMidi()
{
    midiDataLen = 0;
    isMidiPlaying = 0;
    return midiDataLen;
}
long FAR PASCAL OpenMidiPlay(const long buflength)
{
    MMRESULT x,y;
    midiOutBuffer = (long *)malloc(buflength * sizeof(long));
    midiDataLen = 0;
    isMidiPlaying = 0;
    timerRes = 50;
    x = midiOutOpen(&hMidiOut,(UINT)-1,(DWORD)0,(DWORD)0,(DWORD)0);
    y = timeBeginPeriod(timerRes);
    return (long)x+y;
}
long FAR PASCAL CloseMidiPlay()
{
    MMRESULT x;
    free(midiOutBuffer);
    x = timeEndPeriod(timerRes);
    x = midiOutClose(hMidiOut);
    return (long) x;
}
long FAR PASCAL CmdMidi(const long cmd,const long note, const long vel)
{
    MMRESULT x;
    DWORD Msg;
    Msg = cmd + (note<<8) + (vel<<16);
    x = midiOutShortMsg(hMidiOut,Msg);
    return (long) x;
}
//callback function for Midi In data
void CALLBACK MidiInProc(HMIDIIN hMidiIn,UINT wMsg,DWORD dwInstance,DWORD dwParam1,DWORD dwParam2)
{
	if (midiInIdx < MIDIBUFLEN-4) { 
		switch (wMsg)
		{
			case (MIM_DATA):
			case (MIM_MOREDATA):{ 
				if((dwParam1 & 0xF0)!=0xF0){//throw out SYS
					midiInBuffer[midiInIdx++] = (long)dwParam2;
					midiInBuffer[midiInIdx++] = (long)dwParam1;
				}
				break;}
			case MIM_CLOSE:
			case MIM_OPEN:
				break;
		}
	}
	return;
}
long FAR PASCAL OpenMidiRec(const long buflength, const long device)
{
    MMRESULT x,y;
    uMidiInDeviceID=(UINT)device;
    MIDIBUFLEN = buflength;
    midiInBuffer = (long *)malloc(MIDIBUFLEN * sizeof(long));
    midiInIdx = 0;
    x = midiInOpen(&hMidiIn,uMidiInDeviceID,(DWORD)MidiInProc,(DWORD)0,(DWORD)CALLBACK_FUNCTION); // | MIDI_IO_STATUS
    y = midiInReset(hMidiIn);
    return (long)x+y;
}
long FAR PASCAL CloseMidiRec()
{
    MMRESULT x;
    free(midiInBuffer);
    x = midiInClose(hMidiIn);
    return (long) x;
}
long FAR PASCAL RecordMidi()
{
    MMRESULT x;
    midiInIdx = 0;
    x = midiInStart(hMidiIn);
    return (long)x;
}
long FAR PASCAL GetRecordLength()
{
    return midiInIdx-1;
}
long FAR PASCAL GetRecordData(const long idx)
{
    DWORD i=idx;
    long ret=0;
    if(i