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

📄 playmidi.c

📁 MIDI解码程序(用VC编写)
💻 C
📖 第 1 页 / 共 5 页
字号:
    {	/* Unlink chorus link */	voice[v1].chorus_link = v1;	voice[v2].chorus_link = v2;    }    voice[v1].status = VOICE_FREE;    voice[v1].temper_instant = 0;}static int find_free_voice(void){    int i, nv = voices, lowest;    int32 lv, v;    for(i = 0; i < nv; i++)	if(voice[i].status == VOICE_FREE)	{	    if(upper_voices <= i)		upper_voices = i + 1;	    return i;	}    upper_voices = voices;    /* Look for the decaying note with the lowest volume */    lv = 0x7FFFFFFF;    lowest = -1;    for(i = 0; i < nv; i++)    {	if(voice[i].status & ~(VOICE_ON | VOICE_DIE) &&	   !(voice[i].sample && voice[i].sample->note_to_use && ISDRUMCHANNEL(voice[i].channel)))	{	    v = voice[i].left_mix;	    if((voice[i].panned==PANNED_MYSTERY) && (voice[i].right_mix>v))		v = voice[i].right_mix;	    if(v<lv)	    {		lv = v;		lowest = i;	    }	}    }    if(lowest != -1 && !prescanning_flag)    {	free_voice(lowest);	ctl_note_event(lowest);    }    return lowest;}static int find_samples(MidiEvent *e, int *vlist){	int i, j, ch, bank, prog, note, nv;	SpecialPatch *s;	Instrument *ip;		ch = e->channel;	if (channel[ch].special_sample > 0) {		if ((s = special_patch[channel[ch].special_sample]) == NULL) {			ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,					"Strange: Special patch %d is not installed",					channel[ch].special_sample);			return 0;		}		note = e->a + channel[ch].key_shift + note_key_offset;		note = (note < 0) ? 0 : ((note > 127) ? 127 : note);		return select_play_sample(s->sample, s->samples, &note, vlist, e);	}	bank = channel[ch].bank;	if (ISDRUMCHANNEL(ch)) {		note = e->a & 0x7f;		instrument_map(channel[ch].mapID, &bank, &note);		if (! (ip = play_midi_load_instrument(1, bank, note)))			return 0;	/* No instrument? Then we can't play. */		/* if (ip->type == INST_GUS && ip->samples != 1)			ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,					"Strange: percussion instrument with %d samples!",					ip->samples); */		/* "keynum" of SF2, and patch option "note=" */		if (ip->sample->note_to_use)			note = ip->sample->note_to_use;	} else {		if ((prog = channel[ch].program) == SPECIAL_PROGRAM)			ip = default_instrument;		else {			instrument_map(channel[ch].mapID, &bank, &prog);			if (! (ip = play_midi_load_instrument(0, bank, prog)))				return 0;	/* No instrument? Then we can't play. */		}		note = ((ip->sample->note_to_use) ? ip->sample->note_to_use : e->a)				+ channel[ch].key_shift + note_key_offset;		note = (note < 0) ? 0 : ((note > 127) ? 127 : note);	}	nv = select_play_sample(ip->sample, ip->samples, &note, vlist, e);	/* Replace the sample if the sample is cached. */	if (! prescanning_flag) {		if (ip->sample->note_to_use)			note = MIDI_EVENT_NOTE(e);		for (i = 0; i < nv; i++) {			j = vlist[i];			if (! opt_realtime_playing && allocate_cache_size > 0					&& ! channel[ch].portamento) {				voice[j].cache = resamp_cache_fetch(voice[j].sample, note);				if (voice[j].cache)	/* cache hit */					voice[j].sample = voice[j].cache->resampled;			} else				voice[j].cache = NULL;		}	}	return nv;}static int select_play_sample(Sample *splist,		int nsp, int *note, int *vlist, MidiEvent *e){	int ch = e->channel, kn = e->a & 0x7f, vel = e->b;	int32 f, fs, ft, fst, fc, fr, cdiff, diff, sample_link;	int8 tt = channel[ch].temper_type;	uint8 tp = channel[ch].rpnmap[RPN_ADDR_0003];	Sample *sp, *spc, *spr;	int16 sf, sn;	double ratio;	int i, j, k, nv, nvc;		if (ISDRUMCHANNEL(ch))		f = fs = freq_table[*note];	else {		if (opt_pure_intonation) {			if (current_keysig < 8)				f = freq_table_pureint[current_freq_table][*note];			else				f = freq_table_pureint[current_freq_table + 12][*note];		} else if (opt_temper_control)			switch (tt) {			case 0:				f = freq_table_tuning[tp][*note];				break;			case 1:				if (current_temper_keysig < 8)					f = freq_table_pytha[							current_temper_freq_table][*note];				else					f = freq_table_pytha[							current_temper_freq_table + 12][*note];				break;			case 2:				if (current_temper_keysig < 8)					f = freq_table_meantone[current_temper_freq_table							+ ((temper_adj) ? 36 : 0)][*note];				else					f = freq_table_meantone[current_temper_freq_table							+ ((temper_adj) ? 24 : 12)][*note];				break;			case 3:				if (current_temper_keysig < 8)					f = freq_table_pureint[current_temper_freq_table							+ ((temper_adj) ? 36 : 0)][*note];				else					f = freq_table_pureint[current_temper_freq_table							+ ((temper_adj) ? 24 : 12)][*note];				break;			default:	/* user-defined temperament */				if ((tt -= 0x40) >= 0 && tt < 4) {					if (current_temper_keysig < 8)						f = freq_table_user[tt][current_temper_freq_table								+ ((temper_adj) ? 36 : 0)][*note];					else						f = freq_table_user[tt][current_temper_freq_table								+ ((temper_adj) ? 24 : 12)][*note];				} else					f = freq_table[*note];				break;			}		else			f = freq_table[*note];		if (! opt_pure_intonation && opt_temper_control				&& tt == 0 && f != freq_table[*note]) {			*note = log(f / 440000.0) / log(2) * 12 + 69.5;			*note = (*note < 0) ? 0 : ((*note > 127) ? 127 : *note);			fs = freq_table[*note];		} else			fs = freq_table[*note];	}	nv = 0;	for (i = 0, sp = splist; i < nsp; i++, sp++) {		/* GUS/SF2 - Scale Tuning */		if ((sf = sp->scale_factor) != 1024) {			sn = sp->scale_freq;			ratio = pow(2.0, (*note - sn) * (sf - 1024) / 12288.0);			ft = f * ratio + 0.5, fst = fs * ratio + 0.5;		} else			ft = f, fst = fs;		if (ISDRUMCHANNEL(ch) && channel[ch].drums[kn] != NULL)			if ((ratio = get_play_note_ratio(ch, kn)) != 1.0)				ft = ft * ratio + 0.5, fst = fst * ratio + 0.5;		if (sp->low_freq <= fst && sp->high_freq >= fst				&& sp->low_vel <= vel && sp->high_vel >= vel				&& ! (sp->inst_type == INST_SF2				&& sp->sample_type == SF_SAMPLETYPE_RIGHT)) {			j = vlist[nv] = find_voice(e);			voice[j].orig_frequency = ft;			MYCHECK(voice[j].orig_frequency);			voice[j].sample = sp;			voice[j].status = VOICE_ON;			nv++;		}	}	if (nv == 0) {	/* we must select at least one sample. */		fr = fc = 0;		spc = spr = NULL;		cdiff = 0x7fffffff;		for (i = 0, sp = splist; i < nsp; i++, sp++) {			/* GUS/SF2 - Scale Tuning */			if ((sf = sp->scale_factor) != 1024) {				sn = sp->scale_freq;				ratio = pow(2.0, (*note - sn) * (sf - 1024) / 12288.0);				ft = f * ratio + 0.5, fst = fs * ratio + 0.5;			} else				ft = f, fst = fs;			if (ISDRUMCHANNEL(ch) && channel[ch].drums[kn] != NULL)				if ((ratio = get_play_note_ratio(ch, kn)) != 1.0)					ft = ft * ratio + 0.5, fst = fst * ratio + 0.5;			diff = abs(sp->root_freq - fst);			if (diff < cdiff) {				if (sp->inst_type == INST_SF2						&& sp->sample_type == SF_SAMPLETYPE_RIGHT) {					fr = ft;	/* reserve */					spr = sp;	/* reserve */				} else {					fc = ft;					spc = sp;					cdiff = diff;				}			}		}		/* If spc is not NULL, a makeshift sample is found. */		/* Otherwise, it's a lonely right sample, but better than nothing. */		j = vlist[nv] = find_voice(e);		voice[j].orig_frequency = (spc) ? fc : fr;		MYCHECK(voice[j].orig_frequency);		voice[j].sample = (spc) ? spc : spr;		voice[j].status = VOICE_ON;		nv++;	}	nvc = nv;	for (i = 0; i < nvc; i++) {		spc = voice[vlist[i]].sample;		/* If it's left sample, there must be right sample. */		if (spc->inst_type == INST_SF2				&& spc->sample_type == SF_SAMPLETYPE_LEFT) {			sample_link = spc->sf_sample_link;			for (j = 0, sp = splist; j < nsp; j++, sp++)				if (sp->inst_type == INST_SF2						&& sp->sample_type == SF_SAMPLETYPE_RIGHT						&& sp->sf_sample_index == sample_link) {					/* right sample is found. */					/* GUS/SF2 - Scale Tuning */					if ((sf = sp->scale_factor) != 1024) {						sn = sp->scale_freq;						ratio = pow(2.0, (*note - sn) * (sf - 1024) / 12288.0);						ft = f * ratio + 0.5;					} else						ft = f;					if (ISDRUMCHANNEL(ch) && channel[ch].drums[kn] != NULL)						if ((ratio = get_play_note_ratio(ch, kn)) != 1.0)							ft = ft * ratio + 0.5;					k = vlist[nv] = find_voice(e);					voice[k].orig_frequency = ft;					MYCHECK(voice[k].orig_frequency);					voice[k].sample = sp;					voice[k].status = VOICE_ON;					nv++;					break;				}		}	}	return nv;}static double get_play_note_ratio(int ch, int note){	int play_note = channel[ch].drums[note]->play_note;	int bank = channel[ch].bank;	ToneBank *dbank;	int def_play_note;		if (play_note == -1)		return 1.0;	instrument_map(channel[ch].mapID, &bank, &note);	dbank = (drumset[bank]) ? drumset[bank] : drumset[0];	if ((def_play_note = dbank->tone[note].play_note) == -1)		return 1.0;	if (play_note >= def_play_note)		return bend_coarse[(play_note - def_play_note) & 0x7f];	else		return 1 / bend_coarse[(def_play_note - play_note) & 0x7f];}/* Only one instance of a note can be playing on a single channel. */static int find_voice(MidiEvent *e){	int ch = e->channel;	int note = MIDI_EVENT_NOTE(e);	int status_check, mono_check;	AlternateAssign *altassign;	int i, lowest = -1;		status_check = (opt_overlap_voice_allow)			? (VOICE_OFF | VOICE_SUSTAINED) : 0xff;	mono_check = channel[ch].mono;	altassign = find_altassign(channel[ch].altassign, note);	for (i = 0; i < upper_voices; i++)		if (voice[i].status == VOICE_FREE) {			lowest = i;	/* lower volume */			break;		}	for (i = 0; i < upper_voices; i++)		if (voice[i].status != VOICE_FREE && voice[i].channel == ch) {			if ((voice[i].note == note && (voice[i].status & status_check))			    || mono_check			    || (altassign && find_altassign(altassign, voice[i].note)))				kill_note(i);			else if (voice[i].note == note &&				 (channel[ch].assign_mode == 0				  || (channel[ch].assign_mode == 1				      && voice[i].proximate_flag == 0)))				kill_note(i);		}	for (i = 0; i < upper_voices; i++)		if (voice[i].channel == ch && voice[i].note == note)			voice[i].proximate_flag = 0;	if (lowest != -1)	/* Found a free voice. */		return lowest;	if (upper_voices < voices)		return upper_voices++;	return reduce_voice();}int32 get_note_freq(Sample *sp, int note){	int32 f;	int16 sf, sn;	double ratio;		f = freq_table[note];	/* GUS/SF2 - Scale Tuning */	if ((sf = sp->scale_factor) != 1024) {		sn = sp->scale_freq;		ratio = pow(2.0, (note - sn) * (sf - 1024) / 12288.0);		f = f * ratio + 0.5;	}	return f;}static int get_panning(int ch, int note,int v){    int pan;	if(channel[ch].panning != NO_PANNING) {pan = (int)channel[ch].panning - 64;}	else {pan = 0;}	if(ISDRUMCHANNEL(ch) &&	 channel[ch].drums[note] != NULL &&	 channel[ch].drums[note]->drum_panning != NO_PANNING) {		pan += channel[ch].drums[note]->drum_panning;	} else {		pan += voice[v].sample->panning;	}	if (pan > 127) pan = 127;	else if (pan < 0) pan = 0;	return pan;}/*! initialize vibrato parameters for a voice. */static void init_voice_vibrato(int v){	Voice *vp = &(voice[v]);	int ch = vp->channel, j, nrpn_vib_flag;	double ratio;	/* if NRPN vibrato is set, it's believed that there must be vibrato. */	nrpn_vib_flag = opt_nrpn_vibrato		&& (channel[ch].vibrato_ratio != 1.0 || channel[ch].vibrato_depth != 0);		/* vibrato sweep */	vp->vibrato_sweep = vp->sample->vibrato_sweep_increment;	vp->vibrato_sweep_position = 0;	/* vibrato rate */	if (nrpn_vib_flag) {		if(vp->sample->vibrato_control_ratio == 0) {			ratio = cnv_Hz_to_vib_ratio(5.0) * channel[ch].vibrato_ratio;		} else {			ratio = (double)vp->sample->vibrato_control_ratio * channel[ch].vibrato_ratio;		}		if (ratio < 0) {ratio = 0;}		vp->vibrato_control_ratio = (int)ratio;	} else {		vp->vibrato_control_ratio = vp->sample->vibrato_control_ratio;	}		/* vibrato depth */	if (nrpn_vib_flag) {		vp->vibrato_depth = vp->sample->vibrato_depth + channel[ch].vibrato_depth;		if (vp->vibrato_depth > VIBRATO_DEPTH_MAX) {vp->vibrato_depth = VIBRATO_DEPTH_MAX;}		else if (vp->vibrato_depth < 1) {vp->vibrato_depth = 1;}		if (vp->sample->vibrato_depth < 0) {	/* in opposite phase */			vp->vibrato_depth = -vp->vibrato_depth;		}	} else {		vp->vibrato_depth = vp->sample->vibrato_depth;	}		/* vibrato delay */	vp->vibrato_delay = vp->sample->vibrato_delay + channel[ch].vibrato_delay;		/* internal parameters */	vp->orig_vibrato_control_ratio = vp->vibrato_control_ratio;	vp->vibrato_control_counter = vp->vibrato_phase = 0;	for (j = 0; j < VIBRATO_SAMPLE_INCREMENTS; j++) {		vp->vibrato_sample_increment[j] = 0;	}}/*! initialize panning-delay for a voice. */static void init_voice_pan_delay(int v){#ifdef ENABLE_PAN_DELAY	Voice *vp = &(voice[v]);	int ch = vp->channel;	double pan_delay_diff; 	if (vp->pan_delay_buf != NULL) {		free(vp->pan_delay_buf);		vp->pan_delay_buf = NULL;	}	vp->pan_delay_rpt = 0;	if (opt_pan_delay && channel[ch].insertion_effect == 0 && !opt_surround_chorus) {		if (vp->panning == 64) {vp->delay += pan_delay_table[64] * play_mode->rate / 1000;}		else {			if(pan_delay_table[vp->panning] > pan_delay_table[127 - vp->panning]) {				pan_delay_diff = pan_delay_table[vp->panning] - pan_delay_table[127 - vp->panning];				vp->delay += (pan_delay_table[vp->panning] - pan_delay_diff) * play_mode->rate / 1000;			} else {				pan_delay_diff = pan_delay_table[127 - vp->panning] - pan_delay_table[vp->panning];				vp->delay += (pan_delay_t

⌨️ 快捷键说明

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