예제 #1
0
 public override void Release()
 {
     if (State < ADSRState.Releasing)
     {
         if (adsr.R == 0)
         {
             curVelocity = 0;
             Stop();
         }
         else if (curVelocity == 0 && prevVelocity == 0)
         {
             Stop();
         }
         else
         {
             nextState = ADSRState.Releasing;
         }
     }
 }
예제 #2
0
    public void Clock()
    {
        if ((waveform & 0x1) != 0)
        {
            if (state == ADSRState.Release)
            {
                state = ADSRState.Attack;
            }
        }
        else
        {
            state = ADSRState.Release;
        }

        ++adsrCounter;
        adsrCounter &= 0x7fff;
        ushort adsrTarget = 9;

        switch (state)
        {
        case ADSRState.Attack:
            adsrTarget = adsrRateTable[ad >> 4];
            if (adsrCounter == adsrTarget)
            {
                adsrCounter    = 0;
                adsrExpCounter = 0;
                ++volumeLevel;
                if (volumeLevel == 0xff)
                {
                    state = ADSRState.Decay;
                }
            }
            break;

        case ADSRState.Decay:
            adsrTarget = adsrRateTable[ad & 0xf];
            if (adsrCounter == adsrTarget)
            {
                adsrCounter = 0;
                byte adsrExpTarget = volumeLevel < 0x5d ? expTargetTable[volumeLevel] : (byte)1;
                ++adsrExpCounter;
                if (adsrExpCounter >= adsrExpTarget)
                {
                    adsrExpCounter = 0;
                    if (volumeLevel > sustainLevels[sr >> 4])
                    {
                        --volumeLevel;
                    }
                }
            }
            break;

        case ADSRState.Release:
            adsrTarget = adsrRateTable[sr & 0xf];
            if (adsrCounter == adsrTarget)
            {
                adsrCounter = 0;
                if (volumeLevel > 0)
                {
                    byte adsrExpTarget = volumeLevel < 0x5d ? expTargetTable[volumeLevel] : (byte)1;
                    ++adsrExpCounter;
                    if (adsrExpCounter >= adsrExpTarget)
                    {
                        adsrExpCounter = 0;
                        --volumeLevel;
                    }
                }
            }
            break;
        }

        uint lastAccumulator = accumulator;

        accumulator += frequency;
        accumulator &= 0xffffff;

        if ((waveform & 0x8) != 0)
        {
            accumulator = 0;
            //noiseGenerator = 0x7ffff8;
        }

        // Optimization: run noise generator only when necessary
        if ((waveform & 0x80) != 0)
        {
            if ((lastAccumulator & 0x80000) == 0 && (accumulator & 0x80000) != 0)
            {
                uint temp = noiseGenerator;
                uint step = (temp & 0x400000) ^ ((temp & 0x20000) << 5);
                temp <<= 1;
                if (step > 0)
                {
                    temp |= 1;
                }
                noiseGenerator = temp & 0x7fffff;
            }
        }

        doSync = ((lastAccumulator & 0x800000) == 0 && (accumulator & 0x800000) != 0);
    }
예제 #3
0
        protected void StepEnvelope()
        {
            void dec()
            {
                prevVelocity = curVelocity;
                processStep  = 0;
                if (curVelocity - 1 <= sustainVelocity)
                {
                    curVelocity = sustainVelocity;
                    nextState   = ADSRState.Playing;
                }
                else
                {
                    curVelocity = (byte)(curVelocity - 1).Clamp(0, 0xF);
                }
            }

            void sus()
            {
                prevVelocity = curVelocity;
                processStep  = 0;
            }

            void rel()
            {
                if (adsr.R == 0)
                {
                    prevVelocity = 0;
                    curVelocity  = 0;
                    Stop();
                }
                else
                {
                    prevVelocity = curVelocity;
                    processStep  = 0;
                    if (curVelocity - 1 <= 0)
                    {
                        nextState   = ADSRState.Dying;
                        curVelocity = 0;
                    }
                    else
                    {
                        curVelocity--;
                    }
                }
            }

            switch (State)
            {
            case ADSRState.Initializing:
                nextState   = ADSRState.Rising;
                prevPan     = curPan;
                processStep = 0;
                if ((adsr.A | adsr.D) == 0 || (sustainVelocity == 0 && peakVelocity == 0))
                {
                    State        = ADSRState.Playing;
                    prevVelocity = sustainVelocity;
                    curVelocity  = sustainVelocity;
                    return;
                }
                else if (adsr.A == 0 && adsr.S < 0xF)
                {
                    State        = ADSRState.Decaying;
                    prevVelocity = peakVelocity;
                    curVelocity  = (byte)(peakVelocity - 1).Clamp(0, 0xF);
                    if (curVelocity < sustainVelocity)
                    {
                        curVelocity = sustainVelocity;
                    }
                    return;
                }
                else if (adsr.A == 0)
                {
                    State        = ADSRState.Playing;
                    prevVelocity = sustainVelocity;
                    curVelocity  = sustainVelocity;
                    return;
                }
                else
                {
                    State        = ADSRState.Rising;
                    prevVelocity = 0;
                    curVelocity  = 1;
                    return;
                }

            case ADSRState.Rising:
                if (++processStep >= Config.Instance.InterFrames * adsr.A)
                {
                    if (nextState == ADSRState.Decaying)
                    {
                        State = ADSRState.Decaying;
                        dec(); return;
                    }
                    if (nextState == ADSRState.Playing)
                    {
                        State = ADSRState.Playing;
                        sus(); return;
                    }
                    if (nextState == ADSRState.Releasing)
                    {
                        State = ADSRState.Releasing;
                        rel(); return;
                    }
                    prevVelocity = curVelocity;
                    processStep  = 0;
                    if (++curVelocity >= peakVelocity)
                    {
                        if (adsr.D == 0)
                        {
                            nextState = ADSRState.Playing;
                        }
                        else if (peakVelocity == sustainVelocity)
                        {
                            nextState   = ADSRState.Playing;
                            curVelocity = peakVelocity;
                        }
                        else
                        {
                            curVelocity = peakVelocity;
                            nextState   = ADSRState.Decaying;
                        }
                    }
                }
                break;

            case ADSRState.Decaying:
                if (++processStep >= Config.Instance.InterFrames * adsr.D)
                {
                    if (nextState == ADSRState.Playing)
                    {
                        State = ADSRState.Playing;
                        sus(); return;
                    }
                    if (nextState == ADSRState.Releasing)
                    {
                        State = ADSRState.Releasing;
                        rel(); return;
                    }
                    dec();
                }
                break;

            case ADSRState.Playing:
                if (++processStep >= Config.Instance.InterFrames)
                {
                    if (nextState == ADSRState.Releasing)
                    {
                        State = ADSRState.Releasing;
                        rel(); return;
                    }
                    sus();
                }
                break;

            case ADSRState.Releasing:
                if (++processStep >= Config.Instance.InterFrames * adsr.R)
                {
                    if (nextState == ADSRState.Dying)
                    {
                        Stop();
                        return;
                    }
                    rel();
                }
                break;
            }
        }