예제 #1
0
 private void clampArray(double[] array)
 {
     for (int x = 0; x < array.Length; x++)
     {
         array[x] = SynthHelper.Clamp(array[x], 0.0, 1.0);
     }
 }
예제 #2
0
 /*change time stretch parameters*/
 public void Configure(double timeScale, double sequenceSec, double overlapSec, double windowSec, int sampleRate)
 {
     time_scale    = SynthHelper.Clamp(timeScale, 0.0, 2.0);
     sequence_size = (int)SynthHelper.SamplesFromTime(sampleRate, sequenceSec);
     overlap_size  = (int)SynthHelper.SamplesFromTime(sampleRate, overlapSec);
     seek_window   = (int)SynthHelper.SamplesFromTime(sampleRate, windowSec);
     flat_duration = sequence_size - 2 * overlap_size;
     flat_duration = sequence_size - 2 * overlap_size;
     sequence_skip = (int)((sequence_size - overlap_size) * time_scale);
 }
예제 #3
0
파일: Echo.cs 프로젝트: zzbin6210/BlockFun
 //--Public Methods
 /// <summary>
 /// A simple echo effect.
 /// </summary>
 /// <param name="synth">A constructed synthesizer instance.</param>
 /// <param name="delaytime">Echo delay in seconds.</param>
 /// <param name="decay">Controls the volume of the echo.</param>
 public Echo(StreamSynthesizer synth, float delaytime, float decay)
     : base()
 {
     if (delaytime <= 0.0f)
     {
         throw new ArgumentException("delay time must be positive non-zero for echo effect.");
     }
     this.decay         = SynthHelper.Clamp(decay, 0.0f, 1.0f);
     this.EffectBuffer  = new float[synth.Channels, SynthHelper.getSampleFromTime(synth.SampleRate, delaytime)];
     channels           = this.EffectBuffer.GetLength(0);
     secondarybufferlen = this.EffectBuffer.GetLength(1);
 }
예제 #4
0
 private void CheckValidParameters()
 {
     //limit cutoff
     if (CutOff <= 0)
     {
         FilterMethod = FilterTypeEnum.None;
     }
     if (RootKey < 0 || RootKey > 127)
     {
         RootKey = 60;
     }
     KeyTrack = SynthHelper.Clamp(KeyTrack, (short)0, (short)1200);
     VelTrack = SynthHelper.Clamp(VelTrack, (short)-9600, (short)9600);
 }
예제 #5
0
 private void CheckValidParameters()
 {
     //release must be with min and max
     ReleaseTime = SynthHelper.Clamp(ReleaseTime, 0.001f, 2.0f);
     //positive only checks
     DelayTime    = Math.Max(DelayTime, 0f);
     AttackTime   = Math.Max(AttackTime, 0f);
     HoldTime     = Math.Max(HoldTime, 0f);
     DecayTime    = Math.Max(DecayTime, 0f);
     SustainTime  = Math.Max(SustainTime, 0);
     ReleaseTime  = Math.Max(ReleaseTime, 0f);
     SustainLevel = Math.Max(SustainLevel, 0f);
     PeakLevel    = Math.Max(PeakLevel, 0f);
     StartLevel   = SynthHelper.Clamp(StartLevel, 0, PeakLevel);
 }
예제 #6
0
        public static float[] CreateExponentialTable(int size, double coeff)
        {
            coeff = SynthHelper.Clamp(coeff, .001, .9);
            float[] graph = new float[size];
            double  val   = 0;

            for (int x = 0; x < graph.Length; x++)
            {
                graph[x] = (float)val;
                val     += coeff * ((1 / 0.63) - val);
            }
            for (int x = 0; x < graph.Length; x++)
            {
                graph[x] = graph[x] / graph[graph.Length - 1];
            }
            return(graph);
        }
예제 #7
0
 public void QuickSetup(int sampleRate, int note, float velocity, FilterDescriptor filterInfo)
 {
     cutOff     = filterInfo.CutOff;
     resonance  = filterInfo.Resonance;
     filterType = filterInfo.FilterMethod;
     lastFc     = -1000;
     m1         = 0f;
     m2         = 0f;
     m3         = 0f;
     if (filterType == FilterTypeEnum.None || cutOff <= 0.0 || resonance <= 0.0)
     {
         filterType = FilterTypeEnum.None;
     }
     else
     {
         double fc = cutOff * SynthHelper.CentsToPitch((note - filterInfo.RootKey) * filterInfo.KeyTrack + (int)(velocity * filterInfo.VelTrack));
         UpdateCoefficients(SynthHelper.Clamp(fc / sampleRate, 0, .5), resonance);
     }
 }
