示例#1
0
        private float _vibratoPhase; // Phase through the vibrato sine wave

        #endregion Fields

        #region Constructors

        public Synth(SynthParams sfxParams)
        {
            GenerateAudioData(sfxParams);
        }
示例#2
0
        private float[] GenerateAudioData(SynthParams sfxParams)
        {
            float[] buffer = null;
            bool _finished = false;

            for (int i = 0; i < buffer.Length; i++)
            {
                if (_finished) return buffer;

                // Repeats every _repeatLimit times, partially resetting the sound parameters
                if (sfxParams.RepeatLimit > 0)
                {
                    if (++_repeatTime >= sfxParams.RepeatLimit)
                    {
                        _repeatTime = 0;
                        Reset(false);
                    }
                }

                // If _changeLimit is reached, shifts the pitch
                if (_changeLimit != 0)
                {
                    if (++_changeTime >= _changeLimit)
                    {
                        _changeLimit = 0;
                        _period *= sfxParams.ChangeAmount;
                    }
                }

                // Acccelerate and apply slide
                sfxParams.Slide += sfxParams.DeltaSlide;
                _period *= sfxParams.Slide;

                // Checks for frequency getting too low, and stops the sound if a minFrequency was set
                if (_period > _maxPeriod)
                {
                    _period = _maxPeriod;
                    if (sfxParams.MinFrequency > 0) _finished = true;
                }

                _periodTemp = _period;

                if (sfxParams.IsVibratoEnabled)
                {
                    _vibratoPhase += sfxParams.VibratoSpeed;
                    _periodTemp = _period * (float)(1.0f + Math.Sin(_vibratoPhase) * sfxParams.VibratoDepth);
                }

                _periodTemp = Math.Max((int)_periodTemp,8);

                if (sfxParams.WaveShape == SynthParams.WaveShapeEnum.Square)
                {
                    sfxParams.SquareDuty += sfxParams.DutySweep;
                    if (sfxParams.SquareDuty < 0.0) sfxParams.SquareDuty = 0.0f;
                    if (sfxParams.SquareDuty > 0.5) sfxParams.SquareDuty = 0.5f;
                }

                // Moves through the different stages of the volume envelope
                if (++_envelopeTime > _envelopeLength) {
                    _envelopeTime = 0;

                    switch (++_envelopeStage) {
                        case 1:
                            _envelopeLength = _envelopeLength1;
                            break;
                        case 2:
                            _envelopeLength = _envelopeLength2;
                            break;
                    }
                }

                // Sets the volume based on the position in the envelope
                switch (_envelopeStage) {
                    case 0:
                        _envelopeVolume = _envelopeTime * _envelopeOverLength0;
                        break;
                    case 1:
                        _envelopeVolume = 1.0f + (1.0f - _envelopeTime * _envelopeOverLength1) * 2.0f * sfxParams.SustainPunch;
                        break;
                    case 2:
                        _envelopeVolume = 1.0f - _envelopeTime * _envelopeOverLength2;
                        break;
                    case 3:
                        _envelopeVolume = 0.0f;
                        _finished = true;
                        break;
                }

                if (sfxParams.IsPhaserEnabled)
                {
                    _phaserOffset += _phaserDeltaOffset;
                    _phaserInt = (int)_phaserOffset;
                    if (_phaserInt < 0) _phaserInt = -_phaserInt;
                    if (_phaserInt > 1023) _phaserInt = 1023;
                }

                if (sfxParams.IsFilterEnabled && Math.Abs(sfxParams.HighPassFilterCutoffSweep) > TOLERANCE) {
                    sfxParams.HighPassFilterCutoff *= sfxParams.HighPassFilterCutoffSweep;
                    if (sfxParams.HighPassFilterCutoff < 0.00001f)
                        sfxParams.HighPassFilterCutoff = 0.00001f;
                    if (sfxParams.HighPassFilterCutoff > 0.1f)
                        sfxParams.HighPassFilterCutoff = 0.1f;
                }

                _superSample = 0;

                // Generates 8 samples which are averaged out to produce superSample
                for (int cycle = 0; cycle < 8; cycle++)
                {
                    if (++_phase >= _periodTemp) _phase = _phase % (int)_periodTemp;

                    switch (sfxParams.WaveShape)
                    {
                        case SynthParams.WaveShapeEnum.Square:
                            _sample = ((_phase / _periodTemp) < sfxParams.SquareDuty) ? 0.5f : -0.5f;
                            break;

                        case SynthParams.WaveShapeEnum.Saw:
                            _sample = 1.0f - (_phase / _periodTemp) * 2.0f;
                            break;

                        case SynthParams.WaveShapeEnum.Sine:
                            _pos = _phase / _periodTemp;
                            _pos = _pos > 0.5f ? (_pos - 1.0f) * 6.28318531f : _pos * 6.28318531f;
                            _sample = _pos < 0 ? 1.27323954f * _pos + 0.405284735f * _pos * _pos : 1.27323954f * _pos - 0.405284735f * _pos * _pos;
                            _sample = _sample < 0 ? 0.225f * (_sample * -_sample - _sample) + _sample : 0.225f * (_sample * _sample - _sample) + _sample;
                            break;

                        case SynthParams.WaveShapeEnum.Noise:
                            _sample = GetRandom.Float(-1, 1);
                            break;
                    }

                    // Applies the low and high pass filters
                    if (sfxParams.IsFilterEnabled) {
                        _lpFilterOldPos = _lpFilterPos;
                        sfxParams.LowPassFilterCutoff *= sfxParams.LowPassFilterCutoffSweep;
                        if (sfxParams.LowPassFilterCutoff < 0.0) sfxParams.LowPassFilterCutoff = 0.0f;
                        if (sfxParams.LowPassFilterCutoff > 0.1) sfxParams.LowPassFilterCutoff = 0.1f;

                        if (sfxParams.IsLowPassFilterEnabled) {
                            _lpFilterDeltaPos += (_sample - _lpFilterPos) * sfxParams.LowPassFilterCutoff;
                            _lpFilterDeltaPos *= _lpFilterDamping;
                        } else {
                            _lpFilterPos = _sample;
                            _lpFilterDeltaPos = 0.0f;
                        }

                        _lpFilterPos += _lpFilterDeltaPos;

                        _hpFilterPos += _lpFilterPos - _lpFilterOldPos;
                        _hpFilterPos *= 1.0f - sfxParams.HighPassFilterCutoff;
                        _sample = _hpFilterPos;
                    }

                    if (sfxParams.IsPhaserEnabled) {
                        _phaserBuffer[_phaserPos & 1023] = _sample;
                        _sample += _phaserBuffer[(_phaserPos - _phaserInt + 1024) & 1023];
                        _phaserPos = (_phaserPos + 1) & 1023;
                    }

                    _superSample += _sample;
                }

                // Averages out the super samples and applies volumes
                _superSample = sfxParams.MasterVolume * _envelopeVolume * _superSample * 0.125f;

                // Apply clipping
                if (_superSample < -1f) _superSample = -1f;
                if (_superSample > 1f) _superSample = 1f;

                // Writes value to list, ignoring left/right sound channels (this is applied when filtering the audio later)
                buffer[i] = _superSample;
            }

            return buffer;
        }
