Beispiel #1
0
        /**
         * PCM_Reset(): Reset the PCM chip.
         */
        private void PCM_Reset(byte ChipID)
        {
            pcm_chip_ chip = PCM_Chip[ChipID];
            int       i;
            pcm_chan_ chan;

            // Clear the PCM memory.
            for (ulong j = 0; j < chip.RAMSize; j++)
            {
                chip.RAM[j] = 0x00;
            }

            chip.Enable   = 0;
            chip.Cur_Chan = 0;
            chip.Bank     = 0;

            /* clear channel registers */
            for (i = 0; i < 8; i++)
            {
                chan           = chip.Channel[i];
                chan.Enable    = 0;
                chan.ENV       = 0;
                chan.PAN       = 0;
                chan.St_Addr   = 0;
                chan.Addr      = 0;
                chan.Loop_Addr = 0;
                chan.Step      = 0;
                chan.Step_B    = 0;
                chan.Data      = 0;
            }
        }
Beispiel #2
0
        public void rf5c164_set_mute_Ch(byte ChipID, int ch, int mute)
        {
            pcm_chip_ chip = PCM_Chip[ChipID];

            chip.Channel[ch].Muted = (uint)(mute & 0x1);
            return;
        }
Beispiel #3
0
        public override void Stop(byte ChipID)
        {
            pcm_chip_ chip = PCM_Chip[ChipID];

            //free(chip->RAM);
            //chip->RAM = NULL;

            return;
        }
Beispiel #4
0
        public override void Update(byte ChipID, int[][] outputs, int samples)
        {
            pcm_chip_ chip = PCM_Chip[ChipID];

            PCM_Update(ChipID, outputs, samples);

            visVolume[ChipID][0][0] = outputs[0][0];
            visVolume[ChipID][0][1] = outputs[1][0];
        }
Beispiel #5
0
        public void rf5c164_set_mute_mask(byte ChipID, uint MuteMask)
        {
            pcm_chip_ chip = PCM_Chip[ChipID];
            byte      CurChn;

            for (CurChn = 0; CurChn < 8; CurChn++)
            {
                chip.Channel[CurChn].Muted = (MuteMask >> CurChn) & 0x01;
            }

            return;
        }
Beispiel #6
0
        };                                                                                     //MAX_CHIPS

        /**
         * PCM_Init(): Initialize the PCM chip.
         * @param Rate Sample rate.
         * @return 0 if successful.
         */
        private int PCM_Init(byte ChipID, uint Rate)
        {
            pcm_chip_ chip = PCM_Chip[ChipID];
            int       i;

            chip.Smpl0Patch = 0;
            for (i = 0; i < 8; i++)
            {
                chip.Channel[i].Muted = 0x00;
            }

            chip.RAMSize = 64 * 1024;
            chip.RAM     = new byte[chip.RAMSize];
            PCM_Reset(ChipID);
            PCM_Set_Rate(ChipID, Rate);

            return(0);
        }
Beispiel #7
0
        /**
         * PCM_Set_Rate(): Change the PCM sample rate.
         * @param Rate New sample rate.
         */
        private void PCM_Set_Rate(byte ChipID, uint Rate)
        {
            pcm_chip_ chip = PCM_Chip[ChipID];
            int       i;

            if (Rate == 0)
            {
                return;
            }

            //chip->Rate = (float) (32 * 1024) / (float) Rate;
            chip.Rate = (float)(31.8 * 1024) / (float)Rate;

            for (i = 0; i < 8; i++)
            {
                chip.Channel[i].Step =
                    (uint)((float)chip.Channel[i].Step_B * chip.Rate);
            }
        }
Beispiel #8
0
        public void rf5c164_write_ram2(byte ChipID, uint RAMStartAdr, uint RAMDataLength, byte[] SrcData, uint SrcStartAdr)
        {
            pcm_chip_ chip = PCM_Chip[ChipID];

            RAMStartAdr |= (uint)chip.Bank;
            if (RAMStartAdr >= chip.RAMSize)
            {
                return;
            }
            if (RAMStartAdr + RAMDataLength > chip.RAMSize)
            {
                RAMDataLength = (uint)(chip.RAMSize - RAMStartAdr);
            }

            for (int i = 0; i < RAMDataLength; i++)
            {
                chip.RAM[RAMStartAdr + i] = SrcData[SrcStartAdr + i];
            }

            return;
        }
