/**********************************************************/
/* MIDEXT */
/* Extracts Text/SysEx/SP Generic bank from a MIDI file */
/* 951110 Now reads SysEx and text messages > 64K */
/* 951112 Speeded up extraction drastically by reading */
/* the whole file into memory before processing */
/**********************************************************/
#include <stdio.h>
#include <dos.h>
#include <fcntl.h>
#include <dir.h>
#include <string.h>
#include <alloc.h>
#include <string.h>
#include <ctype.h>
#include "midifile.h"
#include <c30hdr.h>
unsigned int midf, destf;
char destfname[80];
int data_exists = 0;
unsigned char inbyte;
unsigned long firstnote_dtime = 0xffffffff;
int sysex_after_firstnote = 0;
unsigned long sysex_len = 0L;
int extmode = 0;
int oldtype = 0xffff;
#define TEXT 0
#define SYSEX 1
#define BANK 2
main(int argc,char **argv)
{
struct ffblk ffblk;
char fname[80], extension[5];
int namelen;
int done, found;
if(argc > 2)
{
initfuncs();
switch(argv[2][0]){
case 't' : extmode = TEXT; break;
case 's' : extmode = SYSEX; break;
case 'b' : extmode = BANK; break;
}
switch(extmode) {
case TEXT: strcpy(extension, ".TXT"); break;
case SYSEX: strcpy(extension, ".SYX"); break;
case BANK: strcpy(extension, ".C30"); break;
}
strcpy(fname, argv[1]);
if(strncmp(fname, "*.", 2) != 0)
{
if(! strchr(fname, '.'))
strcat(fname, ".MID");
namelen = strchr(fname, '.') - fname;
strncpy(destfname, fname, namelen);
destfname[namelen] = 0;
strcat(destfname, extension);
extract(fname);
printf("OK.\n");
}
else
{
done = findfirst(fname, &ffblk, 0);
found = 0;
while(! done)
{
namelen = strchr(ffblk.ff_name,'.') - ffblk.ff_name;
strncpy(destfname, ffblk.ff_name, namelen);
destfname[namelen] = 0;
strcat(destfname, extension);
extract(ffblk.ff_name);
done = findnext(&ffblk);
found++;
}
if(found)
printf("OK.\n");
else
printf("No matching files found\n");
}
}
else
{
printf("MIDEXT v2.0 Extracts text or SysEx from a standard MIDI file\n\n");
printf("usage: midext <midifile[.mid]> <t|s|b>\n");
printf("\n");
printf(" t extract text\n");
printf(" s extract SysEx to raw MIDIEX file\n");
printf(" b extract SysEx to SP Gold Generic instrument bank file\n");
printf("\n");
printf("wildcards allowed\n");
}
}
extract(char *fname)
{
data_exists = 0;
sysex_after_firstnote = 0;
sysex_len = 0L;
oldtype = 0xffff;
if((midf = _open(fname, O_BINARY | O_RDONLY)) != -1)
{
destf = _creat(destfname, 0);
if(extmode == BANK)
{
_write(destf, c30hdr, sizeof(c30hdr)); /* Write bank file header */
_write(destf, &sysex_len, 4); /* Dummy write */
}
mfread();
_close(midf);
if(data_exists)
{
if(extmode == BANK)
{
lseek(destf, (unsigned long)sizeof(c30hdr), SEEK_SET);
_write(destf, &sysex_len, 4); /* Write REAL SysEx length */
}
_close(destf);
if((sysex_after_firstnote) && (extmode != TEXT))
printf("Warning: SysEx data after first note played in file %s\n", strupr(fname));
}
else
{
printf("No data in %s\n", fname);
_close(destf);
remove(destfname);
}
}
else
{
printf("MID file not found!\n");
exit(1);
}
}
error(unsigned char *s)
{
fprintf(stderr,"Error: %s\n",s);
exit(1);
}
mext_noteon(chan,pitch,vol)
{
if(firstnote_dtime == 0xffffffff)
firstnote_dtime = mf_currtime;
}
mext_sysex(unsigned long leng, unsigned char far *mess)
{
static unsigned char sysex = 0xf0;
if(extmode == TEXT) return;
if(! data_exists)
data_exists = 1;
if(mf_currtime > firstnote_dtime)
sysex_after_firstnote = 1;
_write(destf, &sysex, 1);
bufwrite(mess, leng);
sysex_len += (++leng);
}
mext_metatext(int type, unsigned long leng, unsigned char far *mess)
{
static char *ttype[] = {
NULL,
"Text Event", /* type=0x01 */
"Copyright Notice", /* type=0x02 */
"Sequence/Track Name",
"Instrument Name", /* ... */
"Lyric",
"Marker",
"Cue Point", /* type=0x07 */
"Unrecognized"
};
int unrecognized = (sizeof(ttype)/sizeof(char *)) - 1;
unsigned long n, c;
unsigned char far *p = mess;
char msgbuf[81];
int i;
if(extmode != TEXT) return;
if(! data_exists)
data_exists = 1;
if ( type < 1 || type > unrecognized )
type = unrecognized;
if(oldtype != type)
{
oldtype = type;
sprintf(msgbuf,"\r\n Type: %s\r\n\r\n", ttype[type]);
_write(destf, msgbuf, strlen(msgbuf));
}
for ( n = 0L; n < leng; n++ ) {
c = *p++;
sprintf(msgbuf, (isprint(c)||isspace(c)) ? "%c" : "\\0x%02x" , c);
_write(destf, msgbuf, strlen(msgbuf));
}
sprintf(msgbuf, "\r\n");
_write(destf, msgbuf, strlen(msgbuf));
}
bufwrite(unsigned char far *buf, unsigned long len)
{
union REGS regs;
struct SREGS segregs;
unsigned int bytes_to_write;
if(FP_OFF(buf) > 0x8000) {
FP_SEG(buf) += 0x0800;
FP_OFF(buf) -= 0x8000;
}
segregs.ds = FP_SEG(buf);
while(1)
{
regs.h.ah = 0x40 ;
regs.x.bx = destf;
regs.x.dx = FP_OFF(buf);
if(len >= 0x8000L)
bytes_to_write = 0x8000;
else
bytes_to_write = (unsigned int)len;
regs.x.cx = bytes_to_write;
intdosx(®s, ®s, &segregs);
if(bytes_to_write < 0x8000) break;
len -= 0x8000L;
if(len == 0L) break;
segregs.ds += 0x0800;
}
}
initfuncs()
{
mf_error = error;
mf_noteon = mext_noteon;
mf_sysex = mext_sysex;
mf_text = mext_metatext;
}