Beispiel #1
0
        private Int32 EG_Update(_SLOT slot)
        {
            switch (slot.EG.state)
            {
            case _STATE.ATTACK:
                slot.EG.volume += slot.EG.AR;
                if (slot.EG.volume >= (0x3ff << EG_SHIFT))
                {
                    slot.EG.state = _STATE.DECAY1;
                    if (slot.EG.D1R >= (0x400 << EG_SHIFT))     //Skip DECAY1, go directly to DECAY2
                    {
                        slot.EG.state = _STATE.DECAY2;
                    }
                    slot.EG.volume = 0x3ff << EG_SHIFT;
                }
                break;

            case _STATE.DECAY1:
                slot.EG.volume -= slot.EG.D1R;
                if (slot.EG.volume <= 0)
                {
                    slot.EG.volume = 0;
                }
                if (slot.EG.volume >> EG_SHIFT <= (slot.EG.DL << (10 - 4)))
                {
                    slot.EG.state = _STATE.DECAY2;
                }
                break;

            case _STATE.DECAY2:
                slot.EG.volume -= slot.EG.D2R;
                if (slot.EG.volume <= 0)
                {
                    slot.EG.volume = 0;
                }
                break;

            case _STATE.RELEASE:
                slot.EG.volume -= slot.EG.RR;
                if (slot.EG.volume <= 0)
                {
                    slot.EG.volume = 0;
                    slot.Playing   = 0;
                }
                break;

            default:
                return(1 << SHIFT);
            }
            return(lin2expvol[slot.EG.volume >> EG_SHIFT]);
        }
Beispiel #2
0
        private void EG_Calc(_MultiPCM ptChip, _SLOT slot)
        {
            Int32 octave = ((slot.Regs[3] >> 4) - 1) & 0xf;
            Int32 rate;

            if ((octave & 8) != 0)
            {
                octave = octave - 16;
            }
            if (slot.Sample.KRS != 0xf)
            {
                rate = (octave + slot.Sample.KRS) * 2 + ((slot.Regs[3] >> 3) & 1);
            }
            else
            {
                rate = 0;
            }

            slot.EG.AR  = (Int32)Get_RATE(ptChip.ARStep, (UInt32)rate, slot.Sample.AR);
            slot.EG.D1R = (Int32)Get_RATE(ptChip.DRStep, (UInt32)rate, slot.Sample.DR1);
            slot.EG.D2R = (Int32)Get_RATE(ptChip.DRStep, (UInt32)rate, slot.Sample.DR2);
            slot.EG.RR  = (Int32)Get_RATE(ptChip.DRStep, (UInt32)rate, slot.Sample.RR);
            slot.EG.DL  = 0xf - slot.Sample.DL;
        }
Beispiel #3
0
        //static STREAM_UPDATE( MultiPCM_update )
        public void MultiPCM_update(byte ChipID, Int32[][] outputs, Int32 samples)
        {
            //MultiPCM *ptChip = (MultiPCM *)param;
            _MultiPCM ptChip = MultiPCMData[ChipID];

            Int32[][] datap = new Int32[2][];
            Int32     i, sl;

            datap[0] = outputs[0];
            datap[1] = outputs[1];

            for (int j = 0; j < samples; j++)
            {
                datap[0][j] = 0;
                datap[1][j] = 0;
            }
            //memset(datap[0], 0, sizeof(*datap[0]) * samples);
            //memset(datap[1], 0, sizeof(*datap[1]) * samples);


            for (i = 0; i < samples; ++i)
            {
                Int32 smpl = 0;
                Int32 smpr = 0;
                for (sl = 0; sl < 28; ++sl)
                {
                    _SLOT slot = ptChip.Slots[sl];
                    if (slot.Playing != 0 && slot.Muted == 0)
                    {
                        UInt32 vol = (slot.TL >> SHIFT) | (slot.Pan << 7);
                        UInt32 adr = slot.offset >> SHIFT;
                        Int32  sample;
                        UInt32 step    = slot.step;
                        Int32  csample = (Int16)(ptChip.ROM[(slot.Base + adr) & ptChip.ROMMask] << 8);
                        Int32  fpart   = (Int32)(slot.offset & ((1 << SHIFT) - 1));
                        sample = (csample * fpart + slot.Prev * ((1 << SHIFT) - fpart)) >> SHIFT;

                        if ((slot.Regs[6] & 7) != 0)    //Vibrato enabled
                        {
                            step   = (UInt32)(step * PLFO_Step(slot.PLFO));
                            step >>= SHIFT;
                        }

                        slot.offset += step;
                        if (slot.offset >= (slot.Sample.End << SHIFT))
                        {
                            slot.offset = slot.Sample.Loop << SHIFT;
                        }
                        if ((adr ^ (slot.offset >> SHIFT)) != 0)
                        {
                            slot.Prev = csample;
                        }

                        if ((slot.TL >> SHIFT) != slot.DstTL)
                        {
                            slot.TL += (UInt32)slot.TLStep;
                        }

                        if ((slot.Regs[7] & 7) != 0)    //Tremolo enabled
                        {
                            sample   = sample * ALFO_Step(slot.ALFO);
                            sample >>= SHIFT;
                        }

                        sample = (sample * EG_Update(slot)) >> 10;

                        smpl += (LPANTABLE[vol] * sample) >> SHIFT;
                        smpr += (RPANTABLE[vol] * sample) >> SHIFT;
                    }
                }

                /*#define ICLIP16(x) (x<-32768)?-32768:((x>32767)?32767:x)
                 *      datap[0][i]=ICLIP16(smpl);
                 *      datap[1][i]=ICLIP16(smpr);*/
                datap[0][i] = smpl;
                datap[1][i] = smpr;
            }
        }
