developer-toolkit-v1.01/installed/SAMPLE/MIDIS.C

UTF-8 rendering of a DOS-encoded (CP437 / CRLF) file. Byte-for-byte original: MIDIS.C.


#ifdef TURBO
#pragma	hdrfile	midis.sym
#endif

#include	<stdio.h>
#include	<dos.h>

#include   "global.H"
#include   "Control.H"
#include   "Midi.H"

#ifdef	TURBO
#pragma	hdrstop

#undef inportb
#undef outportb
#endif

/****************************************************************************/

static enum	ProgMode {
	interr,
	polling
	};

/*
 *	Queue are used in this module to push data before being send
 */

#define queueLength	1024

/*
 *	Synopsis:		Queue, QueuePtr
 *							 
 *	Description: 	Most of the communication between the various levels
 *					of the ICI is done thru queues. A structure is given to
 *					facilitate the manipulation of queues.			
 */

typedef struct	Queue {
	int		head;
	int		tail;
	int		number;
	BYTE	array[queueLength];
	} Queue,  *QueuePtr;

/****************************************************************************/

int		ctrlChipIntNb;						// current ctrl chip vector
void   	(interrupt far *oldFunc)();

Queue	debug;

/****************************************************************************/

void	InstallDriverTestInterrupt2(void);
void   RestoreDriverTestInterrupt2(void);
void	Intelligent(BYTE data);

PRIVATE	void	QueueByte( QueuePtr queue, BYTE byte);
PRIVATE	BYTE	UnQueueByte( QueuePtr queue);
PRIVATE	void	ResetQueue( QueuePtr queue);
PRIVATE	WORD	GetQueueNumber( QueuePtr queue);

typedef	struct Note {
	BYTE	status;
	BYTE	pitch;
	BYTE	velo;
	} Note;

Note		song[100] = {
		{	0x90, 0x34, 0x40    },
		{	0x80, 0x34, 0x40    },
		{	0x90, 0x36, 0x40    },
		{	0x80, 0x36, 0x40    },
		{	0x90, 0x37, 0x40    },
		{	0x80, 0x37, 0x40    },
		{	0x90, 0x38, 0x40    },
		{	0x80, 0x38, 0x40    },
		{	0x90, 0x3b, 0x40    },
		{	0x80, 0x3b, 0x40    },
		{	0x90, 0x3d, 0x40    },
		{	0x80, 0x3d, 0x40    },
		{	0x90, 0x40, 0x40    },
		{	0x80, 0x40, 0x40    },
		{	0x90, 0x42, 0x40    },
		{	0x80, 0x42, 0x40    },
		{	0x90, 0x43, 0x40    },
		{	0x80, 0x43, 0x40    },
		{	0x90, 0x44, 0x40    },
		{	0x80, 0x44, 0x40    },
		{	0x90, 0x47, 0x40    },
		{	0x80, 0x47, 0x40    },
		{	0x90, 0x49, 0x40    },
		{	0x80, 0x49, 0x40    },
		{	0x90, 0x4c, 0x40    },
		{	0x80, 0x4c, 0x40    },
		{	0x90, 0x4e, 0x40    },
		{	0x80, 0x4e, 0x40    },
		{	0x90, 0x4f, 0x40    },
		{	0x80, 0x4f, 0x40    },
		{	0x90, 0x50, 0x40    },
		{	0x80, 0x50, 0x40    },
		{	0x90, 0x53, 0x40    },
		{	0x80, 0x53, 0x40    },
		{	0x90, 0x55, 0x40    },
		{	0x80, 0x55, 0x40    },
		{	0x90, 0x58, 0x40    },
		{	0x80, 0x58, 0x40    },
		{	0x80, 0x49, 0x40    },
		{	0x80, 0x4f, 0x40    },
		{	0x80, 0x37, 0x40    },
		{	0x80, 0x43, 0x40    },
		{	0x80, 0x58, 0x40    },
		{	0x80, 0x3d, 0x40    }};


/****************************************************************************/


void dispatch(WORD msg, DWORD param)
	{
	(void) msg;

	if (param != 0xFE) QueueByte(&debug, param);
	}