Beispiel #9
0
        public void rf5c164_write_ram(byte ChipID, uint DataStart, uint DataLength, byte[] RAMData)
        {
            pcm_chip_ chip = PCM_Chip[ChipID];

            DataStart |= (uint)chip.Bank;
            if (DataStart >= chip.RAMSize)
            {
                return;
            }
            if (DataStart + DataLength > chip.RAMSize)
            {
                DataLength = (uint)(chip.RAMSize - DataStart);
            }

            for (int i = 0; i < DataLength; i++)
            {
                chip.RAM[DataStart + i] = RAMData[i];
            }

            return;
        }
Beispiel #10
0
        public void rf5c164_mem_w(byte ChipID, uint offset, byte data)
        {
            pcm_chip_ chip = PCM_Chip[ChipID];

            chip.RAM[(uint)chip.Bank | offset] = data;
        }
Beispiel #11
0
        /**
         * PCM_Update(): Update the PCM buffer.
         * @param buf PCM buffer.
         * @param Length Buffer length.
         */
        private int PCM_Update(byte ChipID, int[][] buf, int Length)
        {
            pcm_chip_ chip = PCM_Chip[ChipID];
            int       i, j;

            int[]     bufL, bufR;  //, *volL, *volR;
            uint      Addr, k;
            pcm_chan_ CH;

            bufL = buf[0];
            bufR = buf[1];

            // clear buffers
            for (int d = 0; d < Length; d++)
            {
                bufL[d] = 0;
                bufR[d] = 0;
            }

            // if PCM disable, no sound
            if (chip.Enable == 0)
            {
                return(1);
            }

            // for long update
            for (i = 0; i < 8; i++)
            {
                CH = chip.Channel[i];

                // only loop when sounding and on
                if (CH.Enable > 0 && CH.Muted == 0)
                {
                    Addr = CH.Addr >> PCM_STEP_SHIFT;
                    //volL = &(PCM_Volume_Tab[CH->MUL_L << 8]);
                    //volR = &(PCM_Volume_Tab[CH->MUL_R << 8]);

                    for (j = 0; j < Length; j++)
                    {
                        // test for loop signal
                        if (chip.RAM[Addr] == 0xFF)
                        {
                            CH.Addr = (Addr = CH.Loop_Addr) << PCM_STEP_SHIFT;
                            if (chip.RAM[Addr] == 0xFF)
                            {
                                break;
                            }
                            else
                            {
                                j--;
                            }
                        }
                        else
                        {
                            if ((chip.RAM[Addr] & 0x80) != 0)
                            {
                                CH.Data  = chip.RAM[Addr] & 0x7F;
                                bufL[j] -= (int)(CH.Data * CH.MUL_L);
                                bufR[j] -= (int)(CH.Data * CH.MUL_R);
                            }
                            else
                            {
                                CH.Data = chip.RAM[Addr];
                                // this improves the sound of Cosmic Fantasy Stories,
                                // although it's definately false behaviour
                                if (CH.Data == 0 && chip.Smpl0Patch != 0)
                                {
                                    CH.Data = -0x7F;
                                }
                                bufL[j] += (int)(CH.Data * CH.MUL_L);
                                bufR[j] += (int)(CH.Data * CH.MUL_R);
                            }

                            bufL[j] = MDSound.Limit(bufL[j], Int16.MaxValue, Int16.MinValue);
                            bufR[j] = MDSound.Limit(bufR[j], Int16.MaxValue, Int16.MinValue);

                            // update address register
                            k       = Addr + 1;
                            CH.Addr = (CH.Addr + CH.Step) & 0x7FFFFFF;
                            Addr    = CH.Addr >> PCM_STEP_SHIFT;

                            for (; k < Addr; k++)
                            {
                                if (chip.RAM[k] == 0xFF)
                                {
                                    CH.Addr = (Addr = CH.Loop_Addr) << PCM_STEP_SHIFT;
                                    break;
                                }
                            }
                        }
                    }

                    if (chip.RAM[Addr] == 0xFF)
                    {
                        CH.Addr = CH.Loop_Addr << PCM_STEP_SHIFT;
                    }
                }
            }

            return(0);
        }
Beispiel #12
0
        /**
         * PCM_Write_Reg(): Write to a PCM register.
         * @param Reg Register ID.
         * @param Data Data to write.
         */
        private void PCM_Write_Reg(byte ChipID, uint Reg, uint Data)
        {
            pcm_chip_ chip = PCM_Chip[ChipID];
            int       i;
            pcm_chan_ chan = chip.Channel[chip.Cur_Chan];

            Data &= 0xFF;

            switch (Reg)
            {
            case 0x00:
                /* evelope register */
                chan.ENV   = Data;
                chan.MUL_L = (Data * (chan.PAN & 0x0F)) >> 5;
                chan.MUL_R = (Data * (chan.PAN >> 4)) >> 5;
                break;

            case 0x01:
                /* pan register */
                chan.PAN   = Data;
                chan.MUL_L = ((Data & 0x0F) * chan.ENV) >> 5;
                chan.MUL_R = ((Data >> 4) * chan.ENV) >> 5;
                break;

            case 0x02:
                /* frequency step (LB) registers */
                chan.Step_B &= 0xFF00;
                chan.Step_B += Data;
                chan.Step    = (uint)((float)chan.Step_B * chip.Rate);

                //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
                //	"Step low = %.2X   Step calculated = %.8X",
                //	Data, chan->Step);
                break;

            case 0x03:
                /* frequency step (HB) registers */
                chan.Step_B &= 0x00FF;
                chan.Step_B += Data << 8;
                chan.Step    = (uint)((float)chan.Step_B * chip.Rate);

                //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
                //	"Step high = %.2X   Step calculated = %.8X",
                //	Data, chan->Step);
                break;

            case 0x04:
                chan.Loop_Addr &= 0xFF00;
                chan.Loop_Addr += Data;

                //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
                //	"Loop low = %.2X   Loop = %.8X",
                //	Data, chan->Loop_Addr);
                break;

            case 0x05:
                /* loop address registers */
                chan.Loop_Addr &= 0x00FF;
                chan.Loop_Addr += Data << 8;

                //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
                //	"Loop high = %.2X   Loop = %.8X",
                //	Data, chan->Loop_Addr);
                break;

            case 0x06:
                /* start address registers */
                chan.St_Addr = Data << (PCM_STEP_SHIFT + 8);
                //chan->Addr = chan->St_Addr;

                //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
                //	"Start addr = %.2X   New Addr = %.8X",
                //	Data, chan->Addr);
                break;

            case 0x07:
                /* control register */
                /* mod is H */
                if ((Data & 0x40) > 0)
                {
                    /* select channel */
                    chip.Cur_Chan = (int)(Data & 0x07);
                }
                /* mod is L */
                else
                {
                    /* pcm ram bank select */
                    chip.Bank = (int)((Data & 0x0F) << 12);
                }

                /* sounding bit */
                if ((Data & 0x80) > 0)
                {
                    chip.Enable = 0xFF;     // Used as mask
                }
                else
                {
                    chip.Enable = 0;
                }

                //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
                //	"General Enable = %.2X", Data);
                break;

            case 0x08:
                /* sound on/off register */
                Data ^= 0xFF;

                //LOG_MSG(pcm, LOG_MSG_LEVEL_DEBUG1,
                //	"Channel Enable = %.2X", Data);

                for (i = 0; i < 8; i++)
                {
                    chan = chip.Channel[i];
                    if (chan.Enable == 0)
                    {
                        chan.Addr = chan.St_Addr;
                    }
                }

                for (i = 0; i < 8; i++)
                {
                    chip.Channel[i].Enable = (uint)(Data & (1 << i));
                }
                break;
            }
        }