Please consider a donation to the Higher Intellect project. See https://preterhuman.net/donate.php or the Donate to Higher Intellect page for more info.

SEQ.C

From Higher Intellect Vintage Wiki
Jump to navigation Jump to search
/* fmsynt plays the fm chip with MIDI messages from MIDI IN */
/* With Built-in FM editor                                  */
/* now with MOUSE support!!!!                               */


#include <stdio.h>
#include <sbc.h>
#include <sbcmusic.h>
#include <bios.h>
#include <conio.h>
#include <dos.h>
#include <dir.h>
#include <cursor.c>
#include <alloc.h>

#include <midi.h>
#include <mkbrk.h>

#define SbProID 100
#define KeyUp 0x80

typedef unsigned long ulong;

struct MIDIpacket {
	unsigned char track;
	ulong 	msec;
	unsigned char midbyte1;
	unsigned char midbyte2;
	unsigned char midbyte3;
	struct MIDIpacket *next,*before;
}  *point, *sequence_start, *sequence_end;

static struct MIDIpacket *last_pos;

unsigned long ms,old_ms;
unsigned char status,kanel,nn,vl;
unsigned char trk;
int solo;

int edpatch;
int opr;
int Loaded_before;
char curr_cmf[80];
char cmfname[80];

unsigned char out_cnvrt(int i,int param);

unsigned char in_runstatus,out_runstatus;

char channel_on[16];

char default_instr[16] =
		{   0x021,0x011,0x04C,0x000,0x0F1,0x0F2,0x063,0x072,
			0x000,0x000,0x004,0x000,0x000,0x000,0x000,0x000 };

char InstrBuf[128][16];

int numinstr;

unsigned char old_note,velocity,octave,program;

int editmode, playmode, recmode;


main(int argc,char **argv)
{
	if(init(argc,argv[1]))
	{
		while(1)
		{
			if(playmode && (point != NULL))
				process_recorded();
			if(playmode)
				process_playkey();
			else
			  if(kbhit())
				 process_key();
		}
	}
}

process_key()
{
int scan,modifiers;

	scan = (bioskey(0) >> 8) & 0xFF;
	modifiers = bioskey(2);

	if(modifiers & 8)
	{
		switch(scan) {
			case 47 : setveloc();break;        /* Alt-V */
			case 24 : all_notes_off();break;   /* Alt-O */
			case 25 : loadpatch();break;       /* Alt-P */
			case 38 : loadpatches();break;     /* Alt-L */
			case 31 : savepatches();break;     /* Alt-S */
			case 44 : listfiles();break;       /* Alt-Z */
			case 17 : save_config_settings();break; /* Alt-W */
			case 21 : fm_edit();break;          /* Alt-Y */
			case 46 : clr_sequence();break;
			case 20 : select_track();break;
			case 45 : set_solo();break;
		 /*

			case 120 : trk = 1; break;
			case 121 : trk = 2; break;
			case 122 : trk = 3; break;
			case 123 : trk = 4; break;
			case 124 : trk = 5; break;
			case 125 : trk = 6; break;
			case 126 : trk = 7; break;
			case 127 : trk = 8; break;
			case 128 : trk = 9; break;
			case 129 : trk = 0; break;
			case 30 : trk = 10; break;
			case 48 : trk = 11; break;
			case 46 : trk = 12; break;
			case 32 : trk = 13; break;
			case 18 : trk = 14; break;
			case 33 : trk = 15; break;

		*/

		}
		draw_screen();
	}
	else
	{
		switch(scan){
			case 25 : rec_play(0); break;
			case 19 : rec_play(1);break;
			case 1 :  quit(0);
		}
	}
}


unsigned char old_key,old_release;

