public int dx7_voice_check_for_dead() { int i, b; for (i = 0, b = 1; i < 6; i++, b <<= 1) { if ((Data.dx7_voice_carriers[this.algorithm] & b) == 0) { continue; /* not a carrier, so still a candidate for killing; continue to check next op */ } if (this.op[i].eg.mode == dx7_eg_mode.DX7_EG_FINISHED) { continue; /* carrier, eg finished, so still a candidate */ } if ((this.op[i].eg.mode == dx7_eg_mode.DX7_EG_CONSTANT || this.op[i].eg.mode == dx7_eg_mode.DX7_EG_SUSTAINING || (this.op[i].eg.mode == dx7_eg_mode.DX7_EG_RUNNING && this.op[i].eg.phase == 3)) && (Inline.FP_TO_INT(this.op[i].eg.value) == 0)) { continue; /* eg constant at 0 or decayed to effectively 0, still a candidate */ } return(0); /* if we got this far, this carrier still has output, so return without killing voice */ } //DEBUG_MESSAGE(DB_NOTE, " dx7_voice_check_for_dead: killing voice %p:%d\n", voice, this.note_id); dx7_voice_off(); return(1); }
public void dx7_op_eg_set_increment(hexter_instance instance, int new_rate, int new_level) { int current_level = Inline.FP_TO_INT(this.value); int need_compensation; float duration; this.target = Inline.INT_TO_FP(new_level); if (this.value <= this.target) { /* envelope will be rising */ /* DX7 envelopes, when rising from levels <= 31 to levels * >= 32, include a compensation feature to speed the * attack, thereby making it sound more natural. The * behavior of some of the boundary cases is bizarre, and * this has been exploited by some patch programmers (the * "Watergarden" patch found in the original ROM cartridge * is one example). We try to emulate it here: */ if (this.value <= Constants.INT_TO_FP_31) { if (new_level > 31) { /* rise quickly to 31, then continue normally */ need_compensation = 1; duration = Data.dx7_voice_eg_rate_rise_duration[new_rate] * (Data.dx7_voice_eg_rate_rise_percent[new_level] - Data.dx7_voice_eg_rate_rise_percent[current_level]); } else if (new_level - current_level > 9) { /* these seem to take zero time */ need_compensation = 0; duration = 0.0f; } else { /* these are the exploited delays */ need_compensation = 0; /* -FIX- this doesn't make WATER GDN work? */ duration = Data.dx7_voice_eg_rate_rise_duration[new_rate] * (float)(new_level - current_level) / 100.0f; } } else { need_compensation = 0; duration = Data.dx7_voice_eg_rate_rise_duration[new_rate] * (Data.dx7_voice_eg_rate_rise_percent[new_level] - Data.dx7_voice_eg_rate_rise_percent[current_level]); } } else { need_compensation = 0; duration = Data.dx7_voice_eg_rate_decay_duration[new_rate] * (Data.dx7_voice_eg_rate_decay_percent[current_level] - Data.dx7_voice_eg_rate_decay_percent[new_level]); } duration *= instance.sample_rate; this.duration = (int)Math.Round(duration); if (this.duration < 1) { this.duration = 1; } if (need_compensation != 0) { Int32 precomp_duration = (Constants.INT_TO_FP_31 - this.value + instance.dx7_eg_max_slew - 1) / instance.dx7_eg_max_slew; if (precomp_duration >= this.duration) { this.duration = precomp_duration; this.increment = (this.target - this.value) / this.duration; if (this.increment > instance.dx7_eg_max_slew) { this.duration = (this.target - this.value + instance.dx7_eg_max_slew - 1) / instance.dx7_eg_max_slew; this.increment = (this.target - this.value) / this.duration; } this.in_precomp = 0; } else if (precomp_duration < 1) { this.increment = (this.target - this.value) / this.duration; if (this.increment > instance.dx7_eg_max_slew) { this.duration = (this.target - this.value + instance.dx7_eg_max_slew - 1) / instance.dx7_eg_max_slew; this.increment = (this.target - this.value) / this.duration; } this.in_precomp = 0; } else { this.postcomp_duration = this.duration - precomp_duration; this.duration = precomp_duration; this.increment = (Constants.INT_TO_FP_31 - this.value) / precomp_duration; this.postcomp_increment = (this.target - Constants.INT_TO_FP_31) / this.postcomp_duration; if (this.postcomp_increment > instance.dx7_eg_max_slew) { this.postcomp_duration = (this.target - Constants.INT_TO_FP_31 + instance.dx7_eg_max_slew - 1) / instance.dx7_eg_max_slew; this.postcomp_increment = (this.target - Constants.INT_TO_FP_31) / this.postcomp_duration; } this.in_precomp = 1; } } else { this.increment = (this.target - this.value) / this.duration; if (Math.Abs(this.increment) > instance.dx7_eg_max_slew) { this.duration = (Math.Abs(this.target - this.value) + instance.dx7_eg_max_slew - 1) / instance.dx7_eg_max_slew; this.increment = (this.target - this.value) / this.duration; } this.in_precomp = 0; } }