예제 #1
0
        public static void OPL3_WriteRegBuffered(ref opl3_chip chip, ushort reg, byte v)
        {
            ulong time1, time2;

            if ((chip.writebuf[chip.writebuf_last].reg & 0x200) != 0)
            {
                OPL3_WriteReg(ref chip, (ushort)(chip.writebuf[chip.writebuf_last].reg & 0x1ff), chip.writebuf[chip.writebuf_last].data);

                chip.writebuf_cur       = (uint)((chip.writebuf_last + 1) % OPL_WRITEBUF_SIZE);
                chip.writebuf_samplecnt = chip.writebuf[chip.writebuf_last].time;
            }

            chip.writebuf[chip.writebuf_last].reg  = (ushort)(reg | 0x200);
            chip.writebuf[chip.writebuf_last].data = v;
            time1 = chip.writebuf_lasttime + (ulong)OPL_WRITEBUF_DELAY;
            time2 = chip.writebuf_samplecnt;

            if (time1 < time2)
            {
                time1 = time2;
            }

            chip.writebuf[chip.writebuf_last].time = time1;
            chip.writebuf_lasttime = time1;
            chip.writebuf_last     = (chip.writebuf_last + 1) % (uint)OPL_WRITEBUF_SIZE;
        }
예제 #2
0
        public static void OPL3_Reset(ref opl3_chip chip, int samplerate)
        {
            byte slotnum;
            byte channum;

            chip = new opl3_chip();
            for (slotnum = 0; slotnum < 36; slotnum++)
            {
                chip.slot[slotnum]      = new opl3_slot();
                chip.slot[slotnum].chip = chip;
                unsafe
                {
                    fixed(short *p = &chip.zeromod)
                    {
                        chip.slot[slotnum].mod = p;
                    }
                }
                chip.slot[slotnum].eg_rout = 0x1ff;
                chip.slot[slotnum].eg_out  = 0x1ff;
                chip.slot[slotnum].eg_gen  = envelope_gen_num.release;
                //chip.slot[slotnum].trem = (byte)chip.zeromod;
                chip.slot[slotnum].tremZero = true;
                chip.slot[slotnum].slot_num = slotnum;
            }
            for (channum = 0; channum < 18; channum++)
            {
                chip.channel[channum]                   = new opl3_channel();
                chip.channel[channum].slots[0]          = chip.slot[ch_slot[channum]];
                chip.channel[channum].slots[1]          = chip.slot[ch_slot[channum] + 3];
                chip.slot[ch_slot[channum]].channel     = chip.channel[channum];
                chip.slot[ch_slot[channum] + 3].channel = chip.channel[channum];
                if ((channum % 9) < 3)
                {
                    chip.channel[channum].pair = chip.channel[channum + 3];
                }
                else if ((channum % 9) < 6)
                {
                    chip.channel[channum].pair = chip.channel[channum - 3];
                }
                chip.channel[channum].chip    = chip;
                chip.channel[channum]._out[0] = chip.zeromod;
                chip.channel[channum]._out[1] = chip.zeromod;
                chip.channel[channum]._out[2] = chip.zeromod;
                chip.channel[channum]._out[3] = chip.zeromod;
                chip.channel[channum].chtype  = ChannelType.ch_2op;
                chip.channel[channum].cha     = 0xffff;
                chip.channel[channum].chb     = 0xffff;
                chip.channel[channum].ch_num  = channum;
                OPL3_ChannelSetupAlg(ref chip.channel[channum]);
            }
            chip.noise        = 1;
            chip.rateratio    = (int)((samplerate << RSM_FRAC) / 49716);
            chip.tremoloshift = 4;
            chip.vibshift     = 1;
        }
예제 #3
0
        public static void OPL3_GenerateStream(ref opl3_chip chip, short[] sndptr, uint numsamples, int pos)
        {
            int x = 0;

            for (int i = 0; i < numsamples / 2; i++)
            {
                OPL3_GenerateResampled(ref chip, sndptr, x);
                x += 2;
                //sndptr += 2;
            }
        }
예제 #4
0
 public static void OPL3_GenerateResampled(ref opl3_chip chip, short[] buf, int pos)
 {
     while (chip.samplecnt >= chip.rateratio)
     {
         chip.oldsamples[0] = chip.samples[0];
         chip.oldsamples[1] = chip.samples[1];
         Nuked.OPL3_Generate(ref chip, chip.samples);
         chip.samplecnt -= chip.rateratio;
     }
     buf[pos]        = (short)((chip.oldsamples[0] * (chip.rateratio - chip.samplecnt) + chip.samples[0] * chip.samplecnt) / chip.rateratio);
     buf[pos + 1]    = (short)((chip.oldsamples[1] * (chip.rateratio - chip.samplecnt) + chip.samples[1] * chip.samplecnt) / chip.rateratio);
     chip.samplecnt += 1 << RSM_FRAC;
 }
예제 #5
0
        public static void OPL3_ChannelSet4Op(ref opl3_chip chip, byte data)
        {
            byte bit;
            byte chnum;

            for (bit = 0; bit < 6; bit++)
            {
                chnum = bit;
                if (bit >= 3)
                {
                    chnum += 9 - 3;
                }
                if (((data >> bit) & 0x01) != 0)
                {
                    chip.channel[chnum].chtype     = ChannelType.ch_4op;
                    chip.channel[chnum + 3].chtype = ChannelType.ch_4op2;
                }
                else
                {
                    chip.channel[chnum].chtype     = ChannelType.ch_2op;
                    chip.channel[chnum + 3].chtype = ChannelType.ch_2op;
                }
            }
        }
예제 #6
0
        public static void OPL3_Generate(ref opl3_chip chip, short[] buf)
        {
            byte  ii;
            byte  jj;
            short accm;
            byte  shift = 0;

            buf[1] = OPL3_ClipSample(chip.mixbuff[1]);

            for (ii = 0; ii < 15; ii++)
            {
                OPL3_SlotCalcFB(ref chip.slot[ii]);
                OPL3_EnvelopeCalc(ref chip.slot[ii]);
                OPL3_PhaseGenerate(ref chip.slot[ii]);
                OPL3_SlotGenerate(ref chip.slot[ii]);
            }

            chip.mixbuff[0] = 0;
            for (ii = 0; ii < 18; ii++)
            {
                accm = 0;
                for (jj = 0; jj < 4; jj++)
                {
                    accm += chip.channel[ii]._out[jj];
                }
                chip.mixbuff[0] += (short)(accm & chip.channel[ii].cha);
            }

            for (ii = 15; ii < 18; ii++)
            {
                OPL3_SlotCalcFB(ref chip.slot[ii]);
                OPL3_EnvelopeCalc(ref chip.slot[ii]);
                OPL3_PhaseGenerate(ref chip.slot[ii]);
                OPL3_SlotGenerate(ref chip.slot[ii]);
            }

            buf[0] = OPL3_ClipSample(chip.mixbuff[0]);

            for (ii = 18; ii < 33; ii++)
            {
                OPL3_SlotCalcFB(ref chip.slot[ii]);
                OPL3_EnvelopeCalc(ref chip.slot[ii]);
                OPL3_PhaseGenerate(ref chip.slot[ii]);
                OPL3_SlotGenerate(ref chip.slot[ii]);
            }

            chip.mixbuff[1] = 0;
            for (ii = 0; ii < 18; ii++)
            {
                accm = 0;
                for (jj = 0; jj < 4; jj++)
                {
                    accm += chip.channel[ii]._out[jj];
                }
                chip.mixbuff[1] += (short)(accm & chip.channel[ii].chb);
            }

            for (ii = 33; ii < 36; ii++)
            {
                OPL3_SlotCalcFB(ref chip.slot[ii]);
                OPL3_EnvelopeCalc(ref chip.slot[ii]);
                OPL3_PhaseGenerate(ref chip.slot[ii]);
                OPL3_SlotGenerate(ref chip.slot[ii]);
            }

            if ((chip.timer & 0x3f) == 0x3f)
            {
                chip.tremolopos = (byte)((chip.tremolopos + 1) % 210);
            }
            if (chip.tremolopos < 105)
            {
                chip.tremolo = (byte)(chip.tremolopos >> chip.tremoloshift);
            }
            else
            {
                chip.tremolo = (byte)((210 - chip.tremolopos) >> chip.tremoloshift);
            }

            if ((chip.timer & 0x3ff) == 0x3ff)
            {
                chip.vibpos = (byte)((chip.vibpos + 1) & 7);
            }

            chip.timer++;

            chip.eg_add = 0;
            if (chip.eg_timer != 0)
            {
                while (shift < 36 && ((chip.eg_timer >> shift) & 1) == 0)
                {
                    shift++;
                }
                if (shift > 12)
                {
                    chip.eg_add = 0;
                }
                else
                {
                    chip.eg_add = (byte)(shift + 1);
                }
            }

            if (chip.eg_timerrem != 0 || chip.eg_state != 0)
            {
                if (chip.eg_timer == 0xfffffffff)
                {
                    chip.eg_timer    = 0;
                    chip.eg_timerrem = 1;
                }
                else
                {
                    chip.eg_timer++;
                    chip.eg_timerrem = 0;
                }
            }

            chip.eg_state ^= 1;

            while (chip.writebuf[chip.writebuf_cur].time <= chip.writebuf_samplecnt)
            {
                if ((chip.writebuf[chip.writebuf_cur].reg & 0x200) == 0)
                {
                    break;
                }
                chip.writebuf[chip.writebuf_cur].reg &= 0x1ff;
                OPL3_WriteReg(ref chip, chip.writebuf[chip.writebuf_cur].reg, chip.writebuf[chip.writebuf_cur].data);
                chip.writebuf_cur = (uint)((chip.writebuf_cur + 1) % OPL_WRITEBUF_SIZE);
            }
            chip.writebuf_samplecnt++;
        }