예제 #8
0
        public static float[] CreateSquareTable(int size, int k)
        {//Uses Fourier Expansion up to k terms
            const double FOUR_OVER_PI = 4 / Math.PI;

            float[] squaretable = new float[size];
            double  inc         = 1.0 / size;
            double  phase       = 0;

            for (int x = 0; x < squaretable.Length; x++)
            {
                double value = 0.0;
                for (int i = 1; i <= k; i++)
                {
                    int twokminus1 = (2 * i) - 1;
                    value += Math.Sin(Synthesizer.TwoPi * (twokminus1) * phase) / (twokminus1);
                }
                squaretable[x] = SynthHelper.Clamp((float)(FOUR_OVER_PI * value), -1f, 1f);
                phase         += inc;
            }
            return(squaretable);
        }
예제 #9
0
        //returns raw audio data in little endian form
        private static void ToPcmFromSamples(float[] input, int bitsPerSample, int channels, byte[] output, int index)
        {
            switch (bitsPerSample)
            {
            case 8:
                for (int x = 0; x < input.Length; x++)
                {
                    output[index] = (byte)((input[x] + 1f) / 2f * 255f);
                    index        += channels;
                }
                break;

            case 16:
                for (int x = 0; x < input.Length; x++)
                {
                    LittleEndianHelper.WriteInt16((short)SynthHelper.Clamp(input[x] * 32768f, -32768f, 32767f), output, index);
                    index += channels * 2;
                }
                break;

            case 24:
                for (int x = 0; x < input.Length; x++)
                {
                    LittleEndianHelper.WriteInt24((int)SynthHelper.Clamp(input[x] * 8388608f, -8388608f, 8388607f), output, index);
                    index += channels * 3;
                }
                break;

            case 32:
                for (int x = 0; x < input.Length; x++)
                {
                    LittleEndianHelper.WriteInt32((int)SynthHelper.Clamp(input[x] * 2147483648f, -2147483648f, 2147483647f), output, index);
                    index += channels * 4;
                }
                break;

            default:
                throw new ArgumentException("Invalid bitspersample value. Supported values are 8, 16, 24, and 32.");
            }
        }
예제 #10
0
        //call sparingly inside process to actively update the cutoff and q
        public void UpdateCoefficients(double fc, double q)
        {
            fc = SynthHelper.Clamp(fc, 0, .49);
            if (Math.Abs(lastFc - fc) > .001)
            {
                switch (filterType)
                {
                case FilterTypeEnum.BiquadLowpass:
                    ConfigBiquadLowpass(fc, q);
                    break;

                case FilterTypeEnum.BiquadHighpass:
                    ConfigBiquadHighpass(fc, q);
                    break;

                case FilterTypeEnum.OnePoleLowpass:
                    ConfigOnePoleLowpass(fc);
                    break;
                }
                lastFc = fc;
            }
        }
예제 #11
0
        //--helper methods for coeff update
        private float[] GenerateFilterCoeff(double fc, double q)
        {
            fc = SynthHelper.Clamp(fc, Synthesizer.DenormLimit, .49);
            float[] coeff = new float[4];
            switch (filterType)
            {
            case FilterTypeEnum.BiquadLowpass:
            {
                double w0    = Synthesizer.TwoPi * fc;
                double cosw0 = Math.Cos(w0);
                double alpha = Math.Sin(w0) / (2.0 * q);
                double a0inv = 1.0 / (1.0 + alpha);
                coeff[0] = (float)(-2.0 * cosw0 * a0inv);
                coeff[1] = (float)((1.0 - alpha) * a0inv);
                coeff[2] = (float)((1.0 - cosw0) * a0inv * (1.0 / Math.Sqrt(q)));
                coeff[3] = b1 * 0.5f;
            }
            break;

            case FilterTypeEnum.BiquadHighpass:
            {
                double w0    = Synthesizer.TwoPi * fc;
                double cosw0 = Math.Cos(w0);
                double alpha = Math.Sin(w0) / (2.0 * q);
                double a0inv = 1.0 / (1.0 + alpha);
                double qinv  = 1.0 / Math.Sqrt(q);
                coeff[0] = (float)(-2.0 * cosw0 * a0inv);
                coeff[1] = (float)((1.0 - alpha) * a0inv);
                coeff[2] = (float)((-1.0 - cosw0) * a0inv * qinv);
                coeff[3] = (float)((1.0 + cosw0) * a0inv * qinv * 0.5);
            }
            break;

            case FilterTypeEnum.OnePoleLowpass:
                coeff[0] = 1.0f - (float)Math.Exp(-2.0 * Math.PI * fc);
                break;
            }
            return(coeff);
        }
