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

📄 readmidi.c

📁 MIDI解码程序(用VC编写)
💻 C
📖 第 1 页 / 共 5 页
字号:
/*    TiMidity++ -- MIDI to WAVE converter and player    Copyright (C) 1999-2004 Masanao Izumo <iz@onicos.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 */#include <stdio.h>#include <stdlib.h>#ifndef NO_STRING_H#include <string.h>#else#include <strings.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif /* HAVE_UNISTD_H */#include "timidity.h"#include "common.h"#include "instrum.h"#include "playmidi.h"#include "readmidi.h"#include "output.h"#include "controls.h"#include "strtab.h"#include "memb.h"#include "zip.h"#include "arc.h"#include "mod.h"#include "wrd.h"#include "tables.h"#include "reverb.h"#include <math.h>/* rcp.c */int read_rcp_file(struct timidity_file *tf, char *magic0, char *fn);/* mld.c */extern int read_mfi_file(struct timidity_file *tf);extern char *get_mfi_file_title(struct timidity_file *tf);#define MAX_MIDI_EVENT ((MAX_SAFE_MALLOC_SIZE / sizeof(MidiEvent)) - 1)#define MARKER_START_CHAR	'('#define MARKER_END_CHAR		')'static uint8 rhythm_part[2];	/* for GS */static uint8 drum_setup_xg[16] = { 9, 9, 9, 9, 9, 9, 9, 9,				   9, 9, 9, 9, 9, 9, 9, 9 };	/* for XG */enum{    CHORUS_ST_NOT_OK = 0,    CHORUS_ST_OK};#ifdef ALWAYS_TRACE_TEXT_META_EVENTint opt_trace_text_meta_event = 1;#elseint opt_trace_text_meta_event = 0;#endif /* ALWAYS_TRACE_TEXT_META_EVENT */int opt_default_mid = 0;int opt_system_mid = 0;int ignore_midi_error = 1;ChannelBitMask quietchannels;struct midi_file_info *current_file_info = NULL;int readmidi_error_flag = 0;int readmidi_wrd_mode = 0;int play_system_mode = DEFAULT_SYSTEM_MODE;static MidiEventList *evlist, *current_midi_point;static int32 event_count;static MBlockList mempool;static StringTable string_event_strtab;static int current_read_track;static int karaoke_format, karaoke_title_flag;static struct midi_file_info *midi_file_info = NULL;static char **string_event_table = NULL;static int    string_event_table_size = 0;int    default_channel_program[256];static MidiEvent timesig[256];void init_delay_status_gs(void);void init_chorus_status_gs(void);void init_reverb_status_gs(void);void init_eq_status_gs(void);void init_insertion_effect_gs(void);void init_multi_eq_xg(void);static void init_all_effect_xg(void);/* MIDI ports will be merged in several channels in the future. */int midi_port_number;/* These would both fit into 32 bits, but they are often added in   large multiples, so it's simpler to have two roomy ints */static int32 sample_increment, sample_correction; /*samples per MIDI delta-t*/#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); }#if MAX_CHANNELS <= 16#define MERGE_CHANNEL_PORT(ch) ((int)(ch))#define MERGE_CHANNEL_PORT2(ch, port) ((int)(ch))#else#define MERGE_CHANNEL_PORT(ch) ((int)(ch) | (midi_port_number << 4))#define MERGE_CHANNEL_PORT2(ch, port) ((int)(ch) | ((int)port << 4))#endif#define alloc_midi_event() \    (MidiEventList *)new_segment(&mempool, sizeof(MidiEventList))typedef struct _UserDrumset {	int8 bank;	int8 prog;	int8 play_note;	int8 level;	int8 assign_group;	int8 pan;	int8 reverb_send_level;	int8 chorus_send_level;	int8 rx_note_off;	int8 rx_note_on;	int8 delay_send_level;	int8 source_map;	int8 source_prog;	int8 source_note;	struct _UserDrumset *next;} UserDrumset;UserDrumset *userdrum_first = (UserDrumset *)NULL;UserDrumset *userdrum_last = (UserDrumset *)NULL; void init_userdrum();UserDrumset *get_userdrum(int bank, int prog);void recompute_userdrum(int bank, int prog);void recompute_userdrum_altassign(int bank,int group);typedef struct _UserInstrument {	int8 bank;	int8 prog;	int8 source_map;	int8 source_bank;	int8 source_prog;	int8 vibrato_rate;	int8 vibrato_depth;	int8 cutoff_freq;	int8 resonance;	int8 env_attack;	int8 env_decay;	int8 env_release;	int8 vibrato_delay;	struct _UserInstrument *next;} UserInstrument;UserInstrument *userinst_first = (UserInstrument *)NULL;UserInstrument *userinst_last = (UserInstrument *)NULL; void init_userinst();UserInstrument *get_userinst(int bank, int prog);void recompute_userinst(int bank, int prog);void recompute_userinst_altassign(int bank,int group);int32 readmidi_set_track(int trackno, int rewindp){    current_read_track = trackno;    memset(&chorus_status_gs.text, 0, sizeof(struct chorus_text_gs_t));    if(karaoke_format == 1 && current_read_track == 2)	karaoke_format = 2; /* Start karaoke lyric */    else if(karaoke_format == 2 && current_read_track == 3)	karaoke_format = 3; /* End karaoke lyric */    midi_port_number = 0;    if(evlist == NULL)	return 0;    if(rewindp)	current_midi_point = evlist;    else    {	/* find the last event in the list */	while(current_midi_point->next != NULL)	    current_midi_point = current_midi_point->next;    }    return current_midi_point->event.time;}void readmidi_add_event(MidiEvent *a_event){    MidiEventList *newev;    int32 at;    if(event_count++ == MAX_MIDI_EVENT)    {	if(!readmidi_error_flag)	{	    readmidi_error_flag = 1;	    ctl->cmsg(CMSG_ERROR, VERB_NORMAL,		      "Maxmum number of events is exceeded");	}	return;    }    at = a_event->time;    newev = alloc_midi_event();    newev->event = *a_event;	/* assign by value!!! */    if(at < 0)	/* for safety */	at = newev->event.time = 0;    if(at >= current_midi_point->event.time)    {	/* Forward scan */	MidiEventList *next = current_midi_point->next;	while (next && (next->event.time <= at))	{	    current_midi_point = next;	    next = current_midi_point->next;	}	newev->prev = current_midi_point;	newev->next = next;	current_midi_point->next = newev;	if (next)	    next->prev = newev;    }    else    {	/* Backward scan -- symmetrical to the one above */	MidiEventList *prev = current_midi_point->prev;	while (prev && (prev->event.time > at)) {	    current_midi_point = prev;	    prev = current_midi_point->prev;	}	newev->prev = prev;	newev->next = current_midi_point;	current_midi_point->prev = newev;	if (prev)	    prev->next = newev;    }    current_midi_point = newev;}void readmidi_add_ctl_event(int32 at, int ch, int a, int b){    MidiEvent ev;    if(convert_midi_control_change(ch, a, b, &ev))    {	ev.time = at;	readmidi_add_event(&ev);    }    else	ctl->cmsg(CMSG_INFO, VERB_DEBUG, "(Control ch=%d %d: %d)", ch, a, b);}char *readmidi_make_string_event(int type, char *string, MidiEvent *ev,				 int cnv){    char *text;    int len;    StringTableNode *st;    int a, b;    if(string_event_strtab.nstring == 0)	put_string_table(&string_event_strtab, "", 0);    else if(string_event_strtab.nstring == 0x7FFE)    {	SETMIDIEVENT(*ev, 0, type, 0, 0, 0);	return NULL; /* Over flow */    }    a = (string_event_strtab.nstring & 0xff);    b = ((string_event_strtab.nstring >> 8) & 0xff);    len = strlen(string);    if(cnv)    {	text = (char *)new_segment(&tmpbuffer, SAFE_CONVERT_LENGTH(len) + 1);	code_convert(string, text + 1, SAFE_CONVERT_LENGTH(len), NULL, NULL);    }    else    {	text = (char *)new_segment(&tmpbuffer, len + 1);	memcpy(text + 1, string, len);	text[len + 1] = '\0';    }    st = put_string_table(&string_event_strtab, text, strlen(text + 1) + 1);    reuse_mblock(&tmpbuffer);    text = st->string;    *text = type;    SETMIDIEVENT(*ev, 0, type, 0, a, b);    return text;}static char *readmidi_make_lcd_event(int type, const uint8 *data, MidiEvent *ev){    char *text;    int len;    StringTableNode *st;    int a, b, i;    if(string_event_strtab.nstring == 0)	put_string_table(&string_event_strtab, "", 0);    else if(string_event_strtab.nstring == 0x7FFE)    {	SETMIDIEVENT(*ev, 0, type, 0, 0, 0);	return NULL; /* Over flow */    }    a = (string_event_strtab.nstring & 0xff);    b = ((string_event_strtab.nstring >> 8) & 0xff);    len = 128;    	text = (char *)new_segment(&tmpbuffer, len + 2);    for( i=0; i<64; i++){	const char tbl[]= "0123456789ABCDEF";	text[1+i*2  ]=tbl[data[i]>>4];	text[1+i*2+1]=tbl[data[i]&0xF];    }    text[len + 1] = '\0';            st = put_string_table(&string_event_strtab, text, strlen(text + 1) + 1);    reuse_mblock(&tmpbuffer);    text = st->string;    *text = type;    SETMIDIEVENT(*ev, 0, type, 0, a, b);    return text;}/* Computes how many (fractional) samples one MIDI delta-time unit contains */static void compute_sample_increment(int32 tempo, int32 divisions){  double a;  a = (double) (tempo) * (double) (play_mode->rate) * (65536.0/1000000.0) /    (double)(divisions);  sample_correction = (int32)(a) & 0xFFFF;  sample_increment = (int32)(a) >> 16;  ctl->cmsg(CMSG_INFO, VERB_DEBUG, "Samples per delta-t: %d (correction %d)",       sample_increment, sample_correction);}/* Read variable-length number (7 bits per byte, MSB first) */static int32 getvl(struct timidity_file *tf){    int32 l;    int c;    errno = 0;    l = 0;    /* 1 */    if((c = tf_getc(tf)) == EOF)	goto eof;    if(!(c & 0x80)) return l | c;    l = (l | (c & 0x7f)) << 7;    /* 2 */    if((c = tf_getc(tf)) == EOF)	goto eof;    if(!(c & 0x80)) return l | c;    l = (l | (c & 0x7f)) << 7;    /* 3 */    if((c = tf_getc(tf)) == EOF)	goto eof;    if(!(c & 0x80)) return l | c;    l = (l | (c & 0x7f)) << 7;    /* 4 */    if((c = tf_getc(tf)) == EOF)	goto eof;    if(!(c & 0x80)) return l | c;    /* Error */    ctl->cmsg(CMSG_ERROR, VERB_NORMAL,	      "%s: Illigal Variable-length quantity format.",	      current_filename);    return -2;  eof:    if(errno)	ctl->cmsg(CMSG_ERROR, VERB_NORMAL,		  "%s: read_midi_event: %s",		  current_filename, strerror(errno));    else	ctl->cmsg(CMSG_ERROR, VERB_NORMAL,		  "Warning: %s: Too shorten midi file.",		  current_filename);    return -1;}static char *add_karaoke_title(char *s1, char *s2){    char *ks;    int k1, k2;    if(s1 == NULL)	return safe_strdup(s2);    k1 = strlen(s1);    k2 = strlen(s2);    if(k2 == 0)	return s1;    ks = (char *)safe_malloc(k1 + k2 + 2);    memcpy(ks, s1, k1);    ks[k1++] = ' ';    memcpy(ks + k1, s2, k2 + 1);    free(s1);	s1 = NULL;    return ks;}

⌨️ 快捷键说明

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