예제 #7
0
        //
        // Channel
        //


        public static void OPL3_ChannelUpdateRhythm(ref opl3_chip chip, byte data)
        {
            opl3_channel channel6;
            opl3_channel channel7;
            opl3_channel channel8;
            byte         chnum;

            chip.rhy = (byte)(data & 0x3f);
            if ((chip.rhy & 0x20) != 0)
            {
                channel6         = chip.channel[6];
                channel7         = chip.channel[7];
                channel8         = chip.channel[8];
                channel6._out[0] = channel6.slots[1]._out;
                channel6._out[1] = channel6.slots[1]._out;
                channel6._out[2] = chip.zeromod;
                channel6._out[3] = chip.zeromod;
                channel7._out[0] = channel7.slots[0]._out;
                channel7._out[1] = channel7.slots[0]._out;
                channel7._out[2] = channel7.slots[1]._out;
                channel7._out[3] = channel7.slots[1]._out;
                channel8._out[0] = channel8.slots[0]._out;
                channel8._out[1] = channel8.slots[0]._out;
                channel8._out[2] = channel8.slots[1]._out;
                channel8._out[3] = channel8.slots[1]._out;
                for (chnum = 6; chnum < 9; chnum++)
                {
                    chip.channel[chnum].chtype = ChannelType.ch_drum;
                }
                OPL3_ChannelSetupAlg(ref channel6);
                OPL3_ChannelSetupAlg(ref channel7);
                OPL3_ChannelSetupAlg(ref channel8);
                //hh
                if ((chip.rhy & 0x01) != 0)
                {
                    OPL3_EnvelopeKeyOn(ref channel7.slots[0], EnvelopeKeyType.drum);
                }
                else
                {
                    OPL3_EnvelopeKeyOff(ref channel7.slots[0], EnvelopeKeyType.drum);
                }
                //tc
                if ((chip.rhy & 0x02) != 0)
                {
                    OPL3_EnvelopeKeyOn(ref channel8.slots[1], EnvelopeKeyType.drum);
                }
                else
                {
                    OPL3_EnvelopeKeyOff(ref channel8.slots[1], EnvelopeKeyType.drum);
                }
                //tom
                if ((chip.rhy & 0x04) != 0)
                {
                    OPL3_EnvelopeKeyOn(ref channel8.slots[0], EnvelopeKeyType.drum);
                }
                else
                {
                    OPL3_EnvelopeKeyOff(ref channel8.slots[0], EnvelopeKeyType.drum);
                }
                //sd
                if ((chip.rhy & 0x08) != 0)
                {
                    OPL3_EnvelopeKeyOn(ref channel7.slots[1], EnvelopeKeyType.drum);
                }
                else
                {
                    OPL3_EnvelopeKeyOff(ref channel7.slots[1], EnvelopeKeyType.drum);
                }
                //bd
                if ((chip.rhy & 0x10) != 0)
                {
                    OPL3_EnvelopeKeyOn(ref channel6.slots[0], EnvelopeKeyType.drum);
                    OPL3_EnvelopeKeyOn(ref channel6.slots[1], EnvelopeKeyType.drum);
                }
                else
                {
                    OPL3_EnvelopeKeyOff(ref channel6.slots[0], EnvelopeKeyType.drum);
                    OPL3_EnvelopeKeyOff(ref channel6.slots[1], EnvelopeKeyType.drum);
                }
            }
            else
            {
                for (chnum = 6; chnum < 9; chnum++)
                {
                    chip.channel[chnum].chtype = ChannelType.ch_2op;
                    OPL3_ChannelSetupAlg(ref chip.channel[chnum]);
                    OPL3_EnvelopeKeyOff(ref chip.channel[chnum].slots[0], EnvelopeKeyType.drum);
                    OPL3_EnvelopeKeyOff(ref chip.channel[chnum].slots[1], EnvelopeKeyType.drum);
                }
            }
        }