예제 #12
0
 public void addPoint(double time, double value)
 {
     value = SynthHelper.Clamp(value, 0.0, 1.0);
     if (contains(timePoints, time))
     {
         replace(time, value);
     }
     else
     {
         if (arraylength == timePoints.Length)
         {
             resize();
         }
         timePoints[arraylength] = time;
         valuPoints[arraylength] = value;
         arraylength++;
         if (time > maxTime)
         {
             maxTime = time;
         }
     }
     sort();
 }
예제 #13
0
 private void LoadEnvelopes(Sf2Region region)
 {
     //mod env
     mod_env              = new EnvelopeDescriptor();
     mod_env.AttackTime   = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.AttackModulationEnvelope] / 1200.0);
     mod_env.AttackGraph  = 3;
     mod_env.DecayTime    = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.DecayModulationEnvelope] / 1200.0);
     mod_env.DelayTime    = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.DelayModulationEnvelope] / 1200.0);
     mod_env.HoldTime     = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.HoldModulationEnvelope] / 1200.0);
     mod_env.PeakLevel    = 1;
     mod_env.ReleaseTime  = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.ReleaseModulationEnvelope] / 1200.0);
     mod_env.StartLevel   = 0;
     mod_env.SustainLevel = 1f - SynthHelper.Clamp(region.Generators[(int)GeneratorEnum.SustainModulationEnvelope], (short)0, (short)1000) / 1000f;
     //checks
     if (mod_env.AttackTime < 0.001f)
     {
         mod_env.AttackTime = 0.001f;
     }
     else if (mod_env.AttackTime > 100f)
     {
         mod_env.AttackTime = 100f;
     }
     if (mod_env.DecayTime < 0.001f)
     {
         mod_env.DecayTime = 0;
     }
     else if (mod_env.DecayTime > 100f)
     {
         mod_env.DecayTime = 100f;
     }
     if (mod_env.DelayTime < 0.001f)
     {
         mod_env.DelayTime = 0;
     }
     else if (mod_env.DelayTime > 20f)
     {
         mod_env.DelayTime = 20f;
     }
     if (mod_env.HoldTime < 0.001f)
     {
         mod_env.HoldTime = 0;
     }
     else if (mod_env.HoldTime > 20f)
     {
         mod_env.HoldTime = 20f;
     }
     if (mod_env.ReleaseTime < 0.001f)
     {
         mod_env.ReleaseTime = 0.001f;
     }
     else if (mod_env.ReleaseTime > 100f)
     {
         mod_env.ReleaseTime = 100f;
     }
     //volume env
     vel_env              = new EnvelopeDescriptor();
     vel_env.AttackTime   = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.AttackVolumeEnvelope] / 1200.0);
     vel_env.AttackGraph  = 3;
     vel_env.DecayTime    = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.DecayVolumeEnvelope] / 1200.0);
     vel_env.DelayTime    = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.DelayVolumeEnvelope] / 1200.0);
     vel_env.HoldTime     = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.HoldVolumeEnvelope] / 1200.0);
     vel_env.PeakLevel    = 0;
     vel_env.ReleaseTime  = (float)Math.Pow(2, region.Generators[(int)GeneratorEnum.ReleaseVolumeEnvelope] / 1200.0);
     vel_env.StartLevel   = -100;
     vel_env.SustainLevel = SynthHelper.Clamp(region.Generators[(int)GeneratorEnum.SustainVolumeEnvelope], (short)0, (short)1000) / -10f;
     //checks
     if (vel_env.AttackTime < 0.001f)
     {
         vel_env.AttackTime = 0.001f;
     }
     else if (vel_env.AttackTime > 100f)
     {
         vel_env.AttackTime = 100f;
     }
     if (vel_env.DecayTime < 0.001f)
     {
         vel_env.DecayTime = 0;
     }
     else if (vel_env.DecayTime > 100f)
     {
         vel_env.DecayTime = 100f;
     }
     if (vel_env.DelayTime < 0.001f)
     {
         vel_env.DelayTime = 0;
     }
     else if (vel_env.DelayTime > 20f)
     {
         vel_env.DelayTime = 20f;
     }
     if (vel_env.HoldTime < 0.001f)
     {
         vel_env.HoldTime = 0;
     }
     else if (vel_env.HoldTime > 20f)
     {
         vel_env.HoldTime = 20f;
     }
     if (vel_env.ReleaseTime < 0.001f)
     {
         vel_env.ReleaseTime = 0.001f;
     }
     else if (vel_env.ReleaseTime > 100f)
     {
         vel_env.ReleaseTime = 100f;
     }
 }
예제 #14
0
 private void CheckValidParameters()
 {
     DelayTime = Math.Max(DelayTime, 0);
     Frequency = SynthHelper.Clamp(Frequency, 1e-5f, 20f);
 }