private void clampArray(double[] array) { for (int x = 0; x < array.Length; x++) { array[x] = SynthHelper.Clamp(array[x], 0.0, 1.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); }
//--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); }
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); }
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); }
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); }
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); } }
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); }
//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."); } }
//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; } }
//--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); }
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(); }
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; } }
private void CheckValidParameters() { DelayTime = Math.Max(DelayTime, 0); Frequency = SynthHelper.Clamp(Frequency, 1e-5f, 20f); }