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

📄 rcp.c

📁 MIDI解码程序(用VC编写)
💻 C
📖 第 1 页 / 共 3 页
字号:
/*    TiMidity++ -- MIDI to WAVE converter and player    Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>    Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/#ifdef HAVE_CONFIG_H#include "config.h"#endif /* HAVE_CONFIG_H *//* rcp.c - written by Masanao Izumo <mo@goice.co.jp> */#include <stdio.h>#ifndef NO_STRING_H#include <string.h>#else#include <strings.h>#endif#include "timidity.h"#include "common.h"#include "instrum.h"#include "playmidi.h"#include "readmidi.h"#include "controls.h"#define RCP_MAXCHANNELS 32/* #define RCP_LOOP_CONT_LIMIT 16 */#define RCP_LOOP_TIME_LIMIT 600struct NoteList{    int32 gate;			/* Note length */    int   ch;			/* channel */    int   note;			/* Note number */    struct NoteList *next;	/* next note */};struct RCPNoteTracer{    int gfmt;			/*! RCP format (1 if G36 or G18) */    int32 at;			/*! current time */    int32 tempo;		/*! current tempo (sync with current_tempo) */    int32 tempo_to;		/*! tempo gradate to */    int tempo_grade;		/*! tempo gradation slope */    int tempo_step;		/*! tempo gradation step */    struct NoteList *notes;	/*! note list */    MBlockList pool;		/*! memory pool for notes */    struct NoteList *freelist;	/*! free note list */};#define SETMIDIEVENT(e, at, t, ch, pa, pb) \    { (e).time = (at); (e).type = (t); \      (e).channel = (uint8)(ch); (e).a = (uint8)(pa); (e).b = (uint8)(pb); }#define MIDIEVENT(at, t, ch, pa, pb) \    { MidiEvent event; SETMIDIEVENT(event, at, t, ch, pa, pb); \      readmidi_add_event(&event); }static int read_rcp_track(struct timidity_file *tf, int trackno, int gfmt);static int preprocess_sysex(uint8* ex, int ch, int gt, int vel);/* Note Tracer */static void ntr_init(struct RCPNoteTracer *ntr, int gfmt, int32 at);static void ntr_end(struct RCPNoteTracer *ntr);static void ntr_incr(struct RCPNoteTracer *ntr, int step);static void ntr_note_on(struct RCPNoteTracer *ntr,			int ch, int note, int velo, int gate);static void ntr_wait_all_off(struct RCPNoteTracer *ntr);#define ntr_at(ntr) ((ntr).at)#define USER_EXCLUSIVE_LENGTH 24#define MAX_EXCLUSIVE_LENGTH 1024static uint8 user_exclusive_data[8][USER_EXCLUSIVE_LENGTH];static int32 init_tempo;static int32 init_keysig;static int play_bias;#define TEMPO_GRADATION_SKIP		2#define TEMPO_GRADATION_GRADE		600int read_rcp_file(struct timidity_file *tf, char *magic0, char *fn){    char buff[361], *p;    int ntrack, timebase1, timebase2, i, len, gfmt;    strncpy(buff, magic0, 4);    if(tf_read(buff + 4, 1, 32-4, tf) != 32-4)	return 1;    len = strlen(fn);    if(strncmp(buff, "RCM-PC98V2.0(C)COME ON MUSIC", 28) == 0)    {	/* RCP or R36 */	gfmt = 0;	if(check_file_extension(fn, ".r36", 1))	    current_file_info->file_type = IS_R36_FILE;	else	    current_file_info->file_type = IS_RCP_FILE;    }    else if(strncmp(buff, "COME ON MUSIC RECOMPOSER RCP3.0", 31) == 0)    {	/* G36 or G18 */	gfmt = 1;	if(check_file_extension(fn, ".g18", 1))	    current_file_info->file_type = IS_G18_FILE;	else	    current_file_info->file_type = IS_G36_FILE;    }    else	return 1;    /* title */    if(tf_read(buff, 1, 64, tf) != 64)	return 1;    if(current_file_info->seq_name == NULL)    {	buff[64] = '\0';	for(len = 63; len >= 0; len--)	{	    if(buff[len] == ' ')		buff[len] = '\0';	    else if(buff[len] != '\0')		break;	}	len = SAFE_CONVERT_LENGTH(len + 1);	p = (char *)new_segment(&tmpbuffer, len);	code_convert(buff, p, len, NULL, NULL);	current_file_info->seq_name = (char *)safe_strdup(p);	reuse_mblock(&tmpbuffer);    }    current_file_info->format = 1;    if(!gfmt) /* RCP or R36 */    {	if(tf_read(buff, 1, 336, tf) != 336)	    return 1;#ifndef __BORLANDC__	buff[336] = '\0';	for(len = 335; len >= 0; len--)	{	    if(buff[len] == ' ')		buff[len] = '\0';	    else if(buff[len] != '\0')		break;	}	len = SAFE_CONVERT_LENGTH(len + 1);	p = (char *)new_segment(&tmpbuffer, len);	code_convert(buff, p, len, NULL, NULL);	ctl->cmsg(CMSG_INFO, VERB_VERBOSE, "Memo: %s", p);	reuse_mblock(&tmpbuffer);#else	buff[336] = '\0';	{	char tmp[30];	int i;	for(i=0;i<336;i+=28)	{	strncpy(tmp,buff+i,28);	tmp[28] = '\0';	for(len=28; len>=0; len--)	{	    if(tmp[len] == ' ')			tmp[len] = '\0';	    else if(tmp[len] != '\0')			break;	}	if(tmp[0]=='\0')		continue;	len = SAFE_CONVERT_LENGTH(len + 1);	p = (char *)new_segment(&tmpbuffer, len);	code_convert(tmp, p, len, NULL, NULL);	ctl->cmsg(CMSG_INFO, VERB_VERBOSE, "Memo: %s", p);	reuse_mblock(&tmpbuffer);	}	}#endif	skip(tf, 16);		/* 0x40 */	timebase1 = tf_getc(tf);	init_tempo = tf_getc(tf); /* tempo */	ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Tempo %d", init_tempo);	if(init_tempo < 8 || init_tempo > 250)	    init_tempo = 120;	/* Time Signature: numerator, denominator, Key Signature */	current_file_info->time_sig_n = tf_getc(tf);	ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Time signature(n) %d",		  current_file_info->time_sig_n);	current_file_info->time_sig_d = tf_getc(tf);	ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Time signature(d) %d",		  current_file_info->time_sig_d);	init_keysig = tf_getc(tf);	ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Key signature %d", init_keysig);	if (init_keysig < 0 || init_keysig >= 32)		init_keysig = 0;	play_bias = (int)(signed char)tf_getc(tf);	ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Play bias %d", play_bias);	if(play_bias < -36 || play_bias > 36)	    play_bias = 0;	skip(tf, 12);		/* cm6 */	skip(tf, 4);		/* reserved */	skip(tf, 12);		/* gsd */	skip(tf, 4);		/* reserved */	if((ntrack = tf_getc(tf)) == EOF)	    return 1;	ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Number of tracks %d", ntrack);	if(ntrack != 18 && ntrack != 36)	    ntrack = 18;	timebase2 = tf_getc(tf);	skip(tf, 14);		/* reserved */	skip(tf, 16);		/*  */	skip(tf, 32 * (14 + 2)); /* rhythm definition */    }    else /* G36 or G18 */    {	skip(tf, 64);	/* reserved */	/* memo */	if(tf_read(buff, 1, 360, tf) != 360)	    return 1;	buff[360] = '\0';	for(len = 359; len >= 0; len--)	{	    if(buff[len] == ' ')		buff[len] = '\0';	    else if(buff[len] != '\0')		break;	}	len = SAFE_CONVERT_LENGTH(len + 1);	p = (char *)new_segment(&tmpbuffer, len);	code_convert(buff, p, len, NULL, NULL);	ctl->cmsg(CMSG_INFO, VERB_VERBOSE, "Memo: %s", p);	reuse_mblock(&tmpbuffer);	/* Number of tracks */	ntrack = tf_getc(tf);	ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Number of tracks %d", ntrack);	if(ntrack != 18 && ntrack != 36)	    ntrack = 18;	skip(tf, 1);	timebase1 = tf_getc(tf);	timebase2 = tf_getc(tf);	init_tempo = tf_getc(tf); /* tempo */	ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Tempo %d", init_tempo);	if(init_tempo < 8 || init_tempo > 250)	    init_tempo = 120;	skip(tf, 1); /* ?? */	/* Time Signature: numerator, denominator, Key Signature */	current_file_info->time_sig_n = tf_getc(tf);	ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Time signature(n) %d",		  current_file_info->time_sig_n);	current_file_info->time_sig_d = tf_getc(tf);	ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Time signature(n) %d",		  current_file_info->time_sig_d);	init_keysig = tf_getc(tf);	ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Key signature %d", init_keysig);	if (init_keysig < 0 || init_keysig >= 32)		init_keysig = 0;	play_bias = (int)(signed char)tf_getc(tf);	ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Play bias %d", play_bias);	if(play_bias < -36 || play_bias > 36)	    play_bias = 0;	skip(tf, 6 + 16 + 112);	/* reserved */	skip(tf, 12);		/* gsd */	skip(tf, 4);	skip(tf, 12);		/* gsd */	skip(tf, 4);	skip(tf, 12);		/* cm6 */	skip(tf, 4);	skip(tf, 80);		/* reserved */	skip(tf, 128 * (14 + 2)); /* rhythm definition */    }    /* SysEx data */    for(i = 0; i < 8; i++)    {	int mid;	skip(tf, 24);	/* memo */	if(tf_read(user_exclusive_data[i], 1, USER_EXCLUSIVE_LENGTH, tf)	   != USER_EXCLUSIVE_LENGTH)	    return 1;	mid = user_exclusive_data[i][0];	if(mid > 0 && mid < 0x7e &&	   (current_file_info->mid == 0 || current_file_info->mid >= 0x7e))	    current_file_info->mid = mid;    }    current_file_info->divisions = (timebase1 | (timebase2 << 8));    ctl->cmsg(CMSG_INFO, VERB_DEBUG, "divisions %d",	      current_file_info->divisions);    current_file_info->format = 1;    current_file_info->tracks = ntrack;    if(!IS_URL_SEEK_SAFE(tf->url))	if((tf->url = url_cache_open(tf->url, 1)) == NULL)	    return 1;    for(i = 0; i < ntrack; i++)	if(read_rcp_track(tf, i, gfmt))	{	    if(ignore_midi_error)		return 0;	    return 1;	}    return 0;}static void rcp_tempo_set(int32 at, int32 tempo){    int lo, mid, hi;        lo = (tempo & 0xff);    mid = ((tempo >> 8) & 0xff);    hi = ((tempo >> 16) & 0xff);    MIDIEVENT(at, ME_TEMPO, lo, hi, mid);}static int32 rcp_tempo_change(struct RCPNoteTracer *ntr, int a, int b){    int32 tempo;        tempo = (int32)((uint32)60000000 * 64 / (init_tempo * a));	/* 6*10^7 / (ini*a/64) */    ntr->tempo_grade = b;    if (b != 0)    {	ntr->tempo_to = tempo;	ntr->tempo_step = 0;	ntr->tempo_grade *= TEMPO_GRADATION_GRADE * TEMPO_GRADATION_SKIP;	tempo = ntr->tempo;	/* unchanged */    }    else    {	ntr->tempo = tempo;	rcp_tempo_set(ntr_at(*ntr), tempo);    }    return tempo;}static void rcp_timesig_change(int32 at){	int n, d;		n = current_file_info->time_sig_n;	d = current_file_info->time_sig_d;	MIDIEVENT(at, ME_TIMESIG, 0, n, d);}static void rcp_keysig_change(int32 at, int32 key){	int8 sf, mi;		if (key < 8)		sf = key, mi = 0;	else if (key < 16)		sf = 8 - key, mi = 0;	else if (key < 24)		sf = key - 16, mi = 1;	else		sf = 24 - key, mi = 1;	MIDIEVENT(at, ME_KEYSIG, 0, sf, mi);}static char *rcp_cmd_name(int cmd){    if(cmd < 0x80)    {	static char name[16];	sprintf(name, "NoteOn %d", cmd);	return name;    }    switch(cmd)    {      case 0x90: return "UserExclusive0";      case 0x91: return "UserExclusive1";      case 0x92: return "UserExclusive2";      case 0x93: return "UserExclusive3";      case 0x94: return "UserExclusive4";      case 0x95: return "UserExclusive5";      case 0x96: return "UserExclusive6";      case 0x97: return "UserExclusive7";      case 0x98: return "ChannelExclusive";      case 0xc0: return "DX7 function";      case 0xc1: return "DX parameter";      case 0xc2: return "DX RERF";      case 0xc3: return "TX function";      case 0xc5: return "FB-01 P parameter";      case 0xc6: return "FB-01 S System";      case 0xc7: return "TX81Z V VCED";      case 0xc8: return "TX81Z A ACED";      case 0xc9: return "TX81Z P PCED";      case 0xca: return "TX81Z S System";      case 0xcb: return "TX81Z E EFFECT";      case 0xcc: return "DX7-2 R REMOTE SW";      case 0xcd: return "DX7-2 A ACED";      case 0xce: return "DX7-2 P PCED";      case 0xcf: return "TX802 P PCED";      case 0xd0: return "YamahaBase";      case 0xd1: return "YamahaPara";      case 0xd2: return "YamahaDevice";      case 0xd3: return "XGPara";      case 0xdc: return "MKS-7";      case 0xdd: return "RolandBase";      case 0xde: return "RolandPara";      case 0xdf: return "RolandDevice";      case 0xe1: return "BnkLPrg";      case 0xe2: return "Bank&ProgCng";      case 0xe5: return "KeyScan";      case 0xe6: return "ChChange";      case 0xe7: return "TempoChange";      case 0xea: return "ChannelAfterTouch";      case 0xeb: return "ControlChange";      case 0xec: return "ProgChange";      case 0xed: return "AfterTouch";      case 0xee: return "PitchBend";      case 0xf5: return "KeyChange";      case 0xf6: return "Comment";      case 0xf7: return "2ndEvent";      case 0xf8: return "LoopEnd";      case 0xf9: return "LoopStart";      case 0xfc: return "SameMeasure";      case 0xfd: return "MeasureEnd";      case 0xfe: return "EndOfTrack";    }    return "Unknown";}static int rcp_parse_sysex_event(int32 at, uint8 *val, int32 len){    MidiEvent ev, evm[260];    int ne, i;    if(len == 0) {return 0;}    if(parse_sysex_event(val, len, &ev))    {	ev.time = at;	readmidi_add_event(&ev);    }	if ((ne = parse_sysex_event_multi(val, len, evm)) > 0)		for (i = 0; i < ne; i++) {			evm[i].time = at;			readmidi_add_event(&evm[i]);		}        return 0;}#define MAX_STACK_DEPTH 16static int read_rcp_track(struct timidity_file *tf, int trackno, int gfmt){    int32 current_tempo;    int size;    int ch;    long last_point, cmdlen;    int key_offset;    struct RCPNoteTracer ntr;    struct    {	long start_at;		/* loop start time */	long loop_start;	/* loop start seek point */	int  count;		/* loop count */    } stack[MAX_STACK_DEPTH];    int sp;    int i, len;    uint8 sysex[MAX_EXCLUSIVE_LENGTH];    int roland_base_init = 0;    int roland_dev_init = 0;    int roland_base_addr0 = 0;    int roland_base_addr1 = 0;    int roland_device_id = 0x10;    int roland_model_id = 0x16;    int yamaha_base_init = 0;    int yamaha_dev_init = 0;    int yamaha_base_addr0 = 0;    int yamaha_base_addr1 = 0;

⌨️ 快捷键说明

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