示例#3
0
            public static SynthParams Powerup()
            {
                var result = new SynthParams();

                if (GetRandom.Bool())
                {
                    result.WaveShape = WaveShapeEnum.Saw;
                }
                else
                {
                    result.SquareDuty = GetRandom.Float(0.6f);
                }

                if (GetRandom.Bool())
                {
                    result.StartFrequency = GetRandom.Float(0.2f, 0.5f);
                    result.Slide = GetRandom.Float(0.1f, 0.5f);
                    result.RepeatSpeed = GetRandom.Float(0.4f, 0.8f);
                }
                else
                {
                    result.StartFrequency = GetRandom.Float(0.2f, 0.5f);
                    result.Slide = GetRandom.Float(0.05f, 0.25f);

                    if (GetRandom.Bool())
                    {
                        result.VibratoDepth = GetRandom.Float(0.7f);
                        result.VibratoSpeed = GetRandom.Float(0.6f);
                    }
                }

                result.SustainTime = GetRandom.Float(0.4f);
                result.DecayTime = GetRandom.Float(0.1f, 0.5f);

                return result;
            }
示例#4
0
            public static SynthParams Random()
            {
                var result = new SynthParams
                {
                    WaveShape = (WaveShapeEnum) (GetRandom.Float()*4f),

                    AttackTime = (float) Math.Pow(GetRandom.Float(-1, 1), 4),
                    SustainTime = (float) Math.Pow(GetRandom.Float(-1, 1), 2),
                    SustainPunch = (float) Math.Pow(GetRandom.Float(0.8f), 2),
                    DecayTime = GetRandom.Float(),

                    StartFrequency = (GetRandom.Bool()) ? (float) Math.Pow(GetRandom.Float(-1, 1), 2) : ((float) Math.Pow(GetRandom.Float(0.5f), 3) + 0.5f),
                    MinFrequency = 0.0f,

                    Slide = (float) Math.Pow(GetRandom.Float(-1, 1), 5),
                    DeltaSlide = (float) Math.Pow(GetRandom.Float(-1, 1), 3),

                    VibratoDepth = (float) Math.Pow(GetRandom.Float(-1, 1), 3),
                    VibratoSpeed = GetRandom.Float(-1, 1),

                    ChangeAmount = GetRandom.Float(-1, 1),
                    ChangeSpeed = GetRandom.Float(-1, 1),

                    SquareDuty = GetRandom.Float(-1, 1),
                    DutySweep = (float) Math.Pow(GetRandom.Float(-1, 1), 3),

                    RepeatSpeed = GetRandom.Float(-1, 1),

                    PhaserOffset = (float) Math.Pow(GetRandom.Float(-1, 1), 3),
                    PhaserSweep = (float) Math.Pow(GetRandom.Float(-1, 1), 3),

                    LowPassFilterCutoff = 1f - (float) Math.Pow(GetRandom.Float(), 3),
                    LowPassFilterCutoffSweep = (float) Math.Pow(GetRandom.Float(-1, 1), 3),
                    LowPassFilterResonance = GetRandom.Float(-1, 1),
                    HighPassFilterCutoff = (float) Math.Pow(GetRandom.Float(), 5),
                    HighPassFilterCutoffSweep = (float) Math.Pow(GetRandom.Float(-1, 1), 5),
                };

                if (result.AttackTime + result.SustainTime + result.DecayTime < 0.2f)
                {
                    result.SustainTime = GetRandom.Float(0.2f, 0.5f);
                    result.DecayTime = GetRandom.Float(0.2f, 0.5f);
                }

                if ((result.StartFrequency > 0.7f && result.Slide > 0.2) || (result.StartFrequency < 0.2 && result.Slide < -0.05))
                {
                    result.Slide = -result.Slide;
                }

                if (result.LowPassFilterCutoff < 0.1f && result.LowPassFilterCutoffSweep < -0.05f)
                {
                    result.LowPassFilterCutoffSweep = -result.LowPassFilterCutoffSweep;
                }

                return result;
            }
示例#5
0
            public static SynthParams MenuBlip()
            {
                var result = new SynthParams();

                result.WaveShape = (WaveShapeEnum) (GetRandom.Int(2));
                if (result.WaveShape == WaveShapeEnum.Square) result.SquareDuty = GetRandom.Float(0.6f);

                result.StartFrequency = GetRandom.Float(0.2f, 0.6f);

                result.SustainTime = GetRandom.Float(0.1f, 0.2f);
                result.DecayTime = GetRandom.Float(0.2f);
                result.HighPassFilterCutoff = 0.1f;

                return result;
            }
示例#6
0
            public static SynthParams PlayerHurt()
            {
                var result = new SynthParams();

                result.WaveShape = (WaveShapeEnum)(GetRandom.Int(3));
                if (result.WaveShape == WaveShapeEnum.Sine) result.WaveShape = WaveShapeEnum.Noise;
                if (result.WaveShape == WaveShapeEnum.Square) result.SquareDuty = GetRandom.Float(0.6f);

                result.StartFrequency = GetRandom.Float(0.2f, 0.8f);
                result.Slide = GetRandom.Float(-0.3f, 0.1f);

                result.SustainTime = GetRandom.Float(0.1f);
                result.DecayTime = GetRandom.Float(0.1f,0.3f);

                if (GetRandom.Bool()) result.HighPassFilterCutoff = GetRandom.Float(0.3f);

                return result;
            }
示例#7
0
            public static SynthParams Laser()
            {
                var result = new SynthParams();

                result.WaveShape = (WaveShapeEnum)(GetRandom.Int(3));

                result.StartFrequency = GetRandom.Float(0.5f,1);
                result.MinFrequency = result.StartFrequency - 0.2f - GetRandom.Float() * 0.6f;
                if (result.MinFrequency < 0.2f) result.MinFrequency = 0.2f;

                result.Slide = -0.15f - GetRandom.Float() * 0.2f;

                if (GetRandom.Float() < 0.33f) {
                    result.StartFrequency = 0.3f + GetRandom.Float() * 0.6f;
                    result.MinFrequency = GetRandom.Float(0.1f);
                    result.Slide = GetRandom.Float(-0.65f,-0.35f);
                }

                if (GetRandom.Bool()) {
                    result.SquareDuty = GetRandom.Float(0.5f);
                    result.DutySweep = GetRandom.Float(0.2f);
                } else {
                    result.SquareDuty = GetRandom.Float(0.4f,0.9f);
                    result.DutySweep = -GetRandom.Float(0.7f);
                }

                result.SustainTime = GetRandom.Float(0.1f,0.3f);
                result.DecayTime = GetRandom.Float(0.4f);
                if (GetRandom.Bool()) result.SustainPunch = GetRandom.Float(0.3f);

                if (GetRandom.Bool(1/3)) {
                    result.PhaserOffset = GetRandom.Float(0.2f);
                    result.PhaserSweep = GetRandom.Float(-0.2f,0);
                }

                if (GetRandom.Bool()) result.HighPassFilterCutoff = GetRandom.Float(0.3f);

                return result;
            }
示例#8
0
            public static SynthParams Jump()
            {
                var result = new SynthParams();

                result.WaveShape = WaveShapeEnum.Square;
                result.SquareDuty = GetRandom.Float(0.6f);
                result.StartFrequency = GetRandom.Float(0.3f, 0.6f);
                result.Slide = GetRandom.Float(0.1f, 0.3f);

                result.SustainTime = GetRandom.Float(0.1f, 0.4f);
                result.DecayTime = GetRandom.Float(0.1f, 0.3f);

                if (GetRandom.Bool()) result.HighPassFilterCutoff = GetRandom.Float(0.3f);
                if (GetRandom.Bool()) result.LowPassFilterCutoff = GetRandom.Float(0.4f, 1.0f);

                return result;
            }
示例#9
0
            public static SynthParams Explosion()
            {
                var result = new SynthParams();
                result.WaveShape = WaveShapeEnum.Noise;

                if (GetRandom.Bool()) {
                    result.StartFrequency = GetRandom.Float(0.1f,0.5f);
                    result.Slide = -0.1f + GetRandom.Float() * 0.4f;
                } else {
                    result.StartFrequency = GetRandom.Float(0.2f,0.9f);
                    result.Slide = GetRandom.Float(-0.2f,0);
                }

                result.StartFrequency *= result.StartFrequency;

                if (GetRandom.Bool(1/5)) result.Slide = 0;
                if (GetRandom.Bool(1/3)) result.RepeatSpeed = GetRandom.Float(0.3f,0.8f);

                result.SustainTime = GetRandom.Float(0.1f,0.4f);
                result.DecayTime = GetRandom.Float(0.5f);
                result.SustainPunch = GetRandom.Float(0.2f,0.8f);

                if (GetRandom.Bool()) {
                    result.PhaserOffset = GetRandom.Float(-0.3f, 0.6f);
                    result.PhaserSweep = GetRandom.Float(-0.3f,0);
                }

                if (GetRandom.Bool(1/3)) {
                    result.ChangeSpeed = GetRandom.Float(0.6f,0.9f);
                    result.ChangeAmount = GetRandom.Float(0.8f,0.8f);
                }

                return result;
            }
示例#10
0
 public static SynthParams Default()
 {
     var result = new SynthParams();
     result.Reset();
     return result;
 }
示例#11
0
            public static SynthParams Coin()
            {
                var result = new SynthParams();

                result.StartFrequency = GetRandom.Float(0.4f, 0.9f);

                result.SustainTime = GetRandom.Float(0.1f);
                result.DecayTime = GetRandom.Float(0.1f, 0.5f);
                result.SustainPunch = GetRandom.Float(0.3f, 0.6f);

                if (GetRandom.Bool())
                {
                    result.ChangeSpeed = GetRandom.Float(0.5f, 0.7f);
                    result.ChangeAmount = GetRandom.Float(0.2f, 0.6f);
                }

                return result;
            }