process_playkey()
{
unsigned char key;


	key=get_mkbrk_code();

	if(key != old_key)
	{
		if(key >= KeyUp)
		{
			if((key-0x80) == old_key)
			{
				stop_note();
				old_key = key;
			}
		}
		else
		{
			if(old_key < KeyUp)
				stop_note();

			switch(key) {
				case 44 : playnote(0);break;                /* z */
				case 31 : playnote(1);break;                /* s */
				case 45 : playnote(2);break;                /* x */
				case 32 : playnote(3);break;               /* d */
				case 46 : playnote(4);break;               /* c */
				case 47 : playnote(5);break;               /* v */
				case 34 : playnote(6);break;               /* g */
				case 48 : playnote(7);break;               /* b */
				case 35 : playnote(8);break;               /* h */
				case 49 : playnote(9);break;               /* n */
				case 36 : playnote(10);break;               /* j */
				case 50 : playnote(11);break;               /* m */
				case 51 : playnote(12);break;               /* , */

				case 16 : playnote(12);break;               /* q */
				case 3  : playnote(13);break;              /* 2 */
				case 17 : playnote(14);break;             /* w */
				case 4  : playnote(15);break;             /* 3 */
				case 18 : playnote(16);break;             /* e */
				case 19 : playnote(17);break;              /* f */
				case 6  : playnote(18);break;             /* 5 */
				case 20 : playnote(19);break;             /* t */
				case 7  : playnote(20);break;             /* 6 */
				case 21 : playnote(21);break;            /* y */
				case 8  : playnote(22);break;           /* 7 */
				case 22 : playnote(23);break;           /* u */
				case 23 : playnote(24);break;           /* i */

				case 78 : if(octave < 7) octave++; break;
				case 74 : if(octave > 2) octave--; break;

				case 73 : change_program(key,0); break;
				case 81 : change_program(key,0);break;  /* PgDwn */

				case  1 : exit_playmode();
			}
			old_key = key;
		}
	}
}


process_recorded()
{
	if(miditicks-ms >= point->msec)
	{
		if(solo && (point->track != trk))
		{
		   point = point->next;
		   return;
		}

		status = point->midbyte1;
		kanel = status & 0xF;

		switch(status & 0xF0){
			case 0x90 :
			{
				nn = point->midbyte2;
				vl = point->midbyte3;

				if(vl)
					sbfd_note_on(kanel,nn,vl);
				else
					sbfd_note_off(kanel,nn,0);

			} break;
			case 0x80 :
			{
				nn = point->midbyte2;
				vl = point->midbyte3;
				sbfd_note_off(kanel,nn,0);
			} break;
			case 0xC0 : sbfd_program_change(kanel,point->midbyte2);
		}
		point = point->next;
	}
}


select_track()
{
unsigned char ts[10];

	gotoxy(1,22);
	printf("Select track (1-16): \n");
	gets(ts);
	trk = (unsigned char)(atoi(ts) - 1);
	gotoxy(1,22);
	printf("                           ");
}


set_solo()
{
unsigned char *mode[2] = {"Off","On"};

	solo ^= 1;
	gotoxy(1,22);
	printf("Solo %s\n",mode[solo]);
	delay(1000);
	gotoxy(1,22);
	printf("         ");
}


rec_play(int mode)
{
	if(mode == 1)
		recmode = 1;
	else
		recmode = 0;

	ms = miditicks;
	point = sequence_start;
	goto_playmode();
}



clr_sequence()
{
	point = sequence_start;         /* f”rsta block i gruppen      */
	do {
		farfree(point);                  /* g”r fri nuvarande block        */
		point = point->next;            /* peka till n„sta                */
	  } while (point->next != NULL);    /* sluta n„r next „r NULL      */

	sequence_start = sequence_end = NULL;
	last_pos = sequence_start;

	gotoxy(1,22);
	printf("Sequence Cleared!\n");
	delay(1000);
	gotoxy(1,22);
	printf("                    ");
}



goto_playmode()
{
	init_mkbrk();
	playmode = 1;
	gotoxy(1,22);
	printf("Keyboard Play mode");

}

exit_playmode()
{
	while(get_mkbrk_code() != 0x81);
	exit_mkbrk();
	playmode = 0;
	gotoxy(1,22);
	printf("                  ");
}



fmplay(unsigned char channel, unsigned char note, unsigned char velocity)
{
	if(velocity != 0)
	   sbfd_note_on(channel,note,velocity);
	else
		sbfd_note_off(channel,note,velocity);
}

setveloc()
{
char velocstr[10];
	ShowCur();
	gotoxy(1,22);
	printf("\nSet velocity (0-127): ");
	gets(velocstr);
	velocity = atoi(velocstr);
	HideCur();
}

all_notes_off()
{
	sbfd_music_off();
}


playnote(unsigned char offs)
{
unsigned char note;

	note = (octave*12)+offs;
	if(recmode)
		add_packet(trk,miditicks-ms,0x90 | trk,note,velocity);
	sbfd_note_on(trk,note,velocity);
	old_note = note;
}

stop_note()
{
	if(recmode)
		add_packet(trk,miditicks-ms,0x90 | trk,old_note,0);
	sbfd_note_off(trk,old_note,0);
}

change_program(int scan,int button)
{
	switch(scan){
		case 73 : {
			if(program < 127)
				program++;
		}break;
		case 81 : {
			if(program > 0)
				program--;
		}break;
	}

	if(recmode)
		add_packet(trk,miditicks-ms,0xC0 | trk,program,0);

	sbfd_program_change(trk,program);

	gotoxy(65,1);printf("%-3u",program);
}




add_packet(trk,tstamp,c1,c2,c3)
unsigned long tstamp;
unsigned char c1,c2,c3;
{
	struct MIDIpacket *scratch,*insert_pt,*get_insert_point();

	scratch = (struct MIDIpacket *) farmalloc(16);

	if(scratch == NULL)
	{
		  fprintf(stderr,"Sorry, out of memory!\n");
		  delay(1000);
		  quit(1);
	}

	scratch->track = trk;
	scratch->msec = tstamp;
	scratch->midbyte1 = c1;
	scratch->midbyte2 = c2;
	scratch->midbyte3 = c3;

	/* Where in the linked list should this packet go? */

	if(sequence_start == NULL)       /* the list is empty */
	{
		sequence_start = sequence_end = scratch;
		scratch->before = NULL;
		scratch->next = NULL;
	}
	else
	{
		insert_pt = get_insert_point(sequence_start,sequence_end,tstamp);
		scratch->track = trk;

		if(insert_pt == NULL) /* insert the new bottom record */
		{
			sequence_end->next = scratch;
			scratch->before = sequence_end;
			scratch->next = NULL;
			sequence_end = scratch;
		}
		else if(insert_pt == sequence_start) /* insert the new top record */
		{
			sequence_start->before = scratch;
			scratch->before = NULL;
			scratch->next = sequence_start;
			sequence_start = scratch;
		}
		else  /* insert before the insert pointer */
		{
			scratch->next = insert_pt;
			scratch->before = insert_pt->before;
			insert_pt->before = scratch;
			(scratch->before)->next = scratch;
		}
	}
} /* end of add_packet() */


struct MIDIpacket *get_insert_point(top,bottom,tstamp)
struct MIDIpacket *top,*bottom;
unsigned long tstamp;
{
	if(tstamp > bottom->msec) return(NULL); /* tack onto end of list */
	if(tstamp < top->msec) return(top); /* insert as the new first record */

	if(tstamp >= (last_pos->before)->msec)
	{
		while(tstamp > last_pos->msec)
			last_pos = last_pos->next;
		return(last_pos);
	}
	else
	{
		last_pos = sequence_start;             /* Apparently a new track */
		while(tstamp > last_pos->msec)
			last_pos = last_pos->next;
		return(last_pos);
	}
}






/* ==================  Initialization and other routines =============== */





int init(int argc,char *patchfile)
{
int i,j;
FILE* f;

	if ( ! GetEnvSetting() )
	{
		if (sbc_check_card() & 4)
		{
			if (sbc_test_int())
			{
				sbfd_init();
				init_midi();

				velocity = 64;
				octave = 5;
				program = 0;

				editmode = 0;
				playmode = 0;
				edpatch = 0;


				sequence_start = sequence_end = NULL;
				last_pos = sequence_start;

				trk = 0;
				solo = 0;

				for(i=0;i<16;i++)
					channel_on[i] = 1;

				for(i=0;i<128;i++)
					for(j=0;j<16;j++)
						InstrBuf[i][j]=default_instr[j];

				if(f=fopen("fmsynt.cfg","rb"))
					get_config_settings(f);

				if(argc > 1)
					loadpatches2(patchfile);
				else
					if(f=fopen("default.set","rb"))
					{
						fclose(f);
						loadpatches2("default.set");
					}

				sbfd_instrument((char far*)InstrBuf);
				draw_screen();
			}
			else
			{
				printf("Error on interrupt.\n");
				return(0);
			}
		}
		else
		{
			printf("Sound Blaster Card not found or wrong I/O setting.\n") ;
			return(0);
		}
	}
	else
	{
		printf("BLASTER environment variable not set or incomplete or invalid.\n");
		return(0);
	}
	return(1);
}


quit(mode)
{
int k, butstat;

	if(!mode)
	{
		gotoxy(1,22);
		printf("Do you really want to quit (Y\\n)?");

		k = (bioskey(0) >> 8) & 0xff;

	}else
		k = 28;

	if(k == 28 || k == 21)
	{
		point = sequence_start;         /* f”rsta block i gruppen      */
		do {
			farfree(point);             /* g”r fri nuvarande block        */
			point = point->next;        /* peka till n„sta                */
		} while (point->next !=NULL);    /* sluta n„r next „r NULL      */

		sbfd_music_off();
		exit_midi();
		ShowCur();
		clrscr();
		exit(0);
	}
	draw_screen();
}



get_config_settings(FILE* cfgf)
{
	fread(&channel_on[0],1,16,cfgf);
	fread(&velocity,1,1,cfgf);
	fclose(cfgf);
}

save_config_settings()
{
FILE* cfgf;
	cfgf = fopen("fmsynt.cfg","wb");
	fwrite(&channel_on[0],1,16,cfgf);
	fwrite(&velocity,1,1,cfgf);
	fclose(cfgf);
}

draw_screen()
{
int i;
	clrscr();
	printf("*** THE Sequencer! ***                          Current Program: %-3u\n\n",program);
	printf("^V Set Velocity  ^O All notes off  ^Y FM Editor  ^Z List Files  ^P Load Patch\n\n");
	printf("^L Load 128-patch set  ^S Save 128-patch set  ^W Save Settings  ^C Clear seq\n\n");
	printf("^T Select Track  ^X Solo  (R)ecord  (P)lay  (Q)uit\n\n\n");

	printf("Current Track: %d\n",trk+1);
}

loadpatch()
{
FILE* f;

char patchname[80],patchnumstr[10];

	clrscr();
	ShowCur();

	printf("Name of single patch to load: ");
	gets(patchname);

	if (strlen(patchname) != 0)
	{
		printf("Patch number to load patch into (0-127): ");
		gets(patchnumstr);

		if(f=fopen(patchname,"rb"))
		{
			fread(&InstrBuf[atoi(patchnumstr)][0],16,1,f);
			fclose(f);
		}
		else
		{
			printf("Couldn't find %s!\n",patchname);
			delay(1000);
		}
	}
	if(editmode)
		draw_editscreen();
	else
		draw_screen();
}


loadpatches()
{
char patchsetname[80];

	clrscr();
	ShowCur();
	printf("Name of patch set to load: ");
	gets(patchsetname);

	loadpatches2(patchsetname);

	if(editmode)
		draw_editscreen();
	else
		draw_screen();
}

loadpatches2(char *patchfile)
{
FILE* f;
int i;

	if(f = fopen(patchfile,"rb"))
	{
		for(i=0;i<128;i++)                     /* read instruments */
			fread(&InstrBuf[i][0],1,16,f);
		fclose(f);
	}
	else
	{
		printf("Couldn't find %s!\n",patchfile);
		delay(1000);
	}
}

savepatches()
{
FILE* f;
int i;
char patchsetname[80];

	clrscr();
	ShowCur();
	printf("Save patch set as: ");
	gets(patchsetname);

	f = fopen(patchsetname,"wb");

	for(i=0;i<128;i++)
		fwrite(&InstrBuf[i][0],1,16,f);

	fclose(f);

	if(editmode)
		draw_editscreen();
	else
		draw_screen();
}

listfiles()
{
struct ffblk ffblk;
int done;

	clrscr();

	done = findfirst("*.*",&ffblk,0);
	while (!done)
	{
		printf("%16s", ffblk.ff_name);
		done = findnext(&ffblk);
	}
	printf("\n\nPress any key...");

	getch();

	if(editmode)
		draw_editscreen();
	else
		draw_screen();
}




#include "fmedit.c"