Beispiel #4
0
        private void WriteSlot(_MultiPCM ptChip, _SLOT slot, Int32 reg, byte data)
        {
            slot.Regs[reg] = data;

            switch (reg)
            {
            case 0:     //PANPOT
                slot.Pan = (UInt32)((data >> 4) & 0xf);
                break;

            case 1:     //Sample
                        //according to YMF278 sample write causes some base params written to the regs (envelope+lfos)
                        //the game should never change the sample while playing.
            {
                _Sample Sample = ptChip.Samples[slot.Regs[1]];
                WriteSlot(ptChip, slot, 6, Sample.LFOVIB);
                WriteSlot(ptChip, slot, 7, Sample.AM);
            }
            break;

            case 2:     //Pitch
            case 3:
            {
                UInt32 oct   = (UInt32)(((slot.Regs[3] >> 4) - 1) & 0xf);
                UInt32 pitch = (UInt32)(((slot.Regs[3] & 0xf) << 6) | (slot.Regs[2] >> 2));
                pitch = ptChip.FNS_Table[pitch];
                if ((oct & 0x8) != 0)
                {
                    pitch >>= (Int32)(16 - oct);
                }
                else
                {
                    pitch <<= (Int32)oct;
                }
                slot.step = (UInt32)(pitch / ptChip.Rate);
            }
            break;

            case 4:                     //KeyOn/Off (and more?)
            {
                if ((data & 0x80) != 0) //KeyOn
                {
                    slot.Sample  = ptChip.Samples[slot.Regs[1]];
                    slot.Playing = 1;
                    slot.Base    = slot.Sample.Start;
                    slot.offset  = 0;
                    slot.Prev    = 0;
                    slot.TL      = slot.DstTL << SHIFT;

                    EG_Calc(ptChip, slot);
                    slot.EG.state  = _STATE.ATTACK;
                    slot.EG.volume = 0;

                    if (slot.Base >= 0x100000)
                    {
                        if ((slot.Pan & 8) != 0)
                        {
                            slot.Base = (slot.Base & 0xfffff) | (ptChip.BankL);
                        }
                        else
                        {
                            slot.Base = (slot.Base & 0xfffff) | (ptChip.BankR);
                        }
                    }
                }
                else
                {
                    if (slot.Playing != 0)
                    {
                        if (slot.Sample.RR != 0xf)
                        {
                            slot.EG.state = _STATE.RELEASE;
                        }
                        else
                        {
                            slot.Playing = 0;
                        }
                    }
                }
            }
            break;

            case 5:     //TL+Interpolation
            {
                slot.DstTL = (UInt32)((data >> 1) & 0x7f);
                if ((data & 1) == 0)            //Interpolate TL
                {
                    if ((slot.TL >> SHIFT) > slot.DstTL)
                    {
                        slot.TLStep = TLSteps[0];               //decrease
                    }
                    else
                    {
                        slot.TLStep = TLSteps[1];               //increase
                    }
                }
                else
                {
                    slot.TL = slot.DstTL << SHIFT;
                }
            }
            break;

            case 6:     //LFO freq+PLFO
            {
                if (data != 0)
                {
                    LFO_ComputeStep(ptChip, slot.PLFO, (UInt32)(slot.Regs[6] >> 3) & 7, (UInt32)(slot.Regs[6] & 7), 0);
                    LFO_ComputeStep(ptChip, slot.ALFO, (UInt32)(slot.Regs[6] >> 3) & 7, (UInt32)(slot.Regs[7] & 7), 1);
                }
            }
            break;

            case 7:     //ALFO
            {
                if (data != 0)
                {
                    LFO_ComputeStep(ptChip, slot.PLFO, (UInt32)(slot.Regs[6] >> 3) & 7, (UInt32)(slot.Regs[6] & 7), 0);
                    LFO_ComputeStep(ptChip, slot.ALFO, (UInt32)(slot.Regs[6] >> 3) & 7, (UInt32)(slot.Regs[7] & 7), 1);
                }
            }
            break;
            }
        }