コード例 #1
0
        public void dx7_voice_calculate_runtime_parameters(hexter_instance instance)
        {
            int    i;
            double freq;

            dx7_pitch_envelope_prepare(instance);
            this.amp_mod_lfo_amd_value  = Inline.INT_TO_FP(-64);  /* force initial setup */
            this.amp_mod_lfo_mods_value = Inline.INT_TO_FP(-64);
            this.amp_mod_env_value      = Inline.INT_TO_FP(-64);
            this.lfo_delay_segment      = 0;
            this.lfo_delay_value        = instance.lfo_delay_value[0];
            this.lfo_delay_duration     = instance.lfo_delay_duration[0];
            this.lfo_delay_increment    = instance.lfo_delay_increment[0];
            this.mods_serial            = instance.mods_serial - 1; /* force mod depths update */
            dx7_portamento_prepare(instance);
            freq = dx7_voice_recalculate_frequency(instance);

            this.volume_value = -1.0f;                     /* force initial setup */
            dx7_voice_recalculate_volume(instance);

            for (i = 0; i < Constants.MAX_DX7_OPERATORS; i++)
            {
                this.op[i].frequency = freq;
                if (this.osc_key_sync != 0)
                {
                    this.op[i].phase = 0;
                }
                this.op[i].dx7_op_recalculate_increment(instance);
                this.op[i].dx7_op_envelope_prepare(instance,
                                                   limit_note(this.key + this.transpose - 24),
                                                   this.velocity);
            }
        }
コード例 #2
0
        public double dx7_voice_recalculate_frequency(hexter_instance instance)
        {
            double freq;

            this.last_port_tuning = instance.tuning;

            instance.fixed_freq_multiplier = instance.tuning / 440.0;

            freq = this.pitch_eg.value + this.portamento.value +
                   instance.pitch_bend -
                   instance.lfo_value_for_pitch *
                   (this.pitch_mod_depth_pmd * Inline.FP_TO_DOUBLE(this.lfo_delay_value) +
                    this.pitch_mod_depth_mods);

            this.last_pitch = freq;

            freq += (double)(limit_note(this.key + this.transpose - 24));

            /* -FIX- this maybe could be optimized */

            /*       a lookup table of 8k values would give ~1.5 cent accuracy,
             *       but then would interpolating that be faster than exp()? */
            freq = instance.tuning * Math.Exp((freq - 69.0) * Constants.M_LN2 / 12.0);

            return(freq);
        }
コード例 #3
0
        public void dx7_pitch_eg_set_phase(hexter_instance instance, int phase)
        {
            this.phase = phase;

            if (phase == 0)
            {
                if (this.level[0] == this.level[1] &&
                    this.level[1] == this.level[2] &&
                    this.level[2] == this.level[3])
                {
                    this.mode  = dx7_eg_mode.DX7_EG_CONSTANT;
                    this.value = Data.dx7_voice_pitch_level_to_shift[this.level[3]];
                }
                else
                {
                    this.mode = dx7_eg_mode.DX7_EG_RUNNING;
                    this.dx7_pitch_eg_set_increment(instance, this.rate[phase], this.level[phase]);
                }
            }
            else
            {
                if (this.mode != dx7_eg_mode.DX7_EG_CONSTANT)
                {
                    this.mode = dx7_eg_mode.DX7_EG_RUNNING;
                    this.dx7_pitch_eg_set_increment(instance, this.rate[phase], this.level[phase]);
                }
            }
        }
コード例 #4
0
 public void dx7_voice_setup_note(hexter_instance instance)
 {
     dx7_voice_set_data(instance);
     instance.hexter_instance_set_performance_data();
     dx7_lfo_set(instance);
     dx7_voice_calculate_runtime_parameters(instance);
 }
コード例 #5
0
        public void dx7_pitch_eg_set_increment(hexter_instance instance, int new_rate, int new_level)
        {
            double duration;

            /* translate 0-99 level to shift in semitones */
            this.target = Data.dx7_voice_pitch_level_to_shift[new_level];

            /* -FIX- This is just a quick approximation that I derived from
             * regression of Godric Wilkie's pitch eg timings. In particular,
             * it's not accurate for very slow envelopes. */
            duration = Math.Exp(((double)new_rate - 70.337897) / -25.580953) *
                       Math.Abs((this.target - this.value) / 96.0);

            duration *= (double)instance.nugget_rate;

            this.duration = (int)Math.Round(duration);

            if (this.duration > 1)
            {
                this.increment = (this.target - this.value) / this.duration;
            }
            else
            {
                this.duration  = 1;
                this.increment = this.target - this.value;
            }
        }
コード例 #6
0
ファイル: dx7_op_eg.cs プロジェクト: bpfliegel/sixport
        /*
         * dx7_op_eg_set_next_phase
         *
         * assumes a DX7_EG_RUNNING envelope
         */
        public void dx7_op_eg_set_next_phase(hexter_instance instance)
        {
            switch (this.phase)
            {
            case 0:
            case 1:
                this.phase++;
                dx7_op_eg_set_increment(instance, this.rate[this.phase], this.level[this.phase]);
                if (this.duration == 1 && this.increment == 0)
                {
                    dx7_op_eg_set_next_phase(instance);
                }
                break;

            case 2:
                this.mode      = dx7_eg_mode.DX7_EG_SUSTAINING;
                this.increment = 0;
                this.duration  = -1;
                break;

            case 3:
            default:     /* shouldn't be anything but 0 to 3 */
                this.mode      = dx7_eg_mode.DX7_EG_FINISHED;
                this.increment = 0;
                this.duration  = -1;
                break;
            }
        }
コード例 #7
0
        public void dx7_portamento_process(hexter_instance instance)
        {
            if (this.segment == 0)
            {
                return;
            }

            this.value += this.increment;
            this.duration--;

            if (this.duration == 1)
            {
                this.increment = this.target - this.value;  /* correct any rounding error */
            }
            else if (this.duration == 0)
            {
                if (--this.segment > 0)
                {
                    this.dx7_portamento_set_segment(instance);
                }
                else
                {
                    this.value = 0.0;
                }
            }
        }
コード例 #8
0
        void dx7_voice_recalculate_volume(hexter_instance instance)
        {
            float f;
            int   i;

            this.last_port_volume = instance.volume;
            this.last_cc_volume   = instance.cc_volume;

            /* This 41 OL volume cc mapping matches my TX7 fairly well, to within
             * +/-0.8dB for most of the scale. (It even duplicates the "feature"
             * of not going completely silent at zero....) */
            f  = (instance.volume - 20.0f) * 1.328771f + 86.0f;
            f += (float)instance.cc_volume * 41.0f / 16256.0f;
            i  = (int)Math.Round(f - 0.5f);
            f -= (float)i;
            this.volume_target = (Inline.FP_TO_FLOAT(Data.dx7_voice_eg_ol_to_amp_table[128 + i]) +
                                  f * Inline.FP_TO_FLOAT(Data.dx7_voice_eg_ol_to_amp_table[128 + i + 1] -
                                                         Data.dx7_voice_eg_ol_to_amp_table[128 + i])) *
                                 0.110384f / Data.dx7_voice_carrier_count[this.algorithm];

            if (this.volume_value < 0.0f)
            { /* initial setup */
                this.volume_value    = this.volume_target;
                this.volume_duration = 0;
            }
            else
            {
                this.volume_duration  = instance.ramp_duration;
                this.volume_increment = (this.volume_target - this.volume_value) /
                                        (float)this.volume_duration;
            }
        }
コード例 #9
0
        public void dx7_op_recalculate_increment(hexter_instance instance)
        {
            double freq;

            if (this.osc_mode != 0)
            { /* fixed frequency */
              /* pitch envelope does not affect this */

                /* -FIX- convert this to a table lookup for speed? */
                freq = instance.fixed_freq_multiplier *
                       Math.Exp(Constants.M_LN10 * ((double)(this.coarse & 3) + (double)this.fine / 100.0));
                /* -FIX- figure out what to do with detune */
            }
            else
            {
                freq  = this.frequency;
                freq += ((double)this.detune - 7.0) / 32.0; /* -FIX- is this correct? */
                if (this.coarse != 0)
                {
                    freq = freq * (double)this.coarse;
                }
                else
                {
                    freq = freq / 2.0;
                }
                freq *= (1.0 + ((double)this.fine / 100.0));
            }
            this.phase_increment = (UInt32)Math.Round(freq * (double)Constants.FP_SIZE / (double)instance.sample_rate);
        }
コード例 #10
0
        public void dx7_voice_set_phase(hexter_instance instance, int phase)
        {
            int i;

            for (i = 0; i < Constants.MAX_DX7_OPERATORS; i++)
            {
                this.op[i].eg.dx7_op_eg_set_phase(instance, phase);
            }
            this.pitch_eg.dx7_pitch_eg_set_phase(instance, phase);
        }
コード例 #11
0
        /* dx7_lfo_set_speed
         *
         * called by dx7_lfo_reset() and dx7_lfo_set() to set LFO speed and phase
         */
        public void dx7_lfo_set(hexter_instance instance)
        {
            int set_speed = 0;

            instance.lfo_wave = this.lfo_wave;
            if (instance.lfo_speed != this.lfo_speed)
            {
                instance.lfo_speed = this.lfo_speed;
                set_speed          = 1;
            }
            if (this.lfo_key_sync != 0)
            {
                set_speed = 1; /* because we need to reset the LFO phase */
            }
            if (set_speed != 0)
            {
                instance.dx7_lfo_set_speed();
            }
            if (instance.lfo_delay != this.lfo_delay)
            {
                instance.lfo_delay = this.lfo_delay;
                if (this.lfo_delay > 0)
                {
                    instance.lfo_delay_value[0] = 0;
                    /* -FIX- Jamie's early approximation, replace when he has more data */
                    instance.lfo_delay_duration[0] = (UInt32)
                                                     Math.Round(instance.sample_rate *
                                                                (0.00175338f * (float)(Math.Pow((float)this.lfo_delay, 3.10454f)) + 169.344f - 168.0f) /
                                                                1000.0f);
                    instance.lfo_delay_increment[0] = 0;
                    instance.lfo_delay_value[1]     = 0;
                    /* -FIX- Jamie's early approximation, replace when he has more data */
                    instance.lfo_delay_duration[1] = (UInt32)
                                                     Math.Round(instance.sample_rate *
                                                                (0.321877f * (float)(Math.Pow((float)this.lfo_delay, 2.01163)) + 494.201f - 168.0f) /
                                                                1000.0f);              /* time from note-on until full on */
                    instance.lfo_delay_duration[1] -= instance.lfo_delay_duration[0];  /* now time from end-of-delay until full */
                    instance.lfo_delay_increment[1] = Constants.FP_SIZE / (Int32)instance.lfo_delay_duration[1];
                    instance.lfo_delay_value[2]     = Constants.FP_SIZE;
                    instance.lfo_delay_duration[2]  = 0;
                    instance.lfo_delay_increment[2] = 0;
                }
                else
                {
                    instance.lfo_delay_value[0]     = Constants.FP_SIZE;
                    instance.lfo_delay_duration[0]  = 0;
                    instance.lfo_delay_increment[0] = 0;
                }

                /* -FIX- The TX7 resets the lfo delay for all playing notes at each
                 * new note on. We're not doing that yet, and I don't really wanna,
                 * 'cause it's stupid.... */
            }
        }
コード例 #12
0
        public void dx7_voice_recalculate_freq_and_inc(hexter_instance instance)
        {
            double freq = dx7_voice_recalculate_frequency(instance);
            int    i;

            for (i = 0; i < 6; i++)
            {
                this.op[i].frequency = freq;
                this.op[i].dx7_op_recalculate_increment(instance);
            }
        }
コード例 #13
0
 /*
  * dx7_voice_release_note
  */
 public void dx7_voice_release_note(hexter_instance instance)
 {
     //DEBUG_MESSAGE(DB_NOTE, " dx7_voice_release_note: turning off voice %p\n", voice);
     if (_ON)
     {
         /* dummy up a release velocity */
         this.rvelocity = 64;
     }
     dx7_voice_set_release_phase(instance);
     this.status = dx7_voice_status.DX7_VOICE_RELEASED;
 }
コード例 #14
0
        public void dx7_pitch_eg_process(hexter_instance instance)
        {
            if (this.mode != dx7_eg_mode.DX7_EG_RUNNING)
            {
                return;
            }

            this.value += this.increment;
            this.duration--;

            if (this.duration == 1)
            {
                this.increment = this.target - this.value;  /* correct any rounding error */
            }
            else if (this.duration == 0)
            {
                this.dx7_pitch_eg_set_next_phase(instance);
            }
        }
コード例 #15
0
        /*
         * dx7_pitch_eg_set_next_phase
         *
         * assumes a DX7_EG_RUNNING envelope
         */
        public void dx7_pitch_eg_set_next_phase(hexter_instance instance)
        {
            switch (this.phase)
            {
            case 0:
            case 1:
                this.phase++;
                dx7_pitch_eg_set_increment(instance, this.rate[this.phase],
                                           this.level[this.phase]);
                break;

            case 2:
                this.mode = dx7_eg_mode.DX7_EG_SUSTAINING;
                break;

            case 3:
            default:     /* shouldn't be anything but 0 to 3 */
                this.mode = dx7_eg_mode.DX7_EG_FINISHED;
                break;
            }
        }
コード例 #16
0
        public void dx7_portamento_prepare(hexter_instance instance)
        {
            dx7_portamento port = this.portamento;

            if (instance.portamento_time == 0 ||
                instance.last_key == this.key)
            {
                port.segment = 0;
                port.value   = 0.0;
            }
            else
            {
                /* -FIX- implement portamento time and multi-segment curve */
                float t = ((float)Math.Exp((float)(instance.portamento_time - 99) / 15.0f)) * 18.0f; /* not at all related to what a real DX7 does */
                port.segment  = 1;
                port.value    = (double)(instance.last_key - this.key);
                port.duration = (int)Math.Round(instance.nugget_rate * t);
                port.target   = 0.0;

                port.dx7_portamento_set_segment(instance);
            }
        }
コード例 #17
0
ファイル: dx7_op_eg.cs プロジェクト: bpfliegel/sixport
        public void dx7_op_eg_set_phase(hexter_instance instance, int phase)
        {
            this.phase = phase;

            if (phase == 0)
            {
                if (this.level[0] == this.level[1] &&
                    this.level[1] == this.level[2] &&
                    this.level[2] == this.level[3])
                {
                    this.mode      = dx7_eg_mode.DX7_EG_CONSTANT;
                    this.value     = Inline.INT_TO_FP(this.level[3]);
                    this.increment = 0;
                    this.duration  = -1;
                }
                else
                {
                    this.mode = dx7_eg_mode.DX7_EG_RUNNING;
                    this.dx7_op_eg_set_increment(instance, this.rate[phase], this.level[phase]);
                    if (this.duration == 1 && this.increment == 0)
                    {
                        this.dx7_op_eg_set_next_phase(instance);
                    }
                }
            }
            else
            {
                if (this.mode != dx7_eg_mode.DX7_EG_CONSTANT)
                {
                    this.mode = dx7_eg_mode.DX7_EG_RUNNING;
                    this.dx7_op_eg_set_increment(instance, this.rate[phase], this.level[phase]);
                    if (this.duration == 1 && this.increment == 0)
                    {
                        this.dx7_op_eg_set_next_phase(instance);
                    }
                }
            }
        }
コード例 #18
0
ファイル: dx7_op_eg.cs プロジェクト: bpfliegel/sixport
        public void dx7_op_eg_process(hexter_instance instance)
        {
            this.value += this.increment;

            if (--this.duration == 0)
            {
                if (this.mode != dx7_eg_mode.DX7_EG_RUNNING)
                {
                    this.duration = -1;
                    return;
                }

                if (this.in_precomp != 0)
                {
                    this.in_precomp = 0;
                    this.duration   = this.postcomp_duration;
                    this.increment  = this.postcomp_increment;
                }
                else
                {
                    dx7_op_eg_set_next_phase(instance);
                }
            }
        }
コード例 #19
0
ファイル: dx7_op_eg.cs プロジェクト: bpfliegel/sixport
        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;
            }
        }
コード例 #20
0
 public void dx7_portamento_set_segment(hexter_instance instance)
 {
     /* -FIX- implement portamento multi-segment curve */
     this.increment = (this.target - this.value) / (double)this.duration;
 }
コード例 #21
0
 public void dx7_voice_set_release_phase(hexter_instance instance)
 {
     dx7_voice_set_phase(instance, 3);
 }
コード例 #22
0
        public void dx7_voice_set_data(hexter_instance instance)
        {
            byte[] edit_buffer = instance.current_patch_buffer;
            bool   compat059 = (instance.performance_buffer[0] & 0x01) > 0 ? true : false; /* 0.5.9 compatibility */
            int    i, j;
            double aux_feedbk;

            for (i = 0; i < Constants.MAX_DX7_OPERATORS; i++)
            {
                byte[] eb_op  = edit_buffer;
                int    offset = ((5 - i) * 21);

                this.op[i].output_level = (byte)(Inline.limit(eb_op[16 + offset], 0, 99));

                this.op[i].osc_mode = (byte)(eb_op[17 + offset] & 0x01);
                this.op[i].coarse   = (byte)(eb_op[18 + offset] & 0x1f);
                this.op[i].fine     = (byte)(Inline.limit(eb_op[19 + offset], 0, 99));
                this.op[i].detune   = (byte)(Inline.limit(eb_op[20 + offset], 0, 14));

                this.op[i].level_scaling_bkpoint = (byte)(Inline.limit(eb_op[8 + offset], 0, 99));
                this.op[i].level_scaling_l_depth = (byte)(Inline.limit(eb_op[9 + offset], 0, 99));
                this.op[i].level_scaling_r_depth = (byte)(Inline.limit(eb_op[10 + offset], 0, 99));
                this.op[i].level_scaling_l_curve = (byte)(eb_op[11 + offset] & 0x03);
                this.op[i].level_scaling_r_curve = (byte)(eb_op[12 + offset] & 0x03);
                this.op[i].rate_scaling          = (byte)(eb_op[13 + offset] & 0x07);
                this.op[i].amp_mod_sens          = (byte)((compat059 ? 0 : eb_op[14 + offset] & 0x03));
                this.op[i].velocity_sens         = (byte)(eb_op[15 + offset] & 0x07);

                for (j = 0; j < 4; j++)
                {
                    this.op[i].eg.base_rate[j]  = (byte)(Inline.limit(eb_op[j + offset], 0, 99));
                    this.op[i].eg.base_level[j] = (byte)(Inline.limit(eb_op[4 + j + offset], 0, 99));
                }
            }

            for (i = 0; i < 4; i++)
            {
                this.pitch_eg.rate[i]  = (byte)(Inline.limit(edit_buffer[126 + i], 0, 99));
                this.pitch_eg.level[i] = (byte)(Inline.limit(edit_buffer[130 + i], 0, 99));
            }

            this.algorithm = (byte)(edit_buffer[134] & 0x1f);

            aux_feedbk = (double)(edit_buffer[135] & 0x07) / (2.0 * Constants.M_PI) * 0.18 /* -FIX- feedback_scaling[this.algorithm] */;

            /* the "99.0" here is because we're also using this multiplier to scale the
             * eg level from 0-99 to 0-1 */
            this.feedback_multiplier = (int)Math.Round(aux_feedbk / 99.0 * Constants.FP_SIZE);

            this.osc_key_sync = (byte)(edit_buffer[136] & 0x01);

            this.lfo_speed    = (byte)(Inline.limit(edit_buffer[137], 0, 99));
            this.lfo_delay    = (byte)(Inline.limit(edit_buffer[138], 0, 99));
            this.lfo_pmd      = (byte)(Inline.limit(edit_buffer[139], 0, 99));
            this.lfo_amd      = (byte)(Inline.limit(edit_buffer[140], 0, 99));
            this.lfo_key_sync = (byte)(edit_buffer[141] & 0x01);
            this.lfo_wave     = (byte)(Inline.limit(edit_buffer[142], 0, 5));
            this.lfo_pms      = (byte)((compat059 ? 0 : edit_buffer[143] & 0x07));

            this.transpose = Inline.limit(edit_buffer[144], 0, 48);
        }
コード例 #23
0
        /*
         * dx7_voice_render
         *
         * generate the actual sound data for this voice
         */
        public void dx7_voice_render(hexter_instance instance, double[] outx, UInt64 sample_count)
        {
            UInt64 sample;
            Int32  i;
            Int64  i64;
            Int32  output;

            if ((this.last_port_volume != instance.volume) || (this.last_cc_volume != instance.cc_volume))
            {
                dx7_voice_recalculate_volume(instance);
            }

            for (sample = 0; sample < sample_count; sample++)
            {
                /* calculate amplitude modulation amounts */
                i   = (Int32)(((Int64)(this.amp_mod_lfo_amd_value) * (Int64)(this.lfo_delay_value)) >> Constants.FP_SHIFT);
                i   = this.amp_mod_env_value + (Int32)(((Int64)(i + this.amp_mod_lfo_mods_value) * (Int64)(instance.lfo_buffer[sample])) >> Constants.FP_SHIFT);
                i64 = (Int64)(i);

                ampmod[3] = i;
                ampmod[2] = (Int32)((i64 * Constants.ampmod2) >> Constants.FP_SHIFT);
                ampmod[1] = (Int32)((i64 * Constants.ampmod1) >> Constants.FP_SHIFT);

                switch (this.algorithm)
                {
                case 0:     /* algorithm 1 */

                    /* This first algorithm is all written out, so you can see how it looks */

                    /*
                     * output = (
                     *        dx7_op_calculate_carrier(this.op[Constants.OP_3].eg.value - ampmod[this.op[Constants.OP_3].amp_mod_sens],
                     *                                 (Int32)(this.op[Constants.OP_3].phase) +
                     *                                 dx7_op_calculate_modulator(this.op[Constants.OP_4].eg.value - ampmod[this.op[Constants.OP_4].amp_mod_sens],
                     *                                                            (Int32)(this.op[Constants.OP_4].phase) +
                     *                                                            dx7_op_calculate_modulator(this.op[Constants.OP_5].eg.value - ampmod[this.op[Constants.OP_5].amp_mod_sens],
                     *                                                                                       (Int32)(this.op[Constants.OP_5].phase) +
                     *  // -FIX- need to determine if amp mod is included in feedback, or after
                     *                                                                                       dx7_op_calculate_modulator_saving_feedback(
                     *                                                                                                                                  this.op[Constants.OP_6].eg.value - ampmod[this.op[Constants.OP_6].amp_mod_sens],
                     *                                                                                                                                  (Int32)(this.op[Constants.OP_6].phase) + this.feedback)))) +
                     *        dx7_op_calculate_carrier(this.op[Constants.OP_1].eg.value - ampmod[this.op[Constants.OP_1].amp_mod_sens],
                     *                                 (Int32)(this.op[Constants.OP_1].phase) +
                     *                                 dx7_op_calculate_modulator(this.op[Constants.OP_2].eg.value - ampmod[this.op[Constants.OP_2].amp_mod_sens],
                     *                                                            (Int32)(this.op[Constants.OP_2].phase)))
                     *       );*/

                    output = (
                        car(Constants.OP_3, mod(Constants.OP_4, mod(Constants.OP_5, mod_sfb(Constants.OP_6, this.feedback)))) +
                        car(Constants.OP_1, mod(Constants.OP_2, 0))
                        );

                    break;

                case 1:     /* algorithm 2 */

                    output = (
                        car(Constants.OP_3, mod(Constants.OP_4, mod(Constants.OP_5, mod(Constants.OP_6, 0)))) +
                        car(Constants.OP_1, mod_sfb(Constants.OP_2, this.feedback))
                        );



                    break;


                case 2:     /* algorithm 3 */


                    output = (
                        car(Constants.OP_4, mod(Constants.OP_5, mod_sfb(Constants.OP_6, this.feedback))) +
                        car(Constants.OP_1, mod(Constants.OP_2, mod(Constants.OP_3, 0)))
                        );



                    break;


                case 3:     /* algorithm 4 */


                    output = (
                        car_sfb(Constants.OP_4, mod(Constants.OP_5, mod(Constants.OP_6, this.feedback))) +
                        car(Constants.OP_1, mod(Constants.OP_2, mod(Constants.OP_3, 0)))
                        );



                    break;


                case 4:     /* algorithm 5 */


                    output = (
                        car(Constants.OP_5, mod_sfb(Constants.OP_6, this.feedback)) +
                        car(Constants.OP_3, mod(Constants.OP_4, 0)) +
                        car(Constants.OP_1, mod(Constants.OP_2, 0))
                        );



                    break;


                case 5:     /* algorithm 6 */


                    output = (
                        car_sfb(Constants.OP_5, mod(Constants.OP_6, this.feedback)) +
                        car(Constants.OP_3, mod(Constants.OP_4, 0)) +
                        car(Constants.OP_1, mod(Constants.OP_2, 0))
                        );



                    break;


                case 6:     /* algorithm 7 */


                    output = (
                        car(Constants.OP_3, mod(Constants.OP_5, mod_sfb(Constants.OP_6, this.feedback)) +
                            mod(Constants.OP_4, 0)) +
                        car(Constants.OP_1, mod(Constants.OP_2, 0))
                        );



                    break;


                case 7:     /* algorithm 8 */


                    output = (
                        car(Constants.OP_3, mod(Constants.OP_5, mod(Constants.OP_6, 0)) +
                            mod_sfb(Constants.OP_4, this.feedback)) +
                        car(Constants.OP_1, mod(Constants.OP_2, 0))
                        );



                    break;


                case 8:     /* algorithm 9 */


                    output = (
                        car(Constants.OP_3, mod(Constants.OP_5, mod(Constants.OP_6, 0)) +
                            mod(Constants.OP_4, 0)) +
                        car(Constants.OP_1, mod_sfb(Constants.OP_2, this.feedback))
                        );



                    break;


                case 9:     /* algorithm 10 */


                    output = (
                        car(Constants.OP_4, mod(Constants.OP_6, 0) +
                            mod(Constants.OP_5, 0)) +
                        car(Constants.OP_1, mod(Constants.OP_2, mod_sfb(Constants.OP_3, this.feedback)))
                        );



                    break;


                case 10:     /* algorithm 11 */


                    output = (
                        car(Constants.OP_4, mod_sfb(Constants.OP_6, this.feedback) +
                            mod(Constants.OP_5, 0)) +
                        car(Constants.OP_1, mod(Constants.OP_2, mod(Constants.OP_3, 0)))
                        );



                    break;


                case 11:     /* algorithm 12 */


                    output = (
                        car(Constants.OP_3, mod(Constants.OP_6, 0) +
                            mod(Constants.OP_5, 0) +
                            mod(Constants.OP_4, 0)) +
                        car(Constants.OP_1, mod_sfb(Constants.OP_2, this.feedback))
                        );



                    break;


                case 12:     /* algorithm 13 */


                    output = (
                        car(Constants.OP_3, mod_sfb(Constants.OP_6, this.feedback) +
                            mod(Constants.OP_5, 0) +
                            mod(Constants.OP_4, 0)) +
                        car(Constants.OP_1, mod(Constants.OP_2, 0))
                        );



                    break;


                case 13:     /* algorithm 14 */


                    output = (
                        car(Constants.OP_3, mod(Constants.OP_4, mod_sfb(Constants.OP_6, this.feedback) +
                                                mod(Constants.OP_5, 0))) +
                        car(Constants.OP_1, mod(Constants.OP_2, 0))
                        );



                    break;


                case 14:     /* algorithm 15 */


                    output = (
                        car(Constants.OP_3, mod(Constants.OP_4, mod(Constants.OP_6, 0) +
                                                mod(Constants.OP_5, 0))) +
                        car(Constants.OP_1, mod_sfb(Constants.OP_2, this.feedback))
                        );



                    break;


                case 15:     /* algorithm 16 */


                    output = car(Constants.OP_1, mod(Constants.OP_5, mod_sfb(Constants.OP_6, this.feedback)) +
                                 mod(Constants.OP_3, mod(Constants.OP_4, 0)) +
                                 mod(Constants.OP_2, 0));



                    break;


                case 16:     /* algorithm 17 */


                    output = car(Constants.OP_1, mod(Constants.OP_5, mod(Constants.OP_6, 0)) +
                                 mod(Constants.OP_3, mod(Constants.OP_4, 0)) +
                                 mod_sfb(Constants.OP_2, this.feedback));



                    break;


                case 17:     /* algorithm 18 */


                    output = car(Constants.OP_1, mod(Constants.OP_4, mod(Constants.OP_5, mod(Constants.OP_6, 0))) +
                                 mod_sfb(Constants.OP_3, this.feedback) +
                                 mod(Constants.OP_2, 0));



                    break;


                case 18:     /* algorithm 19 */


                    i      = mod_sfb(Constants.OP_6, this.feedback);
                    output = (
                        car(Constants.OP_5, i) +
                        car(Constants.OP_4, i) +
                        car(Constants.OP_1, mod(Constants.OP_2, mod(Constants.OP_3, 0)))
                        );



                    break;


                case 19:     /* algorithm 20 */


                    i      = mod_sfb(Constants.OP_3, this.feedback);
                    output = (
                        car(Constants.OP_4, mod(Constants.OP_6, 0) +
                            mod(Constants.OP_5, 0)) +
                        car(Constants.OP_2, i) +
                        car(Constants.OP_1, i)
                        );



                    break;


                case 20:     /* algorithm 21 */


                    i      = mod(Constants.OP_6, 0);
                    output = car(Constants.OP_5, i) +
                             car(Constants.OP_4, i);
                    i       = mod_sfb(Constants.OP_3, this.feedback);
                    output += car(Constants.OP_2, i) +
                              car(Constants.OP_1, i);



                    break;


                case 21:     /* algorithm 22 */


                    i      = mod_sfb(Constants.OP_6, this.feedback);
                    output = (
                        car(Constants.OP_5, i) +
                        car(Constants.OP_4, i) +
                        car(Constants.OP_3, i) +
                        car(Constants.OP_1, mod(Constants.OP_2, 0))
                        );



                    break;


                case 22:     /* algorithm 23 */


                    i      = mod_sfb(Constants.OP_6, this.feedback);
                    output = (
                        car(Constants.OP_5, i) +
                        car(Constants.OP_4, i) +
                        car(Constants.OP_2, mod(Constants.OP_3, 0)) +
                        car(Constants.OP_1, 0)
                        );



                    break;


                case 23:     /* algorithm 24 */


                    i      = mod_sfb(Constants.OP_6, this.feedback);
                    output = (
                        car(Constants.OP_5, i) +
                        car(Constants.OP_4, i) +
                        car(Constants.OP_3, i) +
                        car(Constants.OP_2, 0) +
                        car(Constants.OP_1, 0)
                        );



                    break;


                case 24:     /* algorithm 25 */


                    i      = mod_sfb(Constants.OP_6, this.feedback);
                    output = (
                        car(Constants.OP_5, i) +
                        car(Constants.OP_4, i) +
                        car(Constants.OP_3, 0) +
                        car(Constants.OP_2, 0) +
                        car(Constants.OP_1, 0)
                        );



                    break;


                case 25:     /* algorithm 26 */


                    output = (
                        car(Constants.OP_4, mod_sfb(Constants.OP_6, this.feedback) +
                            mod(Constants.OP_5, 0)) +
                        car(Constants.OP_2, mod(Constants.OP_3, 0)) +
                        car(Constants.OP_1, 0)
                        );



                    break;


                case 26:     /* algorithm 27 */


                    output = (
                        car(Constants.OP_4, mod(Constants.OP_6, 0) +
                            mod(Constants.OP_5, 0)) +
                        car(Constants.OP_2, mod_sfb(Constants.OP_3, this.feedback)) +
                        car(Constants.OP_1, 0)
                        );



                    break;


                case 27:     /* algorithm 28 */


                    output = (
                        car(Constants.OP_6, 0) +
                        car(Constants.OP_3, mod(Constants.OP_4, mod_sfb(Constants.OP_5, this.feedback))) +
                        car(Constants.OP_1, mod(Constants.OP_2, 0))
                        );



                    break;


                case 28:     /* algorithm 29 */


                    output = (
                        car(Constants.OP_5, mod_sfb(Constants.OP_6, this.feedback)) +
                        car(Constants.OP_3, mod(Constants.OP_4, 0)) +
                        car(Constants.OP_2, 0) +
                        car(Constants.OP_1, 0)
                        );



                    break;


                case 29:     /* algorithm 30 */


                    output = (
                        car(Constants.OP_6, 0) +
                        car(Constants.OP_3, mod(Constants.OP_4, mod_sfb(Constants.OP_5, this.feedback))) +
                        car(Constants.OP_2, 0) +
                        car(Constants.OP_1, 0)
                        );



                    break;


                case 30:     /* algorithm 31 */


                    output = (
                        car(Constants.OP_5, mod_sfb(Constants.OP_6, this.feedback)) +
                        car(Constants.OP_4, 0) +
                        car(Constants.OP_3, 0) +
                        car(Constants.OP_2, 0) +
                        car(Constants.OP_1, 0)
                        );



                    break;


                case 31:     /* algorithm 32 */
                default:     /* just in case */


                    output = (
                        car_sfb(Constants.OP_6, this.feedback) +
                        car(Constants.OP_5, 0) +
                        car(Constants.OP_4, 0) +
                        car(Constants.OP_3, 0) +
                        car(Constants.OP_2, 0) +
                        car(Constants.OP_1, 0)
                        );



                    break;
                }
                /* this.volume_value contains a scaling factor for the number of carriers */

                /* mix voice output into output buffer */
                outx[sample] += (((double)output) * Constants.FP_TO_FLOAT_DOUBLE) * ((double)this.volume_value);

                /* update runtime parameters for next sample */
                this.op[Constants.OP_6].phase += this.op[Constants.OP_6].phase_increment;
                this.op[Constants.OP_5].phase += this.op[Constants.OP_5].phase_increment;
                this.op[Constants.OP_4].phase += this.op[Constants.OP_4].phase_increment;
                this.op[Constants.OP_3].phase += this.op[Constants.OP_3].phase_increment;
                this.op[Constants.OP_2].phase += this.op[Constants.OP_2].phase_increment;
                this.op[Constants.OP_1].phase += this.op[Constants.OP_1].phase_increment;

                this.op[Constants.OP_6].eg.dx7_op_eg_process(instance);
                this.op[Constants.OP_5].eg.dx7_op_eg_process(instance);
                this.op[Constants.OP_4].eg.dx7_op_eg_process(instance);
                this.op[Constants.OP_3].eg.dx7_op_eg_process(instance);
                this.op[Constants.OP_2].eg.dx7_op_eg_process(instance);
                this.op[Constants.OP_1].eg.dx7_op_eg_process(instance);

                if (this.amp_mod_env_duration != 0)
                {
                    this.amp_mod_env_value += this.amp_mod_env_increment;
                    this.amp_mod_env_duration--;
                }
                if (this.amp_mod_lfo_mods_duration != 0)
                {
                    this.amp_mod_lfo_mods_value += this.amp_mod_lfo_mods_increment;
                    this.amp_mod_lfo_mods_duration--;
                }
                if (this.amp_mod_lfo_amd_duration != 0)
                {
                    this.amp_mod_lfo_amd_value += this.amp_mod_lfo_amd_increment;
                    this.amp_mod_lfo_amd_duration--;
                }
                if (this.lfo_delay_duration != 0)
                {
                    this.lfo_delay_value += this.lfo_delay_increment;
                    if (--this.lfo_delay_duration == 0)
                    {
                        i = ++this.lfo_delay_segment;
                        this.lfo_delay_duration  = instance.lfo_delay_duration[i];
                        this.lfo_delay_value     = instance.lfo_delay_value[i];
                        this.lfo_delay_increment = instance.lfo_delay_increment[i];
                    }
                }
                if (this.volume_duration != 0)
                {
                    this.volume_value += this.volume_increment;
                    this.volume_duration--;
                }
            }
        }
コード例 #24
0
        public void dx7_voice_update_mod_depths(hexter_instance instance)
        {
            byte  kp = instance.key_pressure[this.key];
            byte  cp = instance.channel_pressure;
            float pressure;
            float pdepth, adepth, mdepth, edepth;

            /* add the channel and key pressures together in a way that 'feels' good */
            if (kp > cp)
            {
                pressure  = (float)kp / 127.0f;
                pressure += (1.0f - pressure) * ((float)cp / 127.0f);
            }
            else
            {
                pressure  = (float)cp / 127.0f;
                pressure += (1.0f - pressure) * ((float)kp / 127.0f);
            }

            /* calculate modulation depths */
            pdepth = (float)this.lfo_pmd / 99.0f;
            this.pitch_mod_depth_pmd = (double)Data.dx7_voice_pms_to_semitones[this.lfo_pms] *
                                       (double)pdepth;
            // -FIX- this could be optimized:
            // -FIX- this just adds everything together -- maybe it should limit the result, or
            // combine the various mods like update_pressure() does
            pdepth = (((instance.mod_wheel_assign & 0x01) != 0) ?
                      // -FIX- this assumes that mod_wheel_sensitivity, etc. scale linearly => verify
                      (float)instance.mod_wheel_sensitivity / 15.0f * instance.mod_wheel :
                      0.0f) +
                     (((instance.foot_assign & 0x01) != 0) ?
                      (float)instance.foot_sensitivity / 15.0f * instance.foot :
                      0.0f) +
                     (((instance.pressure_assign & 0x01) != 0) ?
                      (float)instance.pressure_sensitivity / 15.0f * pressure :
                      0.0f) +
                     (((instance.breath_assign & 0x01) != 0) ?
                      (float)instance.breath_sensitivity / 15.0f * instance.breath :
                      0.0f);
            this.pitch_mod_depth_mods = (double)Data.dx7_voice_pms_to_semitones[this.lfo_pms] *
                                        (double)pdepth;

            // -FIX- these are total guesses at how to combine/limit the amp mods:
            adepth = Data.dx7_voice_amd_to_ol_adjustment[this.lfo_amd];
            // -FIX- this could be optimized:
            mdepth = (((instance.mod_wheel_assign & 0x02) != 0) ?
                      Data.dx7_voice_mss_to_ol_adjustment[instance.mod_wheel_sensitivity] *
                      instance.mod_wheel :
                      0.0f) +
                     (((instance.foot_assign & 0x02) != 0) ?
                      Data.dx7_voice_mss_to_ol_adjustment[instance.foot_sensitivity] *
                      instance.foot :
                      0.0f) +
                     (((instance.pressure_assign & 0x02) != 0) ?
                      Data.dx7_voice_mss_to_ol_adjustment[instance.pressure_sensitivity] *
                      pressure :
                      0.0f) +
                     (((instance.breath_assign & 0x02) != 0) ?
                      Data.dx7_voice_mss_to_ol_adjustment[instance.breath_sensitivity] *
                      instance.breath :
                      0.0f);
            edepth = // -FIX- this could be optimized:
                     (((instance.mod_wheel_assign & 0x04) != 0) ?
                      Data.dx7_voice_mss_to_ol_adjustment[instance.mod_wheel_sensitivity] *
                      (1.0f - instance.mod_wheel) :
                      0.0f) +
                     (((instance.foot_assign & 0x04) != 0) ?
                      Data.dx7_voice_mss_to_ol_adjustment[instance.foot_sensitivity] *
                      (1.0f - instance.foot) :
                      0.0f) +
                     (((instance.pressure_assign & 0x04) != 0) ?
                      Data.dx7_voice_mss_to_ol_adjustment[instance.pressure_sensitivity] *
                      (1.0f - pressure) :
                      0.0f) +
                     (((instance.breath_assign & 0x04) != 0) ?
                      Data.dx7_voice_mss_to_ol_adjustment[instance.breath_sensitivity] *
                      (1.0f - instance.breath) :
                      0.0f);

            /* full-scale amp mod for adepth and edepth should be 52.75 and
             * their sum _must_ be limited to less than 128, or bad things will happen! */
            if (adepth > 127.5f)
            {
                adepth = 127.5f;
            }
            if (adepth + mdepth > 127.5f)
            {
                mdepth = 127.5f - adepth;
            }
            if (adepth + mdepth + edepth > 127.5f)
            {
                edepth = 127.5f - (adepth + mdepth);
            }

            this.amp_mod_lfo_amd_target = Inline.FLOAT_TO_FP(adepth);
            if (this.amp_mod_lfo_amd_value <= Inline.INT_TO_FP(-64))
            {
                this.amp_mod_lfo_amd_value     = this.amp_mod_lfo_amd_target;
                this.amp_mod_lfo_amd_increment = 0;
                this.amp_mod_lfo_amd_duration  = 0;
            }
            else
            {
                this.amp_mod_lfo_amd_duration  = instance.ramp_duration;
                this.amp_mod_lfo_amd_increment = (this.amp_mod_lfo_amd_target - this.amp_mod_lfo_amd_value) /
                                                 (Int32)this.amp_mod_lfo_amd_duration;
            }
            this.amp_mod_lfo_mods_target = Inline.FLOAT_TO_FP(mdepth);
            if (this.amp_mod_lfo_mods_value <= Inline.INT_TO_FP(-64))
            {
                this.amp_mod_lfo_mods_value     = this.amp_mod_lfo_mods_target;
                this.amp_mod_lfo_mods_increment = 0;
                this.amp_mod_lfo_mods_duration  = 0;
            }
            else
            {
                this.amp_mod_lfo_mods_duration  = instance.ramp_duration;
                this.amp_mod_lfo_mods_increment = (this.amp_mod_lfo_mods_target - this.amp_mod_lfo_mods_value) /
                                                  (Int32)this.amp_mod_lfo_mods_duration;
            }
            this.amp_mod_env_target = Inline.FLOAT_TO_FP(edepth);
            if (this.amp_mod_env_value <= Inline.INT_TO_FP(-64))
            {
                this.amp_mod_env_value     = this.amp_mod_env_target;
                this.amp_mod_env_increment = 0;
                this.amp_mod_env_duration  = 0;
            }
            else
            {
                this.amp_mod_env_duration  = instance.ramp_duration;
                this.amp_mod_env_increment = (this.amp_mod_env_target - this.amp_mod_env_value) /
                                             (Int32)this.amp_mod_env_duration;
            }
        }
コード例 #25
0
        /*
         * dx7_voice_note_off
         */
        public void dx7_voice_note_off(hexter_instance instance, byte key, byte rvelocity)
        {
            //DEBUG_MESSAGE(DB_NOTE, " dx7_voice_note_off: called for voice %p, key %d\n", voice, key);

            /* save release velocity */
            this.rvelocity = rvelocity;

            if (instance.monophonic != 0)
            {     /* monophonic mode */
                if (instance.held_keys[0] >= 0)
                { /* still some keys held */
                    if (this.key != instance.held_keys[0])
                    {
                        /* most-recently-played key has changed */
                        this.key = (byte)instance.held_keys[0];
                        //DEBUG_MESSAGE(DB_NOTE, " note-off in monophonic section: changing pitch to %d\n", this.key);
                        this.mods_serial = instance.mods_serial - 1;
                        /* -FIX- dx7_portamento_prepare(instance, voice); */
                        dx7_voice_recalculate_freq_and_inc(instance);

                        /* if mono mode is 'both', re-trigger EGs */
                        if (instance.monophonic == Constants.DSSP_MONO_MODE_BOTH && !_RELEASED)
                        {
                            dx7_voice_set_phase(instance, 0);
                        }
                    }
                }
                else
                {  /* no keys still held */
                    if (instance.HEXTER_INSTANCE_SUSTAINED)
                    {
                        /* no more keys in list, but we're sustained */
                        //DEBUG_MESSAGE(DB_NOTE, " note-off in monophonic section: sustained with no held keys\n");
                        if (!_RELEASED)
                        {
                            this.status = dx7_voice_status.DX7_VOICE_SUSTAINED;
                        }
                    }
                    else
                    {  /* not sustained */
                        /* no more keys in list, so turn off note */
                        //DEBUG_MESSAGE(DB_NOTE, " note-off in monophonic section: turning off voice %p\n", voice);
                        dx7_voice_set_release_phase(instance);
                        this.status = dx7_voice_status.DX7_VOICE_RELEASED;
                    }
                }
            }
            else
            {  /* polyphonic mode */
                if (instance.HEXTER_INSTANCE_SUSTAINED)
                {
                    if (!_RELEASED)
                    {
                        this.status = dx7_voice_status.DX7_VOICE_SUSTAINED;
                    }
                }
                else
                {  /* not sustained */
                    dx7_voice_set_release_phase(instance);
                    this.status = dx7_voice_status.DX7_VOICE_RELEASED;
                }
            }
        }
コード例 #26
0
        public void dx7_voice_note_on(hexter_instance instance, byte key, byte velocity)
        {
            int i;

            this.key      = key;
            this.velocity = velocity;

            if (!(instance.monophonic != 0) || !(_ON || _SUSTAINED))
            {
                /* brand-new voice, or monophonic voice in release phase; set
                 * everything up */
                //DEBUG_MESSAGE(DB_NOTE, " dx7_voice_note_on in polyphonic/new section: key %d, mono %d, old status %d\n", key, instance.monophonic, voice.status);
                dx7_voice_setup_note(instance);
            }
            else
            {
                /* synth is monophonic, and we're modifying a playing voice */
                //DEBUG_MESSAGE(DB_NOTE, " dx7_voice_note_on in monophonic section: old key %d => new key %d\n", instance.held_keys[0], key);

                /* retrigger LFO if needed */
                dx7_lfo_set(instance);

                /* set new pitch */
                this.mods_serial = instance.mods_serial - 1;
                /* -FIX- dx7_portamento_prepare(instance, voice); */
                dx7_voice_recalculate_freq_and_inc(instance);

                /* if in 'on' or 'both' modes, and key has changed, then re-trigger EGs */
                if ((instance.monophonic == Constants.DSSP_MONO_MODE_ON ||
                     instance.monophonic == Constants.DSSP_MONO_MODE_BOTH) &&
                    (instance.held_keys[0] < 0 || instance.held_keys[0] != key))
                {
                    dx7_voice_set_phase(instance, 0);
                }

                /* all other variables stay what they are */
            }

            instance.last_key = key;

            if (instance.monophonic != 0)
            {
                /* add new key to the list of held keys */

                /* check if new key is already in the list; if so, move it to the
                 * top of the list, otherwise shift the other keys down and add it
                 * to the top of the list. */
                // DEBUG_MESSAGE(DB_NOTE, " note-on key list before: %d %d %d %d %d %d %d %d\n", instance.held_keys[0], instance.held_keys[1], instance.held_keys[2], instance.held_keys[3], instance.held_keys[4], instance.held_keys[5], instance.held_keys[6], instance.held_keys[7]);
                for (i = 0; i < 7; i++)
                {
                    if (instance.held_keys[i] == key)
                    {
                        break;
                    }
                }
                for (; i > 0; i--)
                {
                    instance.held_keys[i] = instance.held_keys[i - 1];
                }
                instance.held_keys[0] = key;
                // DEBUG_MESSAGE(DB_NOTE, " note-on key list after: %d %d %d %d %d %d %d %d\n", instance.held_keys[0], instance.held_keys[1], instance.held_keys[2], instance.held_keys[3], instance.held_keys[4], instance.held_keys[5], instance.held_keys[6], instance.held_keys[7]);
            }

            if (!_PLAYING)
            {
                dx7_voice_start_voice();
            }
            else if (!_ON)
            {  /* must be DX7_VOICE_SUSTAINED or DX7_VOICE_RELEASED */
                this.status = dx7_voice_status.DX7_VOICE_ON;
            }
        }
コード例 #27
0
        public void dx7_op_envelope_prepare(hexter_instance instance, int transposed_note, int velocity)
        {
            int   scaled_output_level, i, rate_bump;
            float vel_adj;

            scaled_output_level = this.output_level;

            /* things that affect breakpoint calculations: transpose, ? */
            /* things that don't affect breakpoint calculations: pitch envelope, ? */
            if ((transposed_note < this.level_scaling_bkpoint + 21) && (this.level_scaling_l_depth != 0))
            {
                /* On the original DX7/TX7, keyboard level scaling calculations
                 * group the keyboard into groups of three keys.  This can be quite
                 * noticeable on patches with extreme scaling depths, so I've tried
                 * to replicate it here (the steps between levels may not occur at
                 * exactly the keys).  If you'd prefer smother scaling, define
                 * SMOOTH_KEYBOARD_LEVEL_SCALING. */
                //#ifndef SMOOTH_KEYBOARD_LEVEL_SCALING
                i = this.level_scaling_bkpoint - (((transposed_note + 2) / 3) * 3) + 21;
                //#else
                //        i = this.level_scaling_bkpoint - transposed_note + 21;
                //#endif

                switch (this.level_scaling_l_curve)
                {
                case 0:     /* -LIN */
                    scaled_output_level -= (int)((float)i / 45.0f * (float)this.level_scaling_l_depth);
                    break;

                case 1:     /* -EXP */
                    scaled_output_level -= (int)(Math.Exp((float)(i - 72) / 13.5f) * (float)this.level_scaling_l_depth);
                    break;

                case 2:     /* +EXP */
                    scaled_output_level += (int)(Math.Exp((float)(i - 72) / 13.5f) * (float)this.level_scaling_l_depth);
                    break;

                case 3:     /* +LIN */
                    scaled_output_level += (int)((float)i / 45.0f * (float)this.level_scaling_l_depth);
                    break;
                }
                if (scaled_output_level < 0)
                {
                    scaled_output_level = 0;
                }
                if (scaled_output_level > 99)
                {
                    scaled_output_level = 99;
                }
            }
            else if ((transposed_note > this.level_scaling_bkpoint + 21) && (this.level_scaling_r_depth != 0))
            {
                //#ifndef SMOOTH_KEYBOARD_LEVEL_SCALING
                i = (((transposed_note + 2) / 3) * 3) - this.level_scaling_bkpoint - 21;
                //#else
                //        i = transposed_note - op.level_scaling_bkpoint - 21;
                //#endif

                switch (this.level_scaling_r_curve)
                {
                case 0:     /* -LIN */
                    scaled_output_level -= (int)((float)i / 45.0f * (float)this.level_scaling_r_depth);
                    break;

                case 1:     /* -EXP */
                    scaled_output_level -= (int)(Math.Exp((float)(i - 72) / 13.5f) * (float)this.level_scaling_r_depth);
                    break;

                case 2:     /* +EXP */
                    scaled_output_level += (int)(Math.Exp((float)(i - 72) / 13.5f) * (float)this.level_scaling_r_depth);
                    break;

                case 3:     /* +LIN */
                    scaled_output_level += (int)((float)i / 45.0f * (float)this.level_scaling_r_depth);
                    break;
                }
                if (scaled_output_level < 0)
                {
                    scaled_output_level = 0;
                }
                if (scaled_output_level > 99)
                {
                    scaled_output_level = 99;
                }
            }

            vel_adj = Data.dx7_voice_velocity_ol_adjustment[velocity] * (float)this.velocity_sens;

            /* DEBUG_MESSAGE(DB_NOTE, " dx7_op_envelope_prepare: s_o_l=%d, vel_adj=%f\n", scaled_output_level, vel_adj); */

            /* -FIX- This calculation comes from Pinkston/Harrington; the original "* 6.0" scaling factor
             * was close to what my TX7 does, but tended to not bump the rate as much, so I changed it
             * to "* 6.5" which seems a little closer, but it's still not spot-on. */
            /* Things which affect this calculation: transpose, ? */
            /* rate_bump = lrintf((float)op.rate_scaling * (float)(transposed_note - 21) / (126.0f - 21.0f) * 127.0f / 128.0f * 6.0f - 0.5f); */
            rate_bump = (int)Math.Round(((float)this.rate_scaling * (float)(transposed_note - 21) / (126.0f - 21.0f) * 127.0f / 128.0f * 6.5f - 0.5f));
            /* -FIX- just a hunch: try it again with "* 6.0f" but also "(120.0f - 21.0f)" instead of "(126.0f - 21.0f)": */
            /* rate_bump = lrintf((float)op.rate_scaling * (float)(transposed_note - 21) / (120.0f - 21.0f) * 127.0f / 128.0f * 6.0f - 0.5f); */

            for (i = 0; i < 4; i++)
            {
                float level = (float)this.eg.base_level[i];

                /* -FIX- is this scaling of eg.base_level values to og.level values correct, i.e. does a softer
                 * velocity shorten the time, since the rate stays the same? */
                level = level * (float)scaled_output_level / 99.0f + vel_adj;
                if (level < 0.0f)
                {
                    level = 0.0f;
                }
                else if (level > 99.0f)
                {
                    level = 99.0f;
                }

                this.eg.level[i] = (byte)Math.Round(level);

                this.eg.rate[i] = (byte)(this.eg.base_rate[i] + rate_bump);
                if (this.eg.rate[i] > 99)
                {
                    this.eg.rate[i] = 99;
                }
            }

            this.eg.value = Inline.INT_TO_FP(this.eg.level[3]);

            this.eg.dx7_op_eg_set_phase(instance, 0);
        }
コード例 #28
0
 public void dx7_pitch_envelope_prepare(hexter_instance instance)
 {
     this.pitch_eg.value = Data.dx7_voice_pitch_level_to_shift[this.pitch_eg.level[3]];
     this.pitch_eg.dx7_pitch_eg_set_phase(instance, 0);
 }