Example #1
0
        public void ChannelStep(int cycles)
        {
            double cpuSpeedFactor = Spu.Device.SpeedFactor;

            if (!Active)
            {
                return;
            }

            // Update volume.
            _volumeEnvelope.Update(cycles);
            float amplitude = ChannelVolume * _volumeEnvelope.Volume / 15.0f;

            // Get elapsed gameboy time.
            double timeDelta = (cycles / GameBoyCpu.OfficialClockFrequency) / cpuSpeedFactor;

            // Allocate buffer.
            int sampleRate  = ChannelOutput.SampleRate;
            int sampleCount = (int)(timeDelta * sampleRate) * 2;

            using (var malloc = MemoryPool <float> .Shared.Rent(sampleCount))
            {
                var buffer = malloc.Memory.Span;

                if (!UseSoundLength || _length >= 0)
                {
                    double period            = 1 / Frequency;
                    int    periodSampleCount = (int)(period * sampleRate) * 2;

                    for (int i = 0; i < sampleCount; i += 2)
                    {
                        float sample = amplitude * (_lfsr.CurrentValue ? 1f : 0f);
                        Spu.WriteToSoundBuffer(ChannelNumber, buffer, i, sample);

                        _clock += 2;
                        if (_clock >= periodSampleCount)
                        {
                            _lfsr.PerformShift();
                            _clock -= periodSampleCount;
                        }
                    }

                    if (UseSoundLength)
                    {
                        _length -= timeDelta;
                    }
                }

                ChannelOutput.BufferSoundSamples(buffer, 0, sampleCount);
            }
        }
Example #2
0
        public void ChannelStep(int cycles)
        {
            double cpuSpeedFactor = Spu.Device.Cpu.SpeedFactor;

            if (!Active || double.IsNaN(cpuSpeedFactor) || double.IsInfinity(cpuSpeedFactor) || cpuSpeedFactor < 0.5)
            {
                return;
            }

            // Update volume.
            _volumeEnvelope.Update(cycles);
            float amplitude = ChannelVolume * _volumeEnvelope.Volume / 15.0f;

            // Get elapsed gameboy time.
            double timeDelta = (cycles / GameBoyCpu.OfficialClockFrequency) / cpuSpeedFactor;

            // Allocate buffer.
            int sampleRate  = ChannelOutput.SampleRate;
            int sampleCount = (int)(timeDelta * sampleRate) * 2;

            float[] buffer = new float[sampleCount];

            if (!UseSoundLength || _length >= 0)
            {
                double period            = 1 / Frequency;
                int    periodSampleCount = (int)(period * sampleRate) * 2;

                for (int i = 0; i < buffer.Length; i += 2)
                {
                    float sample = amplitude * (_lfsr.CurrentValue ? 1f : 0f);
                    Spu.WriteToSoundBuffer(ChannelNumber, buffer, i, sample);

                    _clock += 2;
                    if (_clock >= periodSampleCount)
                    {
                        _lfsr.PerformShift();
                        _clock -= periodSampleCount;
                    }
                }

                if (UseSoundLength)
                {
                    _length -= timeDelta;
                }
            }

            ChannelOutput.BufferSoundSamples(buffer, 0, buffer.Length);
        }
Example #3
0
        public void ChannelStep(int cycles)
        {
            double cpuSpeedFactor = Spu.Device.cpu.SpeedFactor;

            if (!Active ||
                !SoundEnabled ||
                double.IsNaN(cpuSpeedFactor) ||
                double.IsInfinity(cpuSpeedFactor) ||
                cpuSpeedFactor < 0.5)
            {
                return;
            }

            int    sampleRate  = ChannelOutput.SampleRate;
            double timeDelta   = (cycles / GameBoySpu.ClockSpeedHz) / cpuSpeedFactor;
            int    sampleCount = (int)(timeDelta * sampleRate) * 2;

            float[] buffer = new float[sampleCount];

            double interval            = 1.0 / Frequency;
            int    intervalSampleCount = (int)(interval * sampleRate);

            if (intervalSampleCount > 0)
            {
                for (int i = 0; i < buffer.Length; i += 2)
                {
                    _coordinate++;
                    if (_coordinate >= intervalSampleCount)
                    {
                        _top        = !_top;
                        _coordinate = 0;
                    }

                    int waveRamCoordinate = (int)(_coordinate / (double)intervalSampleCount * _waveRam.Length);

                    int waveDataSample = _top
                        ? (_waveRam[waveRamCoordinate] & 0xF)
                        : ((_waveRam[waveRamCoordinate] >> 4) & 0xF);

                    float sample = ChannelVolume * OutputLevel * (waveDataSample - 7) / 15f;

                    Spu.WriteToSoundBuffer(ChannelNumber, buffer, i, sample);
                }
            }

            ChannelOutput.BufferSoundSamples(buffer, 0, buffer.Length);
        }
Example #4
0
        public void ChannelStep(int cycles)
        {
            double cpuSpeedFactor = Spu.Device.SpeedFactor;

            if (!Active)
            {
                return;
            }

            int    sampleRate  = ChannelOutput.SampleRate;
            double timeDelta   = (cycles / GameBoyCpu.OfficialClockFrequency) / cpuSpeedFactor;
            int    sampleCount = (int)(timeDelta * sampleRate) * 2;

            using (var malloc = MemoryPool <float> .Shared.Rent(sampleCount))
            {
                var buffer = malloc.Memory.Span;

                double interval            = 1.0 / Frequency;
                int    intervalSampleCount = (int)(interval * sampleRate);

                if (intervalSampleCount > 0)
                {
                    for (int i = 0; i < sampleCount; i += 2)
                    {
                        _coordinate++;
                        if (_coordinate >= intervalSampleCount)
                        {
                            _top        = !_top;
                            _coordinate = 0;
                        }

                        int waveRamCoordinate = (int)(_coordinate / (double)intervalSampleCount * _waveRam.Length);

                        int waveDataSample = _top
                            ? (_waveRam[waveRamCoordinate] & 0xF)
                            : ((_waveRam[waveRamCoordinate] >> 4) & 0xF);

                        float sample = ChannelVolume * OutputLevel * (waveDataSample - 7) / 15f;

                        Spu.WriteToSoundBuffer(ChannelNumber, buffer, i, sample);
                    }
                }

                ChannelOutput.BufferSoundSamples(buffer, 0, sampleCount);
            }
        }
Example #5
0
        public virtual void ChannelStep(int cycles)
        {
            double cpuSpeedFactor = Spu.Device.SpeedFactor;

            if (!Active)
            {
                return;
            }

            // Update volume and calculate wave amplitude.
            _volumeEnvelope.Update(cycles);
            double amplitude = ChannelVolume * (_volumeEnvelope.Volume / 15.0);

            // Obtain elapsed gameboy time.
            double timeDelta = (cycles / GameBoyCpu.OfficialClockFrequency) / cpuSpeedFactor;

            // Allocate sound buffer.
            int sampleRate  = ChannelOutput.SampleRate;
            int sampleCount = (int)Math.Ceiling(timeDelta * sampleRate) * 2;

            using (var malloc = MemoryPool <float> .Shared.Rent(sampleCount))
            {
                var buffer = malloc.Memory.Span;
                if (!UseSoundLength || _length >= 0)
                {
                    double period = 1f / Frequency;
                    for (int i = 0; i < sampleCount; i += 2)
                    {
                        // Get current x coordinate and compute current sample value.
                        double x      = (double)_coordinate / sampleRate;
                        float  sample = DutyWave(amplitude, x, period);
                        Spu.WriteToSoundBuffer(ChannelNumber, buffer, i, sample);

                        _coordinate = (_coordinate + 1) % sampleRate;
                    }

                    if (UseSoundLength)
                    {
                        _length -= timeDelta;
                    }
                }

                ChannelOutput.BufferSoundSamples(buffer, 0, sampleCount);
            }
        }
Example #6
0
        private void CpuLoop()
        {
            bool enabled = true;

            while (enabled)
            {
                if (WaitHandle.WaitAny(new WaitHandle[] { _continueSignal, _terminateSignal }) == 1)
                {
                    enabled = false;
                }
                else
                {
                    Cpu.Running = true;
                    _continueSignal.Reset();
                    OnResumed();

                    int cycles = 0;
                    do
                    {
                        cycles += Cpu.PerformNextInstruction();
                        if (cycles >= GameBoyGpu.FullFrameCycles * Cpu.SpeedMultiplier)
                        {
                            Spu.SpuStep(cycles / Cpu.SpeedMultiplier);
                            cycles -= GameBoyGpu.FullFrameCycles * Cpu.SpeedMultiplier;
                            if (EnableFrameLimit)
                            {
                                WaitHandle.WaitAny(new WaitHandle[] { _breakSignal, _frameStartSignal });
                                _frameStartSignal.Reset();
                            }
                        }

                        if (_breakpoints.TryGetValue(Cpu.Registers.PC, out var breakpoint) && breakpoint.Condition(Cpu))
                        {
                            Cpu.IsBroken = true;
                        }
                    } while (!Cpu.IsBroken);

                    _breakSignal.Reset();
                    Cpu.Running = false;
                    OnPaused();
                }
            }
            OnTerminated();
        }
Example #7
0
        public virtual void ChannelStep(int cycles)
        {
            double cpuSpeedFactor = Spu.Device.cpu.SpeedFactor;

            if (!Active || double.IsNaN(cpuSpeedFactor) || double.IsInfinity(cpuSpeedFactor) || cpuSpeedFactor < 0.5)
            {
                return;
            }

            // Update volume and calculate wave amplitude.
            _volumeEnvelope.Update(cycles);
            double amplitude = ChannelVolume * (_volumeEnvelope.Volume / 15.0);

            // Obtain elapsed gameboy time.
            double timeDelta = (cycles / GameBoySpu.ClockSpeedHz) / cpuSpeedFactor;

            // Allocate sound buffer.
            int sampleRate  = ChannelOutput.SampleRate;
            int sampleCount = (int)Math.Ceiling(timeDelta * sampleRate) * 2;
            var buffer      = new float[sampleCount];

            if (!UseSoundLength || _length >= 0)
            {
                double period = 1f / Frequency;
                for (int i = 0; i < buffer.Length; i += 2)
                {
                    // Get current x coordinate and compute current sample value.
                    double x      = (double)_coordinate / sampleRate;
                    float  sample = DutyWave(amplitude, x, period);
                    Spu.WriteToSoundBuffer(ChannelNumber, buffer, i, sample);

                    _coordinate = (_coordinate + 1) % sampleRate;
                }

                if (UseSoundLength)
                {
                    _length -= timeDelta;
                }
            }

            ChannelOutput.BufferSoundSamples(buffer, 0, buffer.Length);
        }