예제 #1
0
 /* ----- key on  ----- */
 void OPL_KEYON(OPL_SLOT SLOT)
 {
     /* sin wave restart */
     SLOT.Cnt = 0;
     /* set attack */
     SLOT.evm = ENV_MOD_AR;
     SLOT.evs = SLOT.evsa;
     SLOT.evc = EG_AST;
     SLOT.eve = EG_AED;
 }
예제 #2
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);
        }
예제 #3
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));
            }
        }
예제 #4
0
        /* ----- key off ----- */
        void OPL_KEYOFF(OPL_SLOT SLOT)
        {
            if (SLOT.evm > ENV_MOD_RR)
            {
                /* set envelope counter from envleope output */

                // WORKAROUND: The Kyra engine does something very strange when
                // starting a new song. For each channel:
                //
                // * The release rate is set to "fastest".
                // * Any note is keyed off.
                // * A very low-frequency note is keyed on.
                //
                // Usually, what happens next is that the real notes is keyed
                // on immediately, in which case there's no problem.
                //
                // However, if the note is again keyed off (because the channel
                // begins on a rest rather than a note), the envelope counter
                // was moved from the very lowest point on the attack curve to
                // the very highest point on the release curve.
                //
                // Again, this might not be a problem, if the release rate is
                // still set to "fastest". But in many cases, it had already
                // been increased. And, possibly because of inaccuracies in the
                // envelope generator, that would cause the note to "fade out"
                // for quite a long time.
                //
                // What we really need is a way to find the correct starting
                // point for the envelope counter, and that may be what the
                // commented-out line below is meant to do. For now, simply
                // handle the pathological case.

                if (SLOT.evm == ENV_MOD_AR && SLOT.evc == EG_AST)
                {
                    SLOT.evc = EG_DED;
                }
                else if ((SLOT.evc & EG_DST) == 0)
                {
                    //SLOT.evc = (ENV_CURVE[SLOT.evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
                    SLOT.evc = EG_DST;
                }
                SLOT.eve = EG_DED;
                SLOT.evs = SLOT.evsr;
                SLOT.evm = ENV_MOD_RR;
            }
        }
예제 #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));
        }
예제 #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;
            }
        }
예제 #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;
            }
        }
예제 #8
0
        /* return : envelope output */
        uint OPL_CALC_SLOT(OPL_SLOT SLOT)
        {
            /* calcrate envelope generator */
            if ((SLOT.evc += SLOT.evs) >= SLOT.eve)
            {
                switch (SLOT.evm)
                {
                case ENV_MOD_AR:     /* ATTACK . DECAY1 */
                    /* next DR */
                    SLOT.evm = ENV_MOD_DR;
                    SLOT.evc = EG_DST;
                    SLOT.eve = SLOT.SL;
                    SLOT.evs = SLOT.evsd;
                    break;

                case ENV_MOD_DR:     /* DECAY . SL or RR */
                    SLOT.evc = SLOT.SL;
                    SLOT.eve = EG_DED;
                    if (SLOT.eg_typ)
                    {
                        SLOT.evs = 0;
                    }
                    else
                    {
                        SLOT.evm = ENV_MOD_RR;
                        SLOT.evs = SLOT.evsr;
                    }
                    break;

                case ENV_MOD_RR:     /* RR . OFF */
                    SLOT.evc = EG_OFF;
                    SLOT.eve = EG_OFF + 1;
                    SLOT.evs = 0;
                    break;
                }
            }
            /* calcrate envelope */
            return(SLOT.TLL + ENV_CURVE[SLOT.evc >> ENV_BITS] + (SLOT.ams ? ams : 0));
        }
예제 #9
0
파일: FmOPL.cs 프로젝트: scemino/nscumm
        /* ----- key off ----- */
        void OPL_KEYOFF(OPL_SLOT SLOT)
        {
            if (SLOT.evm > ENV_MOD_RR)
            {
                /* set envelope counter from envleope output */

                // WORKAROUND: The Kyra engine does something very strange when
                // starting a new song. For each channel:
                //
                // * The release rate is set to "fastest".
                // * Any note is keyed off.
                // * A very low-frequency note is keyed on.
                //
                // Usually, what happens next is that the real notes is keyed
                // on immediately, in which case there's no problem.
                //
                // However, if the note is again keyed off (because the channel
                // begins on a rest rather than a note), the envelope counter
                // was moved from the very lowest point on the attack curve to
                // the very highest point on the release curve.
                //
                // Again, this might not be a problem, if the release rate is
                // still set to "fastest". But in many cases, it had already
                // been increased. And, possibly because of inaccuracies in the
                // envelope generator, that would cause the note to "fade out"
                // for quite a long time.
                //
                // What we really need is a way to find the correct starting
                // point for the envelope counter, and that may be what the
                // commented-out line below is meant to do. For now, simply
                // handle the pathological case.

                if (SLOT.evm == ENV_MOD_AR && SLOT.evc == EG_AST)
                    SLOT.evc = EG_DED;
                else if ((SLOT.evc & EG_DST) == 0)
                        //SLOT.evc = (ENV_CURVE[SLOT.evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
                        SLOT.evc = EG_DST;
                SLOT.eve = EG_DED;
                SLOT.evs = SLOT.evsr;
                SLOT.evm = ENV_MOD_RR;
            }
        }
예제 #10
0
파일: FmOPL.cs 프로젝트: scemino/nscumm
 /* ----- key on  ----- */
 void OPL_KEYON(OPL_SLOT SLOT)
 {
     /* sin wave restart */
     SLOT.Cnt = 0;
     /* set attack */
     SLOT.evm = ENV_MOD_AR;
     SLOT.evs = SLOT.evsa;
     SLOT.evc = EG_AST;
     SLOT.eve = EG_AED;
 }
예제 #11
0
파일: FmOPL.cs 프로젝트: scemino/nscumm
 /* return : envelope output */
 uint OPL_CALC_SLOT(OPL_SLOT SLOT)
 {
     /* calcrate envelope generator */
     if ((SLOT.evc += SLOT.evs) >= SLOT.eve)
     {
         switch (SLOT.evm)
         {
             case ENV_MOD_AR: /* ATTACK . DECAY1 */
                     /* next DR */
                 SLOT.evm = ENV_MOD_DR;
                 SLOT.evc = EG_DST;
                 SLOT.eve = SLOT.SL;
                 SLOT.evs = SLOT.evsd;
                 break;
             case ENV_MOD_DR: /* DECAY . SL or RR */
                 SLOT.evc = SLOT.SL;
                 SLOT.eve = EG_DED;
                 if (SLOT.eg_typ)
                 {
                     SLOT.evs = 0;
                 }
                 else
                 {
                     SLOT.evm = ENV_MOD_RR;
                     SLOT.evs = SLOT.evsr;
                 }
                 break;
             case ENV_MOD_RR: /* RR . OFF */
                 SLOT.evc = EG_OFF;
                 SLOT.eve = EG_OFF + 1;
                 SLOT.evs = 0;
                 break;
         }
     }
     /* calcrate envelope */
     return SLOT.TLL + ENV_CURVE[SLOT.evc >> ENV_BITS] + (SLOT.ams ? ams : 0);
 }
예제 #12
0
파일: FmOPL.cs 프로젝트: scemino/nscumm
        /* ---------- 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));
        }