Beispiel #1
0
        public PSG(CDRom cdrom)
        {
            m_Channels = new PSG_Channel[8];

            for (int i = 0; i < 8; i++)
            {
                m_Channels[i]               = new PSG_Channel();
                m_Channels[i].m_Buffer      = new int[32];
                m_Channels[i].m_BufferIndex = 0;
            }

            m_Selected = m_Channels[0];
            m_CDRom    = cdrom;

            StartMixer(44100, 1024);
        }
Beispiel #2
0
        public void Write(int address, byte data)
        {
            switch (address)
            {
            // Global audio registers
            case 0x800:
                m_Selected = m_Channels[data & 0x07];
                break;

            case 0x801:
                m_Left_Volume  = (data >> 4);
                m_Right_Volume = (data & 0x0F);
                break;

            case 0x808:
                m_LFO_Frequency = data;
                break;

            case 0x809:
                m_LFO_Enabled = (data & 0x80) != 0;

                switch (data & 0x3)
                {
                case 0:
                    m_LFO_Active = false;
                    break;

                case 1:
                    m_LFO_Active = true;
                    m_LFO_Shift  = 0;
                    break;

                case 2:
                    m_LFO_Active = true;
                    m_LFO_Shift  = 4;
                    break;

                case 3:
                    m_LFO_Active = true;
                    m_LFO_Shift  = 8;
                    break;
                }
                if (m_LFO_Enabled && m_LFO_Active)
                {
                    Console.WriteLine("LFO MODE HAS BEEN ACTIVATED");
                }
                break;

            // Per Channel Registers
            case 0x802:
                m_Selected.m_Frequency = (m_Selected.m_Frequency & 0x0F00) | data;
                break;

            case 0x803:
                m_Selected.m_Frequency = (m_Selected.m_Frequency & 0x00FF) | ((data << 8) & 0x0F00);
                break;

            case 0x804:
                m_Selected.m_Enabled = (data & 0x80) != 0;
                m_Selected.m_DDA     = (data & 0x40) != 0;
                m_Selected.m_Volume  = data & 0x0F;
                break;

            case 0x805:
                m_Selected.m_Left_Volume  = (data >> 4);
                m_Selected.m_Right_Volume = (data & 0x0F);
                break;

            case 0x806:
                m_Selected.m_DDA_Output = data & 0x1F;
                m_Selected.m_Buffer[m_Selected.m_BufferIndex] = (data & 0x1F) - 0x10;
                m_Selected.m_BufferIndex = (m_Selected.m_BufferIndex + 1) & 0x1F;
                break;

            case 0x807:
                m_Selected.m_Noise              = ((data & 0x80) != 0);
                m_Selected.m_NoiseFrequency     = (data & 0x1F ^ 0x1F);
                m_Selected.m_RealNoiseFrequency = 112005.0f / m_SampleRate / (m_Selected.m_NoiseFrequency + 1);
                break;

            default:
                Console.WriteLine("PSG Access at {0:x} -> {1:x}", address, data);
                break;
            }

            for (int i = 0; i < 6; i++)
            {
                PSG_Channel channel = m_Channels[i];
                channel.m_RealFrequency = 3584160.0f / m_SampleRate / (channel.m_Frequency + 1);
                channel.m_LeftOutput    = m_VolumeTable[(channel.m_Left_Volume + m_Left_Volume) * 2 + channel.m_Volume];
                channel.m_RightOutput   = m_VolumeTable[(channel.m_Right_Volume + m_Right_Volume) * 2 + channel.m_Volume];

                if (i < 4)
                {
                    channel.m_Noise = false;
                }
            }

            m_RealLFOFrequency = 3584160.0f / m_SampleRate / ((m_Channels[1].m_Frequency + 1) * m_LFO_Frequency);
        }
Beispiel #3
0
        public unsafe void audioCallback(void *userdata, void *buffer, int len)
        {
            short *stream = (short *)buffer;
            int    i, c;

            len /= 2;

            for (i = 0; i < len; i += 2)
            {
                float left  = 0;
                float right = 0;

                if (m_LFO_Enabled && m_LFO_Active)
                {
                    PSG_Channel channel = m_Channels[1];
                    int         LFOFreq = channel.m_Buffer[(int)channel.m_OutputIndex];

                    channel.m_OutputIndex += m_RealLFOFrequency;
                    while (channel.m_BufferIndex >= 32)
                    {
                        channel.m_BufferIndex -= 32;
                    }

                    // Sign extend the frequency
                    if ((LFOFreq & 0x10) != 0)
                    {
                        LFOFreq |= -16;
                    }

                    channel = m_Channels[0];
                    channel.m_RealFrequency = 3584160.0f / m_SampleRate / (channel.m_Frequency + (LFOFreq << m_LFO_Shift) + 1);
                }

                for (c = 0; c < 6; c++)
                {
                    PSG_Channel channel = m_Channels[c];

                    // LFO disables channel 1
                    if (!channel.m_Enabled || (m_LFO_Enabled && c == 1))
                    {
                        continue;
                    }

                    int sample;

                    if (channel.m_DDA)
                    {
                        sample = channel.m_DDA_Output;
                    }
                    else if (channel.m_Noise)
                    {
                        sample = m_NoiseBuffer[(int)channel.m_NoiseIndex];
                        channel.m_NoiseIndex += channel.m_RealFrequency;

                        while (channel.m_NoiseIndex >= 0x8000)
                        {
                            channel.m_NoiseIndex -= 0x8000;
                        }
                    }
                    else
                    {
                        sample = channel.m_Buffer[(int)channel.m_OutputIndex];
                        channel.m_OutputIndex += channel.m_RealFrequency;

                        while (channel.m_OutputIndex >= 32)
                        {
                            channel.m_OutputIndex -= 32;
                        }
                    }

                    left  += sample * channel.m_LeftOutput;
                    right += sample * channel.m_RightOutput;
                }

                *(stream++) = (short)(right + m_BaseLine);
                *(stream++) = (short)(left + m_BaseLine);
            }

            m_CDRom.MixCD((short *)buffer, len * 2);
        }