示例#1
0
        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);
        }
示例#2
0
        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;
            }
        }