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

📄 mfmidi.cpp

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 CPP
字号:
/* * Read a Standard MIDI File.  Externally-assigned function pointers are * called upon recognizing things in the file.  See midifile(3). *//******************************************************************************       Change Log*       Date    | who : Change*-----------+-----------------------------------------------------------------*  2-Mar-92 | GWL : created changelog; MIDIFILE_ERROR to satisfy compiler*****************************************************************************/#include "stdio.h"#include "mfmidi.h"#include "string.h"#define MIDIFILE_ERROR -1/* public stuff */extern int abort_flag;void Midifile_reader::midifile(){	int ntrks;	midifile_error = 0;	ntrks = readheader();	if (midifile_error) return;	if ( ntrks <= 0 ) {		mferror("No tracks!");		/* no need to return since midifile_error is set */	}	while (ntrks-- > 0 && !midifile_error) readtrack();}int Midifile_reader::readmt(char *s, int skip)    /* read through the "MThd" or "MTrk" header string */    /* if skip == 1, we attempt to skip initial garbage. */{	int nread = 0;	char b[4];	char buff[32];	int c;	char *errmsg = "expecting ";    retry:	while ( nread<4 ) {		c = Mf_getc();		if ( c == EOF ) {			errmsg = "EOF while expecting ";			goto err;		}		b[nread++] = c;	}	/* See if we found the 4 characters we're looking for */	if ( s[0]==b[0] && s[1]==b[1] && s[2]==b[2] && s[3]==b[3] )		return(0);	if ( skip ) {		/* If we are supposed to skip initial garbage, */		/* try again with the next character. */		b[0]=b[1];		b[1]=b[2];		b[2]=b[3];		nread = 3;		goto retry;	}    err:	(void) strcpy(buff,errmsg);	(void) strcat(buff,s);	mferror(buff);	return(0);}int Midifile_reader::egetc()    /* read a single character and abort on EOF */{	int c = Mf_getc();	if ( c == EOF ) {		mferror("premature EOF");		return EOF;	}	Mf_toberead--;	return(c);}int Midifile_reader::readheader()    /* read a header chunk */{	int format, ntrks, division;	if ( readmt("MThd",Mf_skipinit) == EOF )		return(0);	Mf_toberead = read32bit();	if (midifile_error) return MIDIFILE_ERROR;	format = read16bit();	if (midifile_error) return MIDIFILE_ERROR;	ntrks = read16bit();	if (midifile_error) return MIDIFILE_ERROR;	division = read16bit();	if (midifile_error) return MIDIFILE_ERROR;	Mf_header(format,ntrks,division);	/* flush any extra stuff, in case the length of header is not 6 */	while ( Mf_toberead > 0 && !midifile_error)		(void) egetc();	return(ntrks);}void Midifile_reader::readtrack()    /* read a track chunk */{	/* This array is indexed by the high half of a status byte.  It's */	/* value is either the number of bytes needed (1 or 2) for a channel */	/* message, or 0 (meaning it's not  a channel message). */	static int chantype[] = {		0, 0, 0, 0, 0, 0, 0, 0,         /* 0x00 through 0x70 */		2, 2, 2, 2, 1, 1, 2, 0          /* 0x80 through 0xf0 */	};	long lookfor, lng;	int c, c1, type;	int sysexcontinue = 0;  /* 1 if last message was an unfinished sysex */	int running = 0;        /* 1 when running status used */	int status = 0;         /* (possibly running) status byte */	int needed;	if ( readmt("MTrk",0) == EOF )		return;	Mf_toberead = read32bit();	if (midifile_error) return;	Mf_currtime = 0L;    Mf_starttrack();    while ( Mf_toberead > 0 ) {		Mf_currtime += readvarinum();   /* delta time */		if (midifile_error) return;		c = egetc();        if (midifile_error) return;		if ( sysexcontinue && c != 0xf7 ) {			mferror("didn't find expected continuation of a sysex");			return;		}		if ( (c & 0x80) == 0 ) {         /* running status? */			if ( status == 0 ) {				mferror("unexpected running status");				return;			}			running = 1;        } else {			status = c;			running = 0;		}		needed = chantype[ (status>>4) & 0xf ];		if ( needed ) {         /* ie. is it a channel message? */			if ( running )				c1 = c;			else {				c1 = egetc();				if (midifile_error) return;			}			chanmessage( status, c1, (needed>1) ? egetc() : 0 );			if (midifile_error) return;			continue;;		}		switch ( c ) {		case 0xff:                      /* meta event */			type = egetc();			if (midifile_error) return;			/* watch out - Don't combine the next 2 statements */			lng = readvarinum();			if (midifile_error) return;			lookfor = Mf_toberead - lng;			msginit();			while ( Mf_toberead > lookfor ) {				char c = egetc();				if (midifile_error) return;				msgadd(c);			}			metaevent(type);			break;		case 0xf0:              /* start of system exclusive */			/* watch out - Don't combine the next 2 statements */			lng = readvarinum();			if (midifile_error) return;			lookfor = Mf_toberead - lng;			msginit();			msgadd(0xf0);			while ( Mf_toberead > lookfor ) {				c = egetc();				if (midifile_error) return;				msgadd(c);			}			if ( c==0xf7 || Mf_nomerge==0 )				sysex();			else				sysexcontinue = 1;  /* merge into next msg */			break;		case 0xf7:      /* sysex continuation or arbitrary stuff */			/* watch out - Don't combine the next 2 statements */			lng = readvarinum();			if (midifile_error) return;			lookfor = Mf_toberead - lng;			if ( ! sysexcontinue )				msginit();			while ( Mf_toberead > lookfor ) {				c = egetc();				if (midifile_error) return;				msgadd(c);			}			if ( ! sysexcontinue ) {					Mf_arbitrary(msgleng(), msg());			}			else if ( c == 0xf7 ) {				sysex();				sysexcontinue = 0;			}			break;		default:			badbyte(c);			break;		}	}		Mf_endtrack();	return;}void Midifile_reader::badbyte(int c){	char buff[32];	(void) sprintf(buff,"unexpected byte: 0x%02x",c);	mferror(buff);}void Midifile_reader::metaevent(int type){	int leng = msgleng();	char *m = msg();	switch  ( type ) {	case 0x00:			Mf_seqnum(to16bit(m[0],m[1]));		break;	case 0x01:      /* Text event */	case 0x02:      /* Copyright notice */	case 0x03:      /* Sequence/Track name */	case 0x04:      /* Instrument name */	case 0x05:      /* Lyric */	case 0x06:      /* Marker */	case 0x07:      /* Cue point */	case 0x08:	case 0x09:	case 0x0a:	case 0x0b:	case 0x0c:	case 0x0d:	case 0x0e:	case 0x0f:		/* These are all text events */			Mf_text(type,leng,m);		break;	case 0x2f:      /* End of Track */			Mf_eot();		break;	case 0x51:      /* Set tempo */			Mf_tempo(to32bit(0,m[0],m[1],m[2]));		break;	case 0x54:			Mf_smpte(m[0],m[1],m[2],m[3],m[4]);		break;	case 0x58:			Mf_timesig(m[0],m[1],m[2],m[3]);		break;	case 0x59:			Mf_keysig(m[0],m[1]);		break;	case 0x7f:			Mf_sqspecific(leng,m);		break;	default:			Mf_metamisc(type,leng,m);	}}void Midifile_reader::sysex(){	Mf_sysex(msgleng(), msg());}void Midifile_reader::chanmessage(int status, int c1, int c2){	int chan = status & 0xf;	switch ( status & 0xf0 ) {	case NOTEOFF:		Mf_off(chan,c1,c2);		break;	case NOTEON:		Mf_on(chan,c1,c2);		break;	case PRESSURE:		Mf_pressure(chan,c1,c2);		break;	case CONTROLLER:		Mf_controller(chan,c1,c2);		break;	case PITCHBEND:		Mf_pitchbend(chan,c1,c2);		break;	case PROGRAM:		Mf_program(chan,c1);		break;	case CHANPRESSURE:		Mf_chanpressure(chan,c1);		break;	}}/* readvarinum - read a varying-length number, and return the *//* number of characters it took. */long Midifile_reader::readvarinum(){	long value;	int c;	c = egetc();	if (midifile_error) return 0;	value = (long) c;	if ( c & 0x80 ) {		value &= 0x7f;		do {			c = egetc();			if (midifile_error) return 0;			value = (value << 7) + (c & 0x7f);		} while (c & 0x80);	}	return (value);}long Midifile_reader::to32bit(int c1, int c2, int c3, int c4){	long value = 0L;	value = (c1 & 0xff);	value = (value<<8) + (c2 & 0xff);	value = (value<<8) + (c3 & 0xff);	value = (value<<8) + (c4 & 0xff);	return (value);}int Midifile_reader::to16bit(int c1, int c2){	return ((c1 & 0xff ) << 8) + (c2 & 0xff);}long Midifile_reader::read32bit(){	int c1, c2, c3, c4;	c1 = egetc(); if (midifile_error) return 0;	c2 = egetc(); if (midifile_error) return 0;	c3 = egetc(); if (midifile_error) return 0;	c4 = egetc(); if (midifile_error) return 0;	return to32bit(c1,c2,c3,c4);}int Midifile_reader::read16bit(){	int c1, c2;	c1 = egetc(); if (midifile_error) return 0;	c2 = egetc(); if (midifile_error) return 0;	return to16bit(c1,c2);}void Midifile_reader::mferror(char *s){	Mf_error(s);	midifile_error = 1;}/* The code below allows collection of a system exclusive message of *//* arbitrary length.  The Msgbuff is expanded as necessary.  The only *//* visible data/routines are msginit(), msgadd(), msg(), msgleng(). */#define MSGINCREMENT 128Midifile_reader::Midifile_reader(){    Mf_nomerge = 0;    Mf_currtime = 0L;    Mf_skipinit = 0;    Mf_toberead = 0;    Msgbuff = 0;       /* message buffer */    Msgsize = 0;         /* Size of currently allocated Msg */    Msgindex = 0;        /* index of next available location in Msg */}void Midifile_reader::msginit(){	Msgindex = 0;}char *Midifile_reader::msg(){	return(Msgbuff);}int Midifile_reader::msgleng(){	return(Msgindex);}void Midifile_reader::msgadd(int c){	/* If necessary, allocate larger message buffer. */	if ( Msgindex >= Msgsize )		msgenlarge();	Msgbuff[Msgindex++] = c;}void Midifile_reader::msgenlarge(){	char *newmess;	char *oldmess = Msgbuff;	int oldleng = Msgsize;	Msgsize += MSGINCREMENT;	newmess = (char *) Mf_malloc((sizeof(char) * Msgsize) );	/* copy old message into larger new one */	if ( oldmess != 0 ) {		register char *p = newmess;		register char *q = oldmess;		register char *endq = &oldmess[oldleng];		for ( ; q!=endq ; p++,q++ )			*p = *q;		Mf_free(oldmess, oldleng);	}	Msgbuff = newmess;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -