예제 #1
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;
            }
        }
예제 #2
0
        public void dx7_lfo_update(UInt64 sample_count)
        {
            UInt64 sample;

            switch (this.lfo_wave)
            {
            default:
            case 0:      /* triangle */
            case 1:      /* saw down */
            case 2:      /* saw up */
                for (sample = 0; sample < sample_count; sample++)
                {
                    this.lfo_buffer[sample] = this.lfo_value;
                    this.lfo_value         += this.lfo_increment;
                    if ((--this.lfo_duration) == 0)
                    {
                        if (this.lfo_phase != 0)
                        {
                            this.lfo_phase     = 0;
                            this.lfo_value     = 0;
                            this.lfo_duration  = this.lfo_duration0;
                            this.lfo_increment = this.lfo_increment0;
                        }
                        else
                        {
                            this.lfo_phase     = 1;
                            this.lfo_value     = Constants.FP_SIZE;
                            this.lfo_duration  = this.lfo_duration1;
                            this.lfo_increment = this.lfo_increment1;
                        }
                    }
                }
                this.lfo_value_for_pitch = Inline.FP_TO_DOUBLE(this.lfo_value) * 2.0 - 1.0;      /* -FIX- this is still ramped for saw! */
                break;

            case 3:      /* square */
                for (sample = 0; sample < sample_count; sample++)
                {
                    this.lfo_buffer[sample] = this.lfo_value;
                    this.lfo_value         += this.lfo_increment;
                    if ((--this.lfo_duration) == 0)
                    {
                        switch (this.lfo_phase)
                        {
                        default:
                        case 0:
                            this.lfo_phase     = 1;
                            this.lfo_duration  = this.lfo_duration1;
                            this.lfo_increment = this.lfo_increment0;
                            break;

                        case 1:
                            this.lfo_phase     = 2;
                            this.lfo_value     = 0;
                            this.lfo_duration  = this.lfo_duration0;
                            this.lfo_increment = 0;
                            break;

                        case 2:
                            this.lfo_phase     = 3;
                            this.lfo_duration  = this.lfo_duration1;
                            this.lfo_increment = this.lfo_increment1;
                            break;

                        case 3:
                            this.lfo_phase     = 0;
                            this.lfo_value     = Constants.FP_SIZE;
                            this.lfo_duration  = this.lfo_duration0;
                            this.lfo_increment = 0;
                            break;
                        }
                    }
                }
                if (this.lfo_phase == 0 || this.lfo_phase == 3)
                {
                    this.lfo_value_for_pitch = 1.0;
                }
                else
                {
                    this.lfo_value_for_pitch = -1.0;
                }
                break;

            case 4:      /* sine */
                for (sample = 0; sample < sample_count; sample++)
                {
                    Int32 phase, index, outx;

                    phase = this.lfo_value;
                    index = (phase >> Constants.FP_TO_SINE_SHIFT) & Constants.SINE_MASK;
                    outx  = Data.dx7_voice_sin_table[index];
                    outx += (Int32)((((Int64)(Data.dx7_voice_sin_table[index + 1] - outx) *
                                      (Int64)(phase & Constants.FP_TO_SINE_MASK)) >>
                                     (Constants.FP_SHIFT + Constants.FP_TO_SINE_SHIFT)));
                    outx = (outx + Constants.FP_SIZE) >> 1;      /* shift to unipolar */
                    this.lfo_buffer[sample] = outx;
                    this.lfo_value         += this.lfo_increment;
                }
                this.lfo_value_for_pitch = Inline.FP_TO_DOUBLE(this.lfo_buffer[sample - 1]) * 2.0 - 1.0;
                break;

            case 5:      /* sample/hold */
                for (sample = 0; sample < sample_count; sample++)
                {
                    this.lfo_buffer[sample] = this.lfo_value;
                    this.lfo_value         += this.lfo_increment;
                    if ((--this.lfo_duration) == 0)
                    {
                        if (this.lfo_phase != 0)
                        {
                            this.lfo_phase     = 0;
                            this.lfo_value     = this.lfo_target;
                            this.lfo_duration  = this.lfo_duration0;
                            this.lfo_increment = 0;
                        }
                        else
                        {
                            this.lfo_phase     = 1;
                            this.lfo_duration  = this.lfo_duration1;
                            this.lfo_target    = StaticRandom.Next(Constants.FP_SIZE);
                            this.lfo_increment = (this.lfo_target - this.lfo_value) /
                                                 (Int32)this.lfo_duration;
                        }
                    }
                }
                this.lfo_value_for_pitch = Inline.FP_TO_DOUBLE(this.lfo_target) * 2.0 - 1.0;
                break;
            }
        }
예제 #3
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);
        }
예제 #4
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);
        }