Пример #1
0
        public void CacheSamples()
        {
            while(_currentSynthesizedSample < (uint)envelopeFullLength)
            {
                //TODO: error checking, exceptions, etc...
                SynthesizedBuffer buffer = new SynthesizedBuffer();
                buffer.samples = new float[this.BufferSize];

                //initialize buffer
                for(int i = 0; i < buffer.samples.Length; i++)
                    buffer.samples[i] = 0.0f;

                bool finished = false;

                //for (int i = 0; i < samples.Length; i++)
                for(long counter = 0; counter < this.BufferSize; counter++)
                {

                    if (finished)
                        break;

                    // Repeats every _repeatLimit times, partially resetting the sound parameters
                    if(repeatLimit != 0)
                    {
                        if(++repeatTime >= repeatLimit)
                        {
                            repeatTime = 0;
                            Reset(false);
                        }
                    }

                    // If _changeLimit is reached, shifts the pitch
                    if(changeLimit != 0)
                    {
                        if(++changeTime >= changeLimit)
                        {
                            changeLimit = 0;
                            period *= changeAmount;
                        }
                    }

                    // Acccelerate and apply slide
                    slide += deltaSlide;
                    period *= slide;

                    // Checks for frequency getting too low, and stops the sound if a minFrequency was set
                    if(period > maxPeriod)
                    {
                        period = maxPeriod;
                        if(minFrequency > 0.0)
                            finished = true;
                    }

                    periodTemp = period;

                    // Applies the vibrato effect
                    if(vibratoAmplitude > 0.0)
                    {
                        vibratoPhase += vibratoSpeed;
                        periodTemp = period * (float)(1.0 + Math.Sin(vibratoPhase) * vibratoAmplitude);
                    }

                    periodTemp = (int)periodTemp;
                    if(periodTemp < 8)
                        periodTemp = 8;

                    // Sweeps the square duty
                    if (waveType == 0)
                    {
                        squareDuty += dutySweep;
                        if(squareDuty < 0.0f)
                            squareDuty = 0.0f;
                        else if (squareDuty > 0.5f)
                            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 * sustainPunch;
                            break;
                        case 2:
                            envelopeVolume = 1.0f - envelopeTime * envelopeOverLength2;
                            break;
                        case 3:
                            envelopeVolume = 0.0f;
                            finished = true;
                            break;
                    }

                    // Moves the phaser offset
                    if (phaser)
                    {
                        phaserOffset += phaserDeltaOffset;
                        phaserInt = (int)phaserOffset;
                        if(phaserInt < 0)
                            phaserInt = -phaserInt;
                        else if (phaserInt > 1023)
                            phaserInt = 1023;
                    }

                    // Moves the high-pass filter cutoff
                    if(filters && hpFilterDeltaCutoff != 0.0)
                    {
                        hpFilterCutoff *= hpFilterDeltaCutoff;
                        if(hpFilterCutoff < 0.00001f)
                            hpFilterCutoff = 0.00001f;
                        else if(hpFilterCutoff > 0.1f)
                            hpFilterCutoff = 0.1f;
                    }

                    superSample = 0.0f;
                    for(int j = 0; j < 8; j++)
                    {
                        // Cycles through the period
                        phase++;
                        if(phase >= periodTemp)
                        {
                            phase = phase - (int)periodTemp;

                            // Generates new random noise for this period
                            if(waveType == WaveType.Noise)
                            {
                                for(int n=0; n<32; n++)
                                    noiseBuffer[n] = (float)random.NextDouble() * 2.0f - 1.0f;
                            }
                        }

                        // Gets the sample from the oscillator
                        switch(waveType)
                        {
                            case WaveType.Square: // Square wave
                            {
                                sample = ((phase / periodTemp) < squareDuty) ? 0.5f : -0.5f;
                                break;
                            }
                            case WaveType.Saw: // Saw wave
                            {
                                sample = 1.0f - (phase / periodTemp) * 2.0f;
                                break;
                            }
                            case WaveType.Sin: // Sine wave (fast and accurate approx)
                            {
                                pos = phase / periodTemp;
                                pos = pos > 0.5f ? (pos - 1.0f) * 6.28318531f : pos * 6.28318531f;
                                sample = pos < 0 ? 1.27323954f * pos + .405284735f * pos * pos : 1.27323954f * pos - 0.405284735f * pos * pos;
                                sample = sample < 0 ? .225f * (sample *-sample - sample) + sample : .225f * (sample * sample - sample) + sample;

                                break;
                            }
                            case WaveType.Noise: // Noise
                            {
                                sample = noiseBuffer[(phase * 32 / (int)periodTemp) % 32];
                                break;
                            }
                        }

                        // Applies the low and high pass filters
                        if (filters)
                        {
                            lpFilterOldPos = lpFilterPos;
                            lpFilterCutoff *= lpFilterDeltaCutoff;
                            if(lpFilterCutoff < 0.0f)
                                lpFilterCutoff = 0.0f;
                            else if(lpFilterCutoff > 0.1f)
                                lpFilterCutoff = 0.1f;

                            if(lpFilterOn)
                            {
                                lpFilterDeltaPos += (sample - lpFilterPos) * lpFilterCutoff;
                                lpFilterDeltaPos *= lpFilterDamping;
                            }
                            else
                            {
                                lpFilterPos = sample;
                                lpFilterDeltaPos = 0.0f;
                            }

                            lpFilterPos += lpFilterDeltaPos;

                            hpFilterPos += lpFilterPos - lpFilterOldPos;
                            hpFilterPos *= 1.0f - hpFilterCutoff;
                            sample = hpFilterPos;
                        }

                        // Applies the phaser effect
                        if (phaser)
                        {
                            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 = masterVolume * envelopeVolume * superSample * 0.125f;

                    // Clipping if too loud
                    if(superSample > 1.0f)
                        superSample = 1.0f;
                    else if(superSample < -1.0f)
                        superSample = -1.0f;

                    buffer.samples[counter] = (float)superSample;
                    _currentSynthesizedSample++;
                }

                _synthesizedBlocks.Enqueue(buffer);

            }

            //return new SoundEffect(byteSamples, 44100, AudioChannels.Mono);
            this.IsCached = true;
            this.IsReadyToPlay = true;

            _currentSynthesizedSample = 0;
        }
Пример #2
0
        public void CacheSamples()
        {
            while (_currentSynthesizedSample < (uint)envelopeFullLength)
            {
                //TODO: error checking, exceptions, etc...
                SynthesizedBuffer buffer = new SynthesizedBuffer();
                buffer.samples = new float[this.BufferSize];

                //initialize buffer
                for (int i = 0; i < buffer.samples.Length; i++)
                {
                    buffer.samples[i] = 0.0f;
                }

                bool finished = false;

                //for (int i = 0; i < samples.Length; i++)
                for (long counter = 0; counter < this.BufferSize; counter++)
                {
                    if (finished)
                    {
                        break;
                    }

                    // Repeats every _repeatLimit times, partially resetting the sound parameters
                    if (repeatLimit != 0)
                    {
                        if (++repeatTime >= repeatLimit)
                        {
                            repeatTime = 0;
                            Reset(false);
                        }
                    }

                    // If _changeLimit is reached, shifts the pitch
                    if (changeLimit != 0)
                    {
                        if (++changeTime >= changeLimit)
                        {
                            changeLimit = 0;
                            period     *= changeAmount;
                        }
                    }

                    // Acccelerate and apply slide
                    slide  += deltaSlide;
                    period *= slide;

                    // Checks for frequency getting too low, and stops the sound if a minFrequency was set
                    if (period > maxPeriod)
                    {
                        period = maxPeriod;
                        if (minFrequency > 0.0)
                        {
                            finished = true;
                        }
                    }

                    periodTemp = period;

                    // Applies the vibrato effect
                    if (vibratoAmplitude > 0.0)
                    {
                        vibratoPhase += vibratoSpeed;
                        periodTemp    = period * (float)(1.0 + Math.Sin(vibratoPhase) * vibratoAmplitude);
                    }

                    periodTemp = (int)periodTemp;
                    if (periodTemp < 8)
                    {
                        periodTemp = 8;
                    }

                    // Sweeps the square duty
                    if (waveType == 0)
                    {
                        squareDuty += dutySweep;
                        if (squareDuty < 0.0f)
                        {
                            squareDuty = 0.0f;
                        }
                        else if (squareDuty > 0.5f)
                        {
                            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 * sustainPunch;
                        break;

                    case 2:
                        envelopeVolume = 1.0f - envelopeTime * envelopeOverLength2;
                        break;

                    case 3:
                        envelopeVolume = 0.0f;
                        finished       = true;
                        break;
                    }

                    // Moves the phaser offset
                    if (phaser)
                    {
                        phaserOffset += phaserDeltaOffset;
                        phaserInt     = (int)phaserOffset;
                        if (phaserInt < 0)
                        {
                            phaserInt = -phaserInt;
                        }
                        else if (phaserInt > 1023)
                        {
                            phaserInt = 1023;
                        }
                    }

                    // Moves the high-pass filter cutoff
                    if (filters && hpFilterDeltaCutoff != 0.0)
                    {
                        hpFilterCutoff *= hpFilterDeltaCutoff;
                        if (hpFilterCutoff < 0.00001f)
                        {
                            hpFilterCutoff = 0.00001f;
                        }
                        else if (hpFilterCutoff > 0.1f)
                        {
                            hpFilterCutoff = 0.1f;
                        }
                    }

                    superSample = 0.0f;
                    for (int j = 0; j < 8; j++)
                    {
                        // Cycles through the period
                        phase++;
                        if (phase >= periodTemp)
                        {
                            phase = phase - (int)periodTemp;

                            // Generates new random noise for this period
                            if (waveType == WaveType.Noise)
                            {
                                for (int n = 0; n < 32; n++)
                                {
                                    noiseBuffer[n] = (float)random.NextDouble() * 2.0f - 1.0f;
                                }
                            }
                        }

                        // Gets the sample from the oscillator
                        switch (waveType)
                        {
                        case WaveType.Square:                                 // Square wave
                        {
                            sample = ((phase / periodTemp) < squareDuty) ? 0.5f : -0.5f;
                            break;
                        }

                        case WaveType.Saw:                                 // Saw wave
                        {
                            sample = 1.0f - (phase / periodTemp) * 2.0f;
                            break;
                        }

                        case WaveType.Sin:                                 // Sine wave (fast and accurate approx)
                        {
                            pos    = phase / periodTemp;
                            pos    = pos > 0.5f ? (pos - 1.0f) * 6.28318531f : pos * 6.28318531f;
                            sample = pos < 0 ? 1.27323954f * pos + .405284735f * pos * pos : 1.27323954f * pos - 0.405284735f * pos * pos;
                            sample = sample < 0 ? .225f * (sample * -sample - sample) + sample : .225f * (sample * sample - sample) + sample;

                            break;
                        }

                        case WaveType.Noise:                                 // Noise
                        {
                            sample = noiseBuffer[(phase * 32 / (int)periodTemp) % 32];
                            break;
                        }
                        }

                        // Applies the low and high pass filters
                        if (filters)
                        {
                            lpFilterOldPos  = lpFilterPos;
                            lpFilterCutoff *= lpFilterDeltaCutoff;
                            if (lpFilterCutoff < 0.0f)
                            {
                                lpFilterCutoff = 0.0f;
                            }
                            else if (lpFilterCutoff > 0.1f)
                            {
                                lpFilterCutoff = 0.1f;
                            }

                            if (lpFilterOn)
                            {
                                lpFilterDeltaPos += (sample - lpFilterPos) * lpFilterCutoff;
                                lpFilterDeltaPos *= lpFilterDamping;
                            }
                            else
                            {
                                lpFilterPos      = sample;
                                lpFilterDeltaPos = 0.0f;
                            }

                            lpFilterPos += lpFilterDeltaPos;

                            hpFilterPos += lpFilterPos - lpFilterOldPos;
                            hpFilterPos *= 1.0f - hpFilterCutoff;
                            sample       = hpFilterPos;
                        }

                        // Applies the phaser effect
                        if (phaser)
                        {
                            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 = masterVolume * envelopeVolume * superSample * 0.125f;

                    // Clipping if too loud
                    if (superSample > 1.0f)
                    {
                        superSample = 1.0f;
                    }
                    else if (superSample < -1.0f)
                    {
                        superSample = -1.0f;
                    }

                    buffer.samples[counter] = (float)superSample;
                    _currentSynthesizedSample++;
                }

                _synthesizedBlocks.Enqueue(buffer);
            }

            //return new SoundEffect(byteSamples, 44100, AudioChannels.Mono);
            this.IsCached      = true;
            this.IsReadyToPlay = true;

            _currentSynthesizedSample = 0;
        }