예제 #8
0
        public static void OPL3_WriteReg(ref opl3_chip chip, ushort reg, byte v)
        {
            byte high = (byte)((reg >> 8) & 0x01);
            byte regm = (byte)(reg & 0xff);

            switch (regm & 0xf0)
            {
            case 0x00:
                if (high != 0)
                {
                    switch (regm & 0x0f)
                    {
                    case 0x04:
                        OPL3_ChannelSet4Op(ref chip, v);
                        break;

                    case 0x05:
                        chip.newm = (byte)(v & 0x01);
                        break;
                    }
                }
                else
                {
                    switch (regm & 0x0f)
                    {
                    case 0x08:
                        chip.nts = (byte)((v >> 6) & 0x01);
                        break;
                    }
                }
                break;

            case 0x20:
            case 0x30:
                if (ad_slot[regm & 0x1f] >= 0)
                {
                    OPL3_SlotWrite20(ref chip.slot[18 * high + ad_slot[regm & 0x1f]], v);
                }
                break;

            case 0x40:
            case 0x50:
                if (ad_slot[regm & 0x1f] >= 0)
                {
                    OPL3_SlotWrite40(ref chip.slot[18 * high + ad_slot[regm & 0x1f]], v);
                }
                break;

            case 0x60:
            case 0x70:
                if (ad_slot[regm & 0x1f] >= 0)
                {
                    OPL3_SlotWrite60(ref chip.slot[18 * high + ad_slot[regm & 0x1f]], v);
                }
                break;

            case 0x80:
            case 0x90:
                if (ad_slot[regm & 0x1f] >= 0)
                {
                    OPL3_SlotWrite80(ref chip.slot[18 * high + ad_slot[regm & 0x1f]], v);
                }
                break;

            case 0xe0:
            case 0xf0:
                if (ad_slot[regm & 0x1f] >= 0)
                {
                    OPL3_SlotWriteE0(ref chip.slot[18 * high + ad_slot[regm & 0x1f]], v);
                }
                break;

            case 0xa0:
                if ((regm & 0x0f) < 9)
                {
                    OPL3_ChannelWriteA0(ref chip.channel[(int)(9 * high + (regm & 0x0f))], v);
                }
                break;

            case 0xb0:
                if (regm == 0xbd && high == 0)
                {
                    chip.tremoloshift = (byte)((((v >> 7) ^ 1) << 1) + 2);
                    chip.vibshift     = (byte)(((v >> 6) & 0x01) ^ 1);
                    OPL3_ChannelUpdateRhythm(ref chip, v);
                }
                else if ((regm & 0x0f) < 9)
                {
                    OPL3_ChannelWriteB0(ref chip.channel[9 * high + (regm & 0x0f)], v);
                    if ((v & 0x20) != 0)
                    {
                        OPL3_ChannelKeyOn(ref chip.channel[9 * high + (regm & 0x0f)]);
                    }
                    else
                    {
                        OPL3_ChannelKeyOff(ref chip.channel[9 * high + (regm & 0x0f)]);
                    }
                }
                break;

            case 0xc0:
                if ((regm & 0x0f) < 9)
                {
                    OPL3_ChannelWriteC0(ref chip.channel[9 * high + (regm & 0x0f)], v);
                }
                break;
            }
        }