main()
	{
	BYTE	data;
	int		progMode = interr;
	int		i;
	long	j;

	if (InitControlDriver()) {
		printf("Can not link to control chip driver\n");
		exit(1);
		}

	printf("Example program running level %d\n", gssLevel);

	if (InitMidiDriver()) {
		printf("Can not init MIDI driver\n");
		exit(1);
		}

	ResetQueue(&debug);
	
	/*
	 *	In the resident drivers version use: AssignMidiDispatcher(dispatch);
	 *	but in the object version use SetMidiDispatcher(dispatch);
	 */

	SetMidiDispatcher(dispatch);	

   MaskMMAMidiOutInterrupt(0);
   MaskMMAMidiInInterrupt(0);
	MaskMMAOverrunError(0);

	printf("Transmitting a bunch of notes...\n");

	for (i = 0 ; i < 44 ; i += 2) {
		SendMMAMidiData(song[i].status);
		SendMMAMidiData(song[i].pitch);
		SendMMAMidiData(song[i].velo);
		for (j = 0 ; j < 25000 ; j++);

		SendMMAMidiData(song[i+1].status);
		SendMMAMidiData(song[i+1].pitch);
		SendMMAMidiData(song[i+1].velo);
		for (j = 0 ; j < 25000 ; j++);
		}

	printf("press any key to stop collecting\n");
	while (! kbhit()) {
		if (progMode != interr)	{
			if (GetMMAMidiInReady()) {
				QueueByte(&debug, ReadMMAMidiData());
				}
			}
		else {
			while( GetQueueNumber(&debug) ) {
				Intelligent(UnQueueByte(&debug));
				}
			}
		}
	getch();

   MaskMMAMidiOutInterrupt(1);
   MaskMMAMidiInInterrupt(1);
	MaskMMAOverrunError(1);

	ResetMidiDispatcher();

	CloseMidiDriver();
	CloseControlDriver();
	return 0;
   }

void	Intelligent(BYTE data)
	{
	static	int		mode = 0;

	/*
    *  Message             1st byte        2nd byte        3rd byte
    *  -------             --------        --------        --------
    *  Note off            $80 - $8F       $00 - $7F       $00 - $7F
    *                      $90 - $9F       $00 - $7F          $00
    *  Note on             $90 - $9F       $00 - $7F       $00 - $7F
    *  Note After Touch    $A0 - $AF       $00 - $7F       $00 - $7F
    *  Control Change      $B0 - $BF       $00 - $7F       $00 - $7F
    *  Program Change      $C0 - $CF       $00 - $7F  
    *  Ch After Touch      $D0 - $DF       $00 - $7F  
    *  Pitch Wheel         $E0 - $EF       $00 - $7F       $00 - $7F
	 */

	if (data == 0xF0) {
		mode = 1;
		printf("\n%02x ",data);
		return;
		}
	else {
		if (data == 0xF7) {
			mode = 0;
			printf("%02x\n",data);
			return;
			}
		}

	if ((mode == 0) && (data & 0x80)) printf("\n");
	printf("%02x ", data);
	}

/*
 * Synopsis:		void	QueueByte( queue, byte)     
 *
 *	Description: 	Places the given byte at the tail of the queue.
 *
 *	Argument:		QueuePtr    queue;                 
 *					BYTE        byte;                  
 *
 *	Return value:	none
 *     
 */                                   

PRIVATE	
void	QueueByte( QueuePtr queue, BYTE byte)

    {
    int tail;
    
    if (queue->number == queueLength)
        return;
    tail = queue->tail;
    queue->array[tail] = byte;
    if (++tail == queueLength)
        tail = 0;
    queue->tail = tail;
    
    queue->number++;
    }

/*
 * Synopsis:		BYTE    UnQueueByte( QueuePtr queue)
 *
 * Description: 	Unqueues the byte at the head of the specified queue
 *      			and returns it as a result.
 *
 *	Argument:		QueuePtr    queue
 *
 *	Return value:	Return oldest byte stored in the queue.
 */

PRIVATE	
BYTE	UnQueueByte( QueuePtr queue)
    {
    BYTE 	byte;
    int 	head;
    
    head = queue->head;
    byte = queue->array[head];

    if (++head == queueLength)
        head = 0;
    queue->head = head;
    queue->number--;
    
    return(byte);
    }

/*
 *	Synopsis:		ResetQueue( QueuePtr queue)
 *                          
 *	Description: 	Zeroes the specified queue.
 *
 *	Argument:		QueuePtr	queue
 *
 *	Return values:	none
 */

PRIVATE	
void	ResetQueue( QueuePtr queue)
    {
    queue->head = 0;
    queue->tail = 0;
    queue->number = 0;
    }

/*
 *	Synopsis:		GetQueueNumber( QueuePtr queue)
 *                                               
 *	Description:	Returns the current number of byte in queue.
 *
 *	Argument:  		QueuePtr    queue
 *
 *	Return value:	Number of bytes stored in this queue.
 */

PRIVATE	
WORD	GetQueueNumber( QueuePtr queue)
    {
    return(queue->number);
    }