Example #1
0
        /* connect for SLOT 2 */

        /* set algorythm connection */
        static void set_algorythm(OPL_CH CH)
        {
            var carrier = new Func <int,int>(index => outd[index]);

            CH.connect1 = CH.CON != 0 ? carrier : new Func <int,int>(index => feedback2 + index);
            CH.connect2 = carrier;
        }
Example #2
0
        /* ---------- calcrate one of channel ---------- */
        void OPL_CALC_CH(OPL_CH CH)
        {
            uint     env_out;
            OPL_SLOT*SLOT;

            feedback2 = 0;
            /* SLOT 1 */
            SLOT    = &CH.SLOT[SLOT1];
            env_out = OPL_CALC_SLOT(SLOT);
            if (env_out < (uint)(EG_ENT - 1))
            {
                /* PG */
                if (SLOT.vib)
                {
                    SLOT.Cnt += (SLOT.Incr * vib) >> VIB_RATE_SHIFT;
                }
                else
                {
                    SLOT.Cnt += SLOT.Incr;
                }
                /* connection */
                if (CH.FB)
                {
                    int feedback1 = (CH.op1_out[0] + CH.op1_out[1]) >> CH.FB;
                    CH.op1_out[1] = CH.op1_out[0];
                    *CH.connect1 += CH.op1_out[0] = OP_OUT(SLOT,env_out,feedback1);
                }
                else
                {
                    *CH.connect1 += OP_OUT(SLOT,env_out,0);
                }
            }
            else
            {
                CH.op1_out[1] = CH.op1_out[0];
                CH.op1_out[0] = 0;
            }
            /* SLOT 2 */
            SLOT    = &CH.SLOT[SLOT2];
            env_out = OPL_CALC_SLOT(SLOT);
            if (env_out < (uint)(EG_ENT - 1))
            {
                /* PG */
                if (SLOT.vib)
                {
                    SLOT.Cnt += (SLOT.Incr * vib) >> VIB_RATE_SHIFT;
                }
                else
                {
                    SLOT.Cnt += SLOT.Incr;
                }
                /* connection */
                outd[0] += OP_OUT(SLOT,env_out,feedback2);
            }
        }
Example #3
0
        /* set multi,am,vib,EG-TYP,KSR,mul */
        void set_mul(int slot,int v)
        {
            OPL_CH   CH   = P_CH[slot >> 1];
            OPL_SLOT SLOT = CH.SLOT[slot & 1];

            SLOT.mul    = MUL_TABLE[v & 0x0f];
            SLOT.KSR    = (v & 0x10) != 0 ? (byte)0 : (byte)2;
            SLOT.eg_typ = (byte)((v & 0x20) >> 5);
            SLOT.vib    = (byte)(v & 0x40);
            SLOT.ams    = (byte)(v & 0x80);
            CALC_FCSLOT(CH,SLOT);
        }
Example #4
0
        /* set ksl & tl */
        void set_ksl_tl(int slot,int v)
        {
            OPL_CH   CH   = P_CH[slot >> 1];
            OPL_SLOT SLOT = CH.SLOT[slot & 1];
            int      ksl  = v >> 6; /* 0 / 1.5 / 3 / 6 db/OCT */

            SLOT.ksl = ksl != 0 ? (byte)(3 - ksl) : (byte)31;
            SLOT.TL  = (int)((v & 0x3f) * (0.75 / EG_STEP())); /* 0.75db step */

            if ((mode & 0x80) == 0)
            {  /* not CSM latch total level */
                SLOT.TLL = (int)(SLOT.TL + (CH.ksl_base >> SLOT.ksl));
            }
        }
Example #5
0
        /* ---------- frequency counter for operater update ---------- */
        void CALC_FCSLOT(OPL_CH CH,OPL_SLOT SLOT)
        {
            int ksr;

            /* frequency step counter */
            SLOT.Incr = CH.fc * SLOT.mul;
            ksr       = CH.kcode >> SLOT.KSR;

            if (SLOT.ksr != ksr)
            {
                SLOT.ksr = (byte)ksr;
                /* attack , decay rate recalcration */
                SLOT.evsa = SLOT.AR(ksr);
                SLOT.evsd = SLOT.DR(ksr);
                SLOT.evsr = SLOT.RR(ksr);
            }
            SLOT.TLL = (int)(SLOT.TL + (CH.ksl_base >> SLOT.ksl));
        }
Example #6
0
        /* set sustain level & release rate */
        void set_sl_rr(int slot,int v)
        {
            OPL_CH   CH   = P_CH[slot >> 1];
            OPL_SLOT SLOT = CH.SLOT[slot & 1];
            int      sl   = v >> 4;
            int      rr   = v & 0x0f;

            SLOT.SL = SL_TABLE[sl];
            if (SLOT.evm == ENV_MOD_DR)
            {
                SLOT.eve = SLOT.SL;
            }
            SLOT.RR   = new Func <int,int>(index => DR_TABLE[index + rr << 2]);
            SLOT.evsr = SLOT.RR(SLOT.ksr);
            if (SLOT.evm == ENV_MOD_RR)
            {
                SLOT.evs = SLOT.evsr;
            }
        }
Example #7
0
        /* set attack rate & decay rate  */
        void set_ar_dr(int slot,int v)
        {
            OPL_CH   CH   = P_CH[slot >> 1];
            OPL_SLOT SLOT = CH.SLOT[slot & 1];
            int      ar   = v >> 4;
            int      dr   = v & 0x0f;

            SLOT.AR   = ar != 0 ? new Func <int,int>(index => AR_TABLE[index + ar << 2]) : RATE_0;
            SLOT.evsa = SLOT.AR(SLOT.ksr);
            if (SLOT.evm == ENV_MOD_AR)
            {
                SLOT.evs = SLOT.evsa;
            }

            SLOT.DR   = dr != 0 ? new Func <int,int>(index => DR_TABLE[index + dr << 2]) : RATE_0;
            SLOT.evsd = SLOT.DR(SLOT.ksr);
            if (SLOT.evm == ENV_MOD_DR)
            {
                SLOT.evs = SLOT.evsd;
            }
        }
Example #8
0
        /* connect for SLOT 2 */

        /* set algorythm connection */
        static void set_algorythm(OPL_CH CH)
        {
            var carrier = new Func<int,int>(index => outd[index]);
            CH.connect1 = CH.CON != 0 ? carrier : new Func<int,int>(index => feedback2 + index);
            CH.connect2 = carrier;
        }
Example #9
0
        void OPL_CALC_RH(OPL_CH CH)
        {
            uint env_tam, env_sd, env_top, env_hh;
            // This code used to do int(rnd.getRandomBit() * (WHITE_NOISE_db / EG_STEP)),
            // but EG_STEP = 96.0/EG_ENT, and WHITE_NOISE_db=6.0. So, that's equivalent to
            // int(rnd.getRandomBit() * EG_ENT/16). We know that EG_ENT is 4096, or 1024,
            // or 128, so we can safely avoid any FP ops.
            int whitenoise = rnd.getRandomBit() * (EG_ENT >> 4);

            int tone8;

            OPL_SLOT* SLOT;
            int env_out;

            /* BD : same as FM serial mode and output level is large */
            feedback2 = 0;
            /* SLOT 1 */
            SLOT = &CH[6].SLOT[SLOT1];
            env_out = OPL_CALC_SLOT(SLOT);
            if (env_out < EG_ENT - 1)
            {
                /* PG */
                if (SLOT.vib)
                    SLOT.Cnt += (SLOT.Incr * vib) >> VIB_RATE_SHIFT;
                else
                    SLOT.Cnt += SLOT.Incr;
                /* connection */
                if (CH[6].FB)
                {
                    int feedback1 = (CH[6].op1_out[0] + CH[6].op1_out[1]) >> CH[6].FB;
                    CH[6].op1_out[1] = CH[6].op1_out[0];
                    feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT, env_out, feedback1);
                }
                else
                {
                    feedback2 = OP_OUT(SLOT, env_out, 0);
                }
            }
            else
            {
                feedback2 = 0;
                CH[6].op1_out[1] = CH[6].op1_out[0];
                CH[6].op1_out[0] = 0;
            }
            /* SLOT 2 */
            SLOT = &CH[6].SLOT[SLOT2];
            env_out = OPL_CALC_SLOT(SLOT);
            if (env_out < EG_ENT - 1)
            {
                /* PG */
                if (SLOT.vib)
                    SLOT.Cnt += (SLOT.Incr * vib) >> VIB_RATE_SHIFT;
                else
                    SLOT.Cnt += SLOT.Incr;
                /* connection */
                outd[0] += OP_OUT(SLOT, env_out, feedback2) * 2;
            }

            // SD  (17) = mul14[fnum7] + white noise
            // TAM (15) = mul15[fnum8]
            // TOP (18) = fnum6(mul18[fnum8]+whitenoise)
            // HH  (14) = fnum7(mul18[fnum8]+whitenoise) + white noise
            env_sd = OPL_CALC_SLOT(SLOT7_2) + whitenoise;
            env_tam = OPL_CALC_SLOT(SLOT8_1);
            env_top = OPL_CALC_SLOT(SLOT8_2);
            env_hh = OPL_CALC_SLOT(SLOT7_1) + whitenoise;

            /* PG */
            if (SLOT7_1.vib)
                SLOT7_1.Cnt += (SLOT7_1.Incr * vib) >> (VIB_RATE_SHIFT - 1);
            else
                SLOT7_1.Cnt += 2 * SLOT7_1.Incr;
            if (SLOT7_2.vib)
                SLOT7_2.Cnt += (CH[7].fc * vib) >> (VIB_RATE_SHIFT - 3);
            else
                SLOT7_2.Cnt += (CH[7].fc * 8);
            if (SLOT8_1.vib)
                SLOT8_1.Cnt += (SLOT8_1.Incr * vib) >> VIB_RATE_SHIFT;
            else
                SLOT8_1.Cnt += SLOT8_1.Incr;
            if (SLOT8_2.vib)
                SLOT8_2.Cnt += ((CH[8].fc * 3) * vib) >> (VIB_RATE_SHIFT - 4);
            else
                SLOT8_2.Cnt += (CH[8].fc * 48);

            tone8 = OP_OUT(SLOT8_2, whitenoise, 0);

            /* SD */
            if (env_sd < (uint)(EG_ENT - 1))
                outd[0] += OP_OUT(SLOT7_1, env_sd, 0) * 8;
            /* TAM */
            if (env_tam < (uint)(EG_ENT - 1))
                outd[0] += OP_OUT(SLOT8_1, env_tam, 0) * 2;
            /* TOP-CY */
            if (env_top < (uint)(EG_ENT - 1))
                outd[0] += OP_OUT(SLOT7_2, env_top, tone8) * 2;
            /* HH */
            if (env_hh < (uint)(EG_ENT - 1))
                outd[0] += OP_OUT(SLOT7_2, env_hh, tone8) * 2;
        }
Example #10
0
        /* ---------- calcrate one of channel ---------- */
        void OPL_CALC_CH(OPL_CH CH)
        {
            uint env_out;
            OPL_SLOT* SLOT;

            feedback2 = 0;
            /* SLOT 1 */
            SLOT = &CH.SLOT[SLOT1];
            env_out = OPL_CALC_SLOT(SLOT);
            if (env_out < (uint)(EG_ENT - 1))
            {
                /* PG */
                if (SLOT.vib)
                    SLOT.Cnt += (SLOT.Incr * vib) >> VIB_RATE_SHIFT;
                else
                    SLOT.Cnt += SLOT.Incr;
                /* connection */
                if (CH.FB)
                {
                    int feedback1 = (CH.op1_out[0] + CH.op1_out[1]) >> CH.FB;
                    CH.op1_out[1] = CH.op1_out[0];
                    *CH.connect1 += CH.op1_out[0] = OP_OUT(SLOT, env_out, feedback1);
                }
                else
                {
                    *CH.connect1 += OP_OUT(SLOT, env_out, 0);
                }
            }
            else
            {
                CH.op1_out[1] = CH.op1_out[0];
                CH.op1_out[0] = 0;
            }
            /* SLOT 2 */
            SLOT = &CH.SLOT[SLOT2];
            env_out = OPL_CALC_SLOT(SLOT);
            if (env_out < (uint)(EG_ENT - 1))
            {
                /* PG */
                if (SLOT.vib)
                    SLOT.Cnt += (SLOT.Incr * vib) >> VIB_RATE_SHIFT;
                else
                    SLOT.Cnt += SLOT.Incr;
                /* connection */
                outd[0] += OP_OUT(SLOT, env_out, feedback2);
            }
        }
Example #11
0
        /* ---------- frequency counter for operater update ---------- */
        void CALC_FCSLOT(OPL_CH CH, OPL_SLOT SLOT)
        {
            int ksr;

            /* frequency step counter */
            SLOT.Incr = CH.fc * SLOT.mul;
            ksr = CH.kcode >> SLOT.KSR;

            if (SLOT.ksr != ksr)
            {
                SLOT.ksr = (byte)ksr;
                /* attack , decay rate recalcration */
                SLOT.evsa = SLOT.AR(ksr);
                SLOT.evsd = SLOT.DR(ksr);
                SLOT.evsr = SLOT.RR(ksr);
            }
            SLOT.TLL = (int)(SLOT.TL + (CH.ksl_base >> SLOT.ksl));
        }
Example #12
0
        void OPL_CALC_RH(OPL_CH CH)
        {
            uint env_tam,env_sd,env_top,env_hh;
            // This code used to do int(rnd.getRandomBit() * (WHITE_NOISE_db / EG_STEP)),
            // but EG_STEP = 96.0/EG_ENT, and WHITE_NOISE_db=6.0. So, that's equivalent to
            // int(rnd.getRandomBit() * EG_ENT/16). We know that EG_ENT is 4096, or 1024,
            // or 128, so we can safely avoid any FP ops.
            int whitenoise = rnd.getRandomBit() * (EG_ENT >> 4);

            int tone8;

            OPL_SLOT*SLOT;
            int      env_out;

            /* BD : same as FM serial mode and output level is large */
            feedback2 = 0;
            /* SLOT 1 */
            SLOT    = &CH[6].SLOT[SLOT1];
            env_out = OPL_CALC_SLOT(SLOT);
            if (env_out < EG_ENT - 1)
            {
                /* PG */
                if (SLOT.vib)
                {
                    SLOT.Cnt += (SLOT.Incr * vib) >> VIB_RATE_SHIFT;
                }
                else
                {
                    SLOT.Cnt += SLOT.Incr;
                }
                /* connection */
                if (CH[6].FB)
                {
                    int feedback1 = (CH[6].op1_out[0] + CH[6].op1_out[1]) >> CH[6].FB;
                    CH[6].op1_out[1] = CH[6].op1_out[0];
                    feedback2        = CH[6].op1_out[0] = OP_OUT(SLOT,env_out,feedback1);
                }
                else
                {
                    feedback2 = OP_OUT(SLOT,env_out,0);
                }
            }
            else
            {
                feedback2        = 0;
                CH[6].op1_out[1] = CH[6].op1_out[0];
                CH[6].op1_out[0] = 0;
            }
            /* SLOT 2 */
            SLOT    = &CH[6].SLOT[SLOT2];
            env_out = OPL_CALC_SLOT(SLOT);
            if (env_out < EG_ENT - 1)
            {
                /* PG */
                if (SLOT.vib)
                {
                    SLOT.Cnt += (SLOT.Incr * vib) >> VIB_RATE_SHIFT;
                }
                else
                {
                    SLOT.Cnt += SLOT.Incr;
                }
                /* connection */
                outd[0] += OP_OUT(SLOT,env_out,feedback2) * 2;
            }

            // SD  (17) = mul14[fnum7] + white noise
            // TAM (15) = mul15[fnum8]
            // TOP (18) = fnum6(mul18[fnum8]+whitenoise)
            // HH  (14) = fnum7(mul18[fnum8]+whitenoise) + white noise
            env_sd  = OPL_CALC_SLOT(SLOT7_2) + whitenoise;
            env_tam = OPL_CALC_SLOT(SLOT8_1);
            env_top = OPL_CALC_SLOT(SLOT8_2);
            env_hh  = OPL_CALC_SLOT(SLOT7_1) + whitenoise;

            /* PG */
            if (SLOT7_1.vib)
            {
                SLOT7_1.Cnt += (SLOT7_1.Incr * vib) >> (VIB_RATE_SHIFT - 1);
            }
            else
            {
                SLOT7_1.Cnt += 2 * SLOT7_1.Incr;
            }
            if (SLOT7_2.vib)
            {
                SLOT7_2.Cnt += (CH[7].fc * vib) >> (VIB_RATE_SHIFT - 3);
            }
            else
            {
                SLOT7_2.Cnt += (CH[7].fc * 8);
            }
            if (SLOT8_1.vib)
            {
                SLOT8_1.Cnt += (SLOT8_1.Incr * vib) >> VIB_RATE_SHIFT;
            }
            else
            {
                SLOT8_1.Cnt += SLOT8_1.Incr;
            }
            if (SLOT8_2.vib)
            {
                SLOT8_2.Cnt += ((CH[8].fc * 3) * vib) >> (VIB_RATE_SHIFT - 4);
            }
            else
            {
                SLOT8_2.Cnt += (CH[8].fc * 48);
            }

            tone8 = OP_OUT(SLOT8_2,whitenoise,0);

            /* SD */
            if (env_sd < (uint)(EG_ENT - 1))
            {
                outd[0] += OP_OUT(SLOT7_1,env_sd,0) * 8;
            }
            /* TAM */
            if (env_tam < (uint)(EG_ENT - 1))
            {
                outd[0] += OP_OUT(SLOT8_1,env_tam,0) * 2;
            }
            /* TOP-CY */
            if (env_top < (uint)(EG_ENT - 1))
            {
                outd[0] += OP_OUT(SLOT7_2,env_top,tone8) * 2;
            }
            /* HH */
            if (env_hh < (uint)(EG_ENT - 1))
            {
                outd[0] += OP_OUT(SLOT7_2,env_hh,tone8) * 2;
            }
        }