📄 mix.c
字号:
* 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 + -