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

📄 mix.c

📁 MIDI解码程序(用VC编写)
💻 C
📖 第 1 页 / 共 4 页
字号:
	 *  time it will take to decay a note to zero.	 * 2000-3000 msec seem to be decent values to use.	 */	if (stage == EG_GUS_RELEASE1 && vp->sample->modes & MODES_ENVELOPE	    && vp->status & (VOICE_ON | VOICE_SUSTAINED)) {		int32 new_rate;					ch = vp->channel;		/* Don't adjust the current rate if VOICE_ON */		if (vp->status & VOICE_ON)			return 0;				if (min_sustain_time > 0 || channel[ch].loop_timeout > 0) {			if (min_sustain_time == 1)				/* The sustain stage is ignored. */				return next_stage(v);			if (channel[ch].loop_timeout > 0 &&			    channel[ch].loop_timeout * 1000 < min_sustain_time) {				/* timeout (See also "#extension timeout" line in *.cfg file */				sustain_time = channel[ch].loop_timeout * 1000;			}			else {				sustain_time = min_sustain_time;			}			/* Sustain must not be 0 or else lots of dead notes! */			if (channel[ch].sostenuto == 0 &&			    channel[ch].sustain > 0) {				sustain_time *= (double)channel[ch].sustain / 127.0f;			}			/* Calculate the width of the envelope */			envelope_width = sustain_time * play_mode->rate					 / (1000.0f * (double)control_ratio);			if (vp->sample->inst_type == INST_SF2) {				/* If the instrument is SoundFont, it sustains at the sustain stage. */				vp->envelope_increment = -1;				vp->envelope_target = vp->envelope_volume - envelope_width;				if (vp->envelope_target < 0) {vp->envelope_target = 0;}			} else {				/* Otherwise, it decays at the sustain stage. */				vp->envelope_target = 0;				new_rate = vp->envelope_volume / envelope_width;				/* Use the Release1 rate if slower than new rate */				if (vp->sample->envelope_rate[EG_GUS_RELEASE1] &&					vp->sample->envelope_rate[EG_GUS_RELEASE1] < new_rate)						new_rate = vp->sample->envelope_rate[EG_GUS_RELEASE1];				/* Use the Sustain rate if slower than new rate */				/* (Sustain rate exists only in GUS patches) */				if (vp->sample->inst_type == INST_GUS &&					vp->sample->envelope_rate[EG_GUS_SUSTAIN] &&					vp->sample->envelope_rate[EG_GUS_SUSTAIN] < new_rate)						new_rate = vp->sample->envelope_rate[EG_GUS_SUSTAIN];				/* Avoid freezing */				if (!new_rate)					new_rate = 1;				vp->envelope_increment = -new_rate;			}		}		return 0;	}	return next_stage(v);}/* Envelope ran out. */static inline void voice_ran_out(int v){	/* Already displayed as dead */	int died = (voice[v].status == VOICE_DIE);		free_voice(v);	if (! died)		ctl_note_event(v);}static inline int next_stage(int v){	int stage, ch, eg_stage;	int32 offset, val;	FLOAT_T rate;	Voice *vp = &voice[v];	stage = vp->envelope_stage++;	offset = vp->sample->envelope_offset[stage];	rate = vp->sample->envelope_rate[stage];	if (vp->envelope_volume == offset			|| (stage > EG_GUS_SUSTAIN && vp->envelope_volume < offset))		return recompute_envelope(v);	ch = vp->channel;	/* there is some difference between GUS patch and Soundfont at envelope. */	eg_stage = get_eg_stage(v, stage);	/* envelope generator (see also playmidi.[ch]) */	if (ISDRUMCHANNEL(ch))		val = (channel[ch].drums[vp->note] != NULL)				? channel[ch].drums[vp->note]->drum_envelope_rate[eg_stage]				: -1;	else {		if (vp->sample->envelope_keyf[stage])	/* envelope key-follow */			rate *= pow(2.0, (double) (voice[v].note - 60)					* (double)vp->sample->envelope_keyf[stage] / 1200.0f);		val = channel[ch].envelope_rate[eg_stage];	}	if (vp->sample->envelope_velf[stage])	/* envelope velocity-follow */		rate *= pow(2.0, (double) (voice[v].velocity - vp->sample->envelope_velf_bpo)				* (double)vp->sample->envelope_velf[stage] / 1200.0f);	/* just before release-phase, some modifications are necessary */	if (stage > EG_GUS_SUSTAIN) {		/* adjusting release-rate for consistent release-time */		rate *= (double) vp->envelope_volume				/ vp->sample->envelope_offset[EG_GUS_ATTACK];		/* calculating current envelope scale and a inverted value for optimization */		vp->envelope_scale = vp->last_envelope_volume;		vp->inv_envelope_scale = TIM_FSCALE(OFFSET_MAX / (double)vp->envelope_volume, 16);	}	/* regularizing envelope */	if (offset < vp->envelope_volume) {	/* decaying phase */		if (val != -1) {			if(eg_stage > EG_DECAY) {				rate *= sc_eg_release_table[val & 0x7f];			} else {				rate *= sc_eg_decay_table[val & 0x7f];			}			if (fabs(rate) > OFFSET_MAX)				rate = (rate > 0) ? OFFSET_MAX : -OFFSET_MAX;			else if (fabs(rate) < 1)				rate = (rate > 0) ? 1 : -1;		}		if(stage < EG_SF_DECAY && rate > OFFSET_MAX) {	/* instantaneous decay */			vp->envelope_volume = offset;			return recompute_envelope(v);		} else if(rate > vp->envelope_volume - offset) {	/* fastest decay */			rate = -vp->envelope_volume + offset - 1;		} else if (rate < 1) {	/* slowest decay */			rate = -1;		}		else {	/* ordinary decay */			rate = -rate;		}	} else {	/* attacking phase */		if (val != -1) {			rate *= sc_eg_attack_table[val & 0x7f];			if (fabs(rate) > OFFSET_MAX)				rate = (rate > 0) ? OFFSET_MAX : -OFFSET_MAX;			else if (fabs(rate) < 1)				rate = (rate > 0) ? 1 : -1;		}		if(stage < EG_SF_DECAY && rate > OFFSET_MAX) {	/* instantaneous attack */			vp->envelope_volume = offset;			return recompute_envelope(v);		} else if(rate > offset - vp->envelope_volume) {	/* fastest attack */			rate = offset - vp->envelope_volume + 1;		} else if (rate < 1) {rate =  1;}	/* slowest attack */	}	vp->envelope_increment = (int32)rate;	vp->envelope_target = offset;	return 0;}static inline void update_tremolo(int v){	Voice *vp = &voice[v];	int32 depth = vp->tremolo_depth << 7;	if(vp->tremolo_delay > 0)	{		vp->tremolo_delay -= vp->delay_counter;		if(vp->tremolo_delay > 0) {			vp->tremolo_volume = 1.0;			return;		}		vp->tremolo_delay = 0;	}	if (vp->tremolo_sweep) {		/* Update sweep position */		vp->tremolo_sweep_position += vp->tremolo_sweep;		if (vp->tremolo_sweep_position >= 1 << SWEEP_SHIFT)			/* Swept to max amplitude */			vp->tremolo_sweep = 0;		else {			/* Need to adjust depth */			depth *= vp->tremolo_sweep_position;			depth >>= SWEEP_SHIFT;		}	}	vp->tremolo_phase += vp->tremolo_phase_increment;#if 0	if (vp->tremolo_phase >= SINE_CYCLE_LENGTH << RATE_SHIFT)		vp->tremolo_phase -= SINE_CYCLE_LENGTH << RATE_SHIFT;#endif	if(vp->sample->inst_type == INST_SF2) {	vp->tremolo_volume = 1.0 + TIM_FSCALENEG(			lookup_sine(vp->tremolo_phase >> RATE_SHIFT)			* depth * TREMOLO_AMPLITUDE_TUNING, 17);	} else {	vp->tremolo_volume = 1.0 + TIM_FSCALENEG(			lookup_sine(vp->tremolo_phase >> RATE_SHIFT)			* depth * TREMOLO_AMPLITUDE_TUNING, 17);	}	/* I'm not sure about the +1.0 there -- it makes tremoloed voices'	 *  volumes on average the lower the higher the tremolo amplitude.	 */}int apply_envelope_to_amp(int v){	Voice *vp = &voice[v];	FLOAT_T lamp = vp->left_amp, ramp,		*v_table = vp->sample->inst_type == INST_SF2 ? sb_vol_table : vol_table;	int32 la, ra;		if (vp->panned == PANNED_MYSTERY) {		ramp = vp->right_amp;		if (vp->tremolo_phase_increment) {			lamp *= vp->tremolo_volume;			ramp *= vp->tremolo_volume;		}		if (vp->sample->modes & MODES_ENVELOPE) {			if (vp->envelope_stage > 3)				vp->last_envelope_volume = v_table[						imuldiv16(vp->envelope_volume,						vp->inv_envelope_scale) >> 20]						* vp->envelope_scale;			else if (vp->envelope_stage > 1)				vp->last_envelope_volume = v_table[						vp->envelope_volume >> 20];			else				vp->last_envelope_volume = attack_vol_table[				vp->envelope_volume >> 20];			lamp *= vp->last_envelope_volume;			ramp *= vp->last_envelope_volume;		}		la = TIM_FSCALE(lamp, AMP_BITS);		if (la > MAX_AMP_VALUE)			la = MAX_AMP_VALUE;		ra = TIM_FSCALE(ramp, AMP_BITS);		if (ra > MAX_AMP_VALUE)			ra = MAX_AMP_VALUE;		if ((vp->status & (VOICE_OFF | VOICE_SUSTAINED))				&& (la | ra) <= 0) {			free_voice(v);			ctl_note_event(v);			return 1;		}		vp->left_mix = FINAL_VOLUME(la);		vp->right_mix = FINAL_VOLUME(ra);	} else {		if (vp->tremolo_phase_increment)			lamp *= vp->tremolo_volume;		if (vp->sample->modes & MODES_ENVELOPE) {			if (vp->envelope_stage > 3)				vp->last_envelope_volume = v_table[						imuldiv16(vp->envelope_volume,						vp->inv_envelope_scale) >> 20]						* vp->envelope_scale;			else if (vp->envelope_stage > 1)				vp->last_envelope_volume = v_table[						vp->envelope_volume >> 20];			else				vp->last_envelope_volume = attack_vol_table[				vp->envelope_volume >> 20];			lamp *= vp->last_envelope_volume;		}		la = TIM_FSCALE(lamp, AMP_BITS);		if (la > MAX_AMP_VALUE)		la = MAX_AMP_VALUE;		if ((vp->status & (VOICE_OFF | VOICE_SUSTAINED))				&& la <= 0) {			free_voice(v);			ctl_note_event(v);			return 1;		}		vp->left_mix = FINAL_VOLUME(la);	}	return 0;}#ifdef SMOOTH_MIXINGstatic inline void compute_mix_smoothing(Voice *vp){	int32 max_win, delta;		/* reduce popping -- ramp the amp over a <= 0.5 msec window */	max_win = play_mode->rate * 0.0005;	delta = FROM_FINAL_VOLUME(vp->left_mix) - vp->old_left_mix;	if (labs(delta) > max_win) {		vp->left_mix_inc = delta / max_win;		vp->left_mix_offset = vp->left_mix_inc * (1 - max_win);	} else if (delta) {		vp->left_mix_inc = -1;		if (delta > 0)			vp->left_mix_inc = 1;		vp->left_mix_offset = vp->left_mix_inc - delta;	}	delta = FROM_FINAL_VOLUME(vp->right_mix) - vp->old_right_mix;	if (labs(delta) > max_win) {		vp->right_mix_inc = delta / max_win;		vp->right_mix_offset = vp->right_mix_inc * (1 - max_win);	} else if (delta) {		vp->right_mix_inc = -1;		if (delta > 0)			vp->right_mix_inc = 1;		vp->right_mix_offset = vp->right_mix_inc - delta;	}}#endifstatic inline int update_modulation_envelope(int v){	Voice *vp = &voice[v];	if(vp->modenv_delay > 0) {		vp->modenv_delay -= vp->delay_counter;		if(vp->modenv_delay > 0) {return 1;}		vp->modenv_delay = 0;	}	vp->modenv_volume += vp->modenv_increment;	if ((vp->modenv_increment < 0)			^ (vp->modenv_volume > vp->modenv_target)) {		vp->modenv_volume = vp->modenv_target;		if (recompute_modulation_envelope(v)) {			apply_modulation_envelope(v);			return 1;		}	}	apply_modulation_envelope(v);		return 0;}int apply_modulation_envelope(int v){	Voice *vp = &voice[v];	if(!opt_modulation_envelope) {return 0;}	if (vp->sample->modes & MODES_ENVELOPE) {		vp->last_modenv_volume = modenv_vol_table[vp->modenv_volume >> 20];	}	recompute_voice_filter(v);	if(!(vp->porta_control_ratio && vp->porta_control_counter == 0)) {		recompute_freq(v);	}	return 0;}static inline int modenv_next_stage(int v){	int stage, ch, eg_stage;	int32 offset, val;	FLOAT_T rate;	Voice *vp = &voice[v];		stage = vp->modenv_stage++;	offset = vp->sample->modenv_offset[stage];	rate = vp->sample->modenv_rate[stage];	if (vp->modenv_volume == offset			|| (stage > EG_GUS_SUSTAIN && vp->modenv_volume < offset))		return recompute_modulation_envelope(v);	else if(stage < EG_SF_DECAY && rate > OFFSET_MAX) {	/* instantaneous attack */			vp->modenv_volume = offset;			return recompute_modulation_envelope(v);	}	ch = vp->channel;	/* there is some difference between GUS patch and Soundfont at envelope. */	eg_stage = get_eg_stage(v, stage);	/* envelope generator (see also playmidi.[ch]) */	if (ISDRUMCHANNEL(ch))		val = (channel[ch].drums[vp->note] != NULL)				? channel[ch].drums[vp->note]->drum_envelope_rate[eg_stage]				: -1;	else {		if (vp->sample->modenv_keyf[stage])	/* envelope key-follow */			rate *= pow(2.0, (double) (voice[v].note - 60)					* (double)vp->sample->modenv_keyf[stage] / 1200.0f);		val = channel[ch].envelope_rate[eg_stage];	}	if (vp->sample->modenv_velf[stage])		rate *= pow(2.0, (double) (voice[v].velocity - vp->sample->modenv_velf_bpo)				* (double)vp->sample->modenv_velf[stage] / 1200.0f);	/* just before release-phase, some modifications are necessary */	if (stage > EG_GUS_SUSTAIN) {		/* adjusting release-rate for consistent release-time */		rate *= (double) vp->modenv_volume				/ vp->sample->modenv_offset[EG_GUS_ATTACK];	}	/* regularizing envelope */	if (offset < vp->modenv_volume) {	/* decaying phase */		if (val != -1) {			if(stage > EG_DECAY) {				rate *= sc_eg_release_table[val & 0x7f];			} else {				rate *= sc_eg_decay_table[val & 0x7f];			}		}		if(rate > vp->modenv_volume - offset) {	/* fastest decay */			rate = -vp->modenv_volume + offset - 1;		} else if (rate < 1) {	/* slowest decay */			rate = -1;		} else {	/* ordinary decay */			rate = -rate;		}	} else {	/* attacking phase */		if (val != -1)			rate *= sc_eg_attack_table[val & 0x7f];		if(rate > offset - vp->modenv_volume) {	/* fastest attack */			rate = offset - vp->modenv_volume + 1;		} else if (rate < 1) {rate = 1;}	/* slowest attack */	}		vp->modenv_increment = (int32)rate;	vp->modenv_target = offset;	return 0;}int recompute_modulation_envelope(int v){	int stage, ch;	double sustain_time;	int32 modenv_width;	Voice *vp = &voice[v];	if(!opt_modulation_envelope) {return 0;}	stage = vp->modenv_stage;	if (stage > EG_GUS_RELEASE3) {return 1;}	else if (stage > EG_GUS_SUSTAIN && vp->modenv_volume <= 0) {		return 1;	}	/* Routine to sustain modulation envelope	 *	 * Disabled if !min_sustain_time.	 * min_sustain_time is given in msec, and is the minimum	 *  time it will take to sustain a note.	 * 2000-3000 msec seem to be decent values to use.	 */	if (stage == EG_GUS_RELEASE1 && vp->sample->modes & MODES_ENVELOPE	    && vp->status & (VOICE_ON | VOICE_SUSTAINED)) {		ch = vp->channel;		/* Don't adjust the current rate if VOICE_ON */		if (vp->status & VOICE_ON)			return 0;				if (min_sustain_time > 0 || channel[ch].loop_timeout > 0) {			if (min_sustain_time == 1)				/* The sustain stage is ignored. */				return modenv_next_stage(v);			if (channel[ch].loop_timeout > 0 &&			    channel[ch].loop_timeout * 1000 < min_sustain_time) {				/* timeout (See also "#extension timeout" line in *.cfg file */				sustain_time = channel[ch].loop_timeout * 1000;			}			else {				sustain_time = min_sustain_time;			}			/* Sustain must not be 0 or else lots of dead notes! */			if (channel[ch].sostenuto == 0 &&			    channel[ch].sustain > 0) {				sustain_time *= (double)channel[ch].sustain / 127.0f;			}			/* Calculate the width of the envelope */			modenv_width = sustain_time * play_mode->rate				       / (1000.0f * (double)control_ratio);			vp->modenv_increment = -1;			vp->modenv_target = vp->modenv_volume - modenv_width;			if (vp->modenv_target < 0) {vp->modenv_target = 0;}		}		return 0;	}	return modenv_next_stage(v);}

⌨️ 快捷键说明

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