public void EnvToSecs(bool sustainIsGain) { // EG times need to be converted from timecents to seconds. // Pin very short EG segments. Timecents don't get to zero, and our EG is // happier with zero values. Delay = (Delay < -11950.0f ? 0.0f : SynthHelper.Timecents2Secs(Delay)); Attack = (Attack < -11950.0f ? 0.0f : SynthHelper.Timecents2Secs(Attack)); Release = (Release < -11950.0f ? 0.0f : SynthHelper.Timecents2Secs(Release)); // If we have dynamic hold or decay times depending on key number we need // to keep the values in timecents so we can calculate it during startNote if (KeynumToHold == 0) { Hold = (Hold < -11950.0f ? 0.0f : SynthHelper.Timecents2Secs(Hold)); } if (KeynumToDecay == 0) { Decay = (Decay < -11950.0f ? 0.0f : SynthHelper.Timecents2Secs(Decay)); } if (Sustain < 0.0f) { Sustain = 0.0f; } else if (sustainIsGain) { Sustain = SynthHelper.DecibelsToGain(-Sustain / 10.0f); } else { Sustain = 1.0f - (Sustain / 1000.0f); } }
private void LoadFilter(Sf2Region region) { fltr = new FilterDescriptor(); fltr.FilterMethod = FilterTypeEnum.BiquadLowpass; fltr.CutOff = (float)SynthHelper.KeyToFrequency(region.Generators[(int)GeneratorEnum.InitialFilterCutoffFrequency] / 100.0, 69); fltr.Resonance = (float)SynthHelper.DBtoLinear(region.Generators[(int)GeneratorEnum.InitialFilterQ] / 10.0); }
public override bool Start(VoiceParameters voiceparams) { //calculate velocity float fVel = voiceparams.velocity / 127f; //setup generator voiceparams.generatorParams[0].QuickSetup(voiceparams.generators[0]); //setup envelopes voiceparams.envelopes[0].QuickSetup(voiceparams.synth.SampleRate, fVel, this.EnvelopeInfo[0]); voiceparams.envelopes[1].QuickSetup(voiceparams.synth.SampleRate, fVel, this.EnvelopeInfo[1]); voiceparams.envelopes[2].QuickSetup(voiceparams.synth.SampleRate, fVel, this.EnvelopeInfo[2]); //setup lfos voiceparams.lfos[0].QuickSetup(voiceparams.synth.SampleRate, LfoInfo[0]); voiceparams.lfos[1].QuickSetup(voiceparams.synth.SampleRate, LfoInfo[1]); voiceparams.lfos[2].QuickSetup(voiceparams.synth.SampleRate, LfoInfo[2]); //setup filter voiceparams.filters[0].QuickSetup(voiceparams.synth.SampleRate, voiceparams.note, fVel, this.FilterInfo[0]); if (!voiceparams.filters[0].Enabled) {//disable filter components if necessary voiceparams.envelopes[1].Depth = 0f; voiceparams.lfos[1].Depth = 0f; } //setup sfz params voiceparams.pitchOffset = (voiceparams.note - voiceparams.generators[0].RootKey) * voiceparams.generators[0].KeyTrack + (int)(fVel * voiceparams.generators[0].VelocityTrack) + voiceparams.generators[0].Tune; float dBVel = -20.0f * (float)Math.Log10(16129.0 / (voiceparams.velocity * voiceparams.velocity)); voiceparams.volOffset = (float)SynthHelper.DBtoLinear((voiceparams.note - ampRootKey) * ampKeyTrack + dBVel * ampVelTrack + sfzVolume) * voiceparams.synth.MixGain; //check if we have finished before we have begun return(voiceparams.generatorParams[0].currentState != GeneratorStateEnum.Finished && voiceparams.envelopes[2].CurrentState != EnvelopeStateEnum.None); }
private void clampArray(double[] array) { for (int x = 0; x < array.Length; x++) { array[x] = SynthHelper.Clamp(array[x], 0.0, 1.0); } }
public override float getSampleAtTime(int note, int channel, int synthSampleRate, ref double time) { double freq = SynthHelper.NoteToFrequency(note); double delta = (1.0 / freq); //Position in wave form in 2PI * (time* frequency) if (time >= delta) //Waveform repeates at 1.0 / freq { time = time % delta; } switch (type) { case SynthHelper.WaveFormType.Sine: return(SynthHelper.Sine(freq, time) * SynthHelper.DEFAULT_AMPLITUDE); case SynthHelper.WaveFormType.Sawtooth: return(SynthHelper.Sawtooth(freq, time) * SynthHelper.DEFAULT_AMPLITUDE); case SynthHelper.WaveFormType.Square: return(SynthHelper.Square(freq, time) * SynthHelper.DEFAULT_AMPLITUDE); case SynthHelper.WaveFormType.Triangle: return(SynthHelper.Triangle(freq, time) * SynthHelper.DEFAULT_AMPLITUDE); case SynthHelper.WaveFormType.WhiteNoise: return(SynthHelper.WhiteNoise(note, time) * SynthHelper.DEFAULT_AMPLITUDE); default: return(0.0f); } }
public void Load(Sf2Region region, AssetManager assets) { this.exGroup = region.Generators[(int)GeneratorEnum.ExclusiveClass]; this.exTarget = exGroup; iniFilterFc = region.Generators[(int)GeneratorEnum.InitialFilterCutoffFrequency]; filterQ = SynthHelper.DBtoLinear(region.Generators[(int)GeneratorEnum.InitialFilterQ] / 10.0); initialAttn = -region.Generators[(int)GeneratorEnum.InitialAttenuation] / 10f; keyOverride = region.Generators[(int)GeneratorEnum.KeyNumber]; velOverride = region.Generators[(int)GeneratorEnum.Velocity]; keynumToModEnvHold = region.Generators[(int)GeneratorEnum.KeyNumberToModulationEnvelopeHold]; keynumToModEnvDecay = region.Generators[(int)GeneratorEnum.KeyNumberToModulationEnvelopeDecay]; keynumToVolEnvHold = region.Generators[(int)GeneratorEnum.KeyNumberToVolumeEnvelopeHold]; keynumToVolEnvDecay = region.Generators[(int)GeneratorEnum.KeyNumberToVolumeEnvelopeDecay]; pan = new PanComponent(region.Generators[(int)GeneratorEnum.Pan] / 500f, PanFormulaEnum.Neg3dBCenter); modLfoToPitch = region.Generators[(int)GeneratorEnum.ModulationLFOToPitch]; vibLfoToPitch = region.Generators[(int)GeneratorEnum.VibratoLFOToPitch]; modEnvToPitch = region.Generators[(int)GeneratorEnum.ModulationEnvelopeToPitch]; modLfoToFilterFc = region.Generators[(int)GeneratorEnum.ModulationLFOToFilterCutoffFrequency]; modEnvToFilterFc = region.Generators[(int)GeneratorEnum.ModulationEnvelopeToFilterCutoffFrequency]; modLfoToVolume = region.Generators[(int)GeneratorEnum.ModulationLFOToVolume] / 10f; LoadGen(region, assets); LoadEnvelopes(region); LoadLfos(region); LoadFilter(region); }
public void SetValue(float value, PanFormulaEnum formula) { value = SynthHelper.ClampF(value, -1, 1); double dvalue; switch (formula) { case PanFormulaEnum.Neg3dBCenter: dvalue = SynthConstants.HalfPi * (value + 1) / 2.0; Left = (float)Math.Cos(dvalue); Right = (float)Math.Sin(dvalue); break; case PanFormulaEnum.Neg6dBCenter: Left = (float)(.5 + value * -.5); Right = (float)(.5 + value * .5); break; case PanFormulaEnum.ZeroCenter: dvalue = SynthConstants.HalfPi * (value + 1.0) / 2.0; Left = (float)(Math.Cos(dvalue) / SynthConstants.InverseSqrtOfTwo); Right = (float)(Math.Sin(dvalue) / SynthConstants.InverseSqrtOfTwo); break; default: throw new Exception("Invalid pan law selected."); } }
public override bool Start(VoiceParameters voiceparams) { int note = keyOverride > -1 ? keyOverride : voiceparams.note; int vel = velOverride > -1 ? velOverride : voiceparams.velocity; //setup generator voiceparams.generatorParams[0].QuickSetup(voiceparams.generators[0]); //setup envelopes voiceparams.envelopes[0].QuickSetup(voiceparams.synth.SampleRate, note, keynumToModEnvHold, keynumToModEnvDecay, 1, this.EnvelopeInfo[0]); float susMod = (float)SynthHelper.DBtoLinear(-sustainVolEnv); if (susMod <= 1e-5f) { susMod = 0; } voiceparams.envelopes[1].QuickSetup(voiceparams.synth.SampleRate, note, keynumToVolEnvHold, keynumToVolEnvDecay, susMod, this.EnvelopeInfo[1]); //setup filter //if (filterQ == 1 && modLfoToFilterFc + modEnvToFilterFc + iniFilterFc > 14000) voiceparams.filters[0].Disable(); //else // voiceparams.filters[0].QuickSetup(44100, note, 1f, this.FilterInfo[0]); //setup lfos voiceparams.lfos[0].QuickSetup(voiceparams.synth.SampleRate, LfoInfo[0]); voiceparams.lfos[1].QuickSetup(voiceparams.synth.SampleRate, LfoInfo[1]); //calculate base volume and pitch voiceparams.pitchOffset = (note - voiceparams.generators[0].RootKey) * voiceparams.generators[0].KeyTrack + voiceparams.generators[0].Tune; voiceparams.volOffset = -20.0f * (float)Math.Log10(16129.0 / (vel * vel)) + -initialAttn; //check if we have finished before we have begun return(voiceparams.generatorParams[0].currentState != GeneratorStateEnum.Finished && voiceparams.envelopes[1].CurrentState != EnvelopeStateEnum.None); }
private void loadProgramFile(string file) { //StreamReader reader = new StreamReader(File.Open(file, FileMode.Open)); StreamReader reader = new StreamReader(Application.GetResourceStream(new Uri(file, UriKind.Relative)).Stream); if (!reader.ReadLine().Trim().ToUpper().Equals("[FM INSTRUMENT]")) { reader.Close(); throw new InvalidDataException("Invalid Program file: Incorrect Header!"); } string[] args = reader.ReadLine().Split(new string[] { "|" }, StringSplitOptions.None); if (args.Length < 4) { reader.Close(); throw new InvalidDataException("Invalid Program file: Parameters are missing"); } this.baseWaveType = SynthHelper.getTypeFromString(args[0]); this.modWaveType = SynthHelper.getTypeFromString(args[1]); this.mfreq = getOpsAndValues(args[2], true); this.mamp = getOpsAndValues(args[3], false); args = reader.ReadLine().Split(new string[] { "|" }, StringSplitOptions.None); if (args.Length < 3) { reader.Close(); throw new InvalidDataException("Invalid Program file: Parameters are missing"); } if (int.Parse(args[0]) == 0) { looping = true; } start_time = double.Parse(args[1]); end_time = double.Parse(args[2]); args = reader.ReadLine().Split(new string[] { "|" }, StringSplitOptions.None); if (args.Length < 3) { reader.Close(); throw new InvalidDataException("Invalid Program file: Parameters are missing"); } switch (args[0].ToLower().Trim()) { case "fadein": env = Envelope.CreateBasicFadeIn(double.Parse(args[2])); break; case "fadeout": env = Envelope.CreateBasicFadeOut(double.Parse(args[2])); break; case "fadein&out": double p = double.Parse(args[2]) / 2.0; env = Envelope.CreateBasicFadeInAndOut(p, p); break; default: env = Envelope.CreateBasicConstant(); break; } env.Peak = double.Parse(args[1]); reader.Close(); }
public override float getSampleAtTime(int note, int channel, int synthSampleRate, ref double time) { double freq = SynthHelper.NoteToFrequency(note); if (freq * time > 1.0) { time = 0.0; } switch (type) { case SynthHelper.WaveFormType.Sine: return(SynthHelper.Sine(freq, time) * SynthHelper.DEFAULT_AMPLITUDE); case SynthHelper.WaveFormType.Sawtooth: return(SynthHelper.Sawtooth(freq, time) * SynthHelper.DEFAULT_AMPLITUDE); case SynthHelper.WaveFormType.Square: return(SynthHelper.Square(freq, time) * SynthHelper.DEFAULT_AMPLITUDE); case SynthHelper.WaveFormType.Triangle: return(SynthHelper.Triangle(freq, time) * SynthHelper.DEFAULT_AMPLITUDE); case SynthHelper.WaveFormType.WhiteNoise: return(SynthHelper.WhiteNoise(note, time) * SynthHelper.DEFAULT_AMPLITUDE); default: return(0.0f); } }
private void loadProgramFile(string file) { StreamReader reader = new StreamReader(PlatformHelper.StreamLoad(file)); if (!reader.ReadLine().Trim().ToUpper().Equals("[FM INSTRUMENT]")) { reader.Close(); throw new Exception("Invalid Program file: Incorrect Header!"); } string[] args = reader.ReadLine().Split(new string[] { "|" }, StringSplitOptions.None); if (args.Length < 4) { reader.Close(); throw new Exception("Invalid Program file: Parameters are missing"); } this.baseWaveType = SynthHelper.getTypeFromString(args[0]); this.modWaveType = SynthHelper.getTypeFromString(args[1]); this.mfreq = (ModulatorFrequencyFunction)getOpsAndValues(args[2], true); this.mamp = (ModulatorAmplitudeFunction)getOpsAndValues(args[3], false); args = reader.ReadLine().Split(new string[] { "|" }, StringSplitOptions.None); if (args.Length < 3) { reader.Close(); throw new Exception("Invalid Program file: Parameters are missing"); } if (int.Parse(args[0]) == 0) { looping = true; } start_time = double.Parse(args[1]); end_time = double.Parse(args[2]); args = reader.ReadLine().Split(new string[] { "|" }, StringSplitOptions.None); if (args.Length < 3) { reader.Close(); throw new Exception("Invalid Program file: Parameters are missing"); } switch (args[0].ToLower().Trim()) { case "fadein": env = Envelope.CreateBasicFadeIn(double.Parse(args[2])); break; case "fadeout": env = Envelope.CreateBasicFadeOut(double.Parse(args[2])); break; case "fadein&out": double p = double.Parse(args[2]) / 2.0; env = Envelope.CreateBasicFadeInAndOut(p, p); break; default: env = Envelope.CreateBasicConstant(); break; } env.Peak = double.Parse(args[1]); reader.Close(); }
public override void Process(VoiceParameters voiceparams, int startIndex, int endIndex, bool isMuted) { //--Base pitch calculation var basePitchFrequency = SynthHelper.CentsToPitch(voiceparams.SynthParams.CurrentPitch) * gen.Frequency; var pitchWithBend = basePitchFrequency * SynthHelper.CentsToPitch(voiceparams.PitchOffset); var basePitch = pitchWithBend / voiceparams.SynthParams.Synth.SampleRate; float baseVolume = isMuted ? 0 : voiceparams.SynthParams.Synth.MasterVolume * voiceparams.SynthParams.CurrentVolume * SynthConstants.DefaultMixGain * voiceparams.SynthParams.MixVolume; //--Main Loop for (int x = startIndex; x < endIndex; x += SynthConstants.DefaultBlockSize * SynthConstants.AudioChannels) { voiceparams.Envelopes[0].Increment(SynthConstants.DefaultBlockSize); voiceparams.Envelopes[1].Increment(SynthConstants.DefaultBlockSize); voiceparams.Lfos[0].Increment(SynthConstants.DefaultBlockSize); voiceparams.Lfos[1].Increment(SynthConstants.DefaultBlockSize); //--Calculate pitch and get next block of samples gen.GetValues(voiceparams.GeneratorParams[0], voiceparams.BlockBuffer, basePitch * SynthHelper.CentsToPitch((int)(voiceparams.Envelopes[0].Value * modEnvToPitch + voiceparams.Lfos[0].Value * modLfoToPitch + voiceparams.Lfos[1].Value * vibLfoToPitch))); //--Filter if (voiceparams.Filters[0].Enabled) { double centsFc = voiceparams.PData[0].Int1 + voiceparams.Lfos[0].Value * modLfoToFilterFc + voiceparams.Envelopes[0].Value * modEnvToFilterFc; if (centsFc > 13500) { centsFc = 13500; } voiceparams.Filters[0].CutOff = SynthHelper.KeyToFrequency(centsFc / 100.0, 69); if (voiceparams.Filters[0].CoeffNeedsUpdating) { voiceparams.Filters[0].ApplyFilterInterp(voiceparams.BlockBuffer, voiceparams.SynthParams.Synth.SampleRate); } else { voiceparams.Filters[0].ApplyFilter(voiceparams.BlockBuffer); } } //--Volume calculation float volume = (float)SynthHelper.DBtoLinear(voiceparams.VolOffset + voiceparams.Envelopes[1].Value + voiceparams.Lfos[0].Value * modLfoToVolume) * baseVolume; //--Mix block based on number of channels if (SynthConstants.AudioChannels == 2) { voiceparams.MixMonoToStereoInterp(x, volume * pan.Left * voiceparams.SynthParams.CurrentPan.Left, volume * pan.Right * voiceparams.SynthParams.CurrentPan.Right); } else { voiceparams.MixMonoToMonoInterp(x, volume); } //--Check and end early if necessary if ((voiceparams.Envelopes[1].CurrentStage > EnvelopeState.Hold && volume <= SynthConstants.NonAudible) || voiceparams.GeneratorParams[0].CurrentState == GeneratorState.Finished) { voiceparams.State = VoiceStateEnum.Stopped; return; } } }
/*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); }
private void LoadSfzFilters(SfzRegion region) { FilterDescriptions = new FilterDescriptor[1]; FilterDescriptions[0] = new FilterDescriptor(); FilterDescriptions[0].FilterMethod = region.filterType; FilterDescriptions[0].CutOff = region.cutOff; FilterDescriptions[0].KeyTrack = region.filterKeyTrack; FilterDescriptions[0].Resonance = (float)SynthHelper.DBtoLinear(region.resonance); FilterDescriptions[0].RootKey = region.filterKeyCenter; FilterDescriptions[0].VelTrack = region.filterVelTrack; }
//--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); }
public override void Process(VoiceParameters voiceparams, int startIndex, int endIndex) { //--Base pitch calculation double basePitch = SynthHelper.CentsToPitch(voiceparams.pitchOffset + voiceparams.synth.totalPitch[voiceparams.channel]) * voiceparams.generators[0].Frequency / voiceparams.synth.SampleRate; //--Base volume calculation //float baseVolume = voiceparams.volOffset * voiceparams.synth.totalVolume[voiceparams.channel]; //--Main Loop for (int x = startIndex; x < endIndex; x += Synthesizer.DefaultBlockSize * voiceparams.synth.AudioChannels) { voiceparams.envelopes[0].Increment(Synthesizer.DefaultBlockSize); voiceparams.envelopes[1].Increment(Synthesizer.DefaultBlockSize); voiceparams.lfos[0].Increment(Synthesizer.DefaultBlockSize); voiceparams.lfos[1].Increment(Synthesizer.DefaultBlockSize); //--Calculate pitch and get next block of samples voiceparams.generators[0].GetValues(voiceparams.generatorParams[0], voiceparams.blockBuffer, basePitch * SynthHelper.CentsToPitch((int)(voiceparams.envelopes[0].Value * modEnvToPitch + voiceparams.lfos[0].Value * modLfoToPitch + voiceparams.lfos[1].Value * vibLfoToPitch))); //--Filter if (voiceparams.filters[0].Enabled) { double centsFc = iniFilterFc + voiceparams.lfos[0].Value * modLfoToFilterFc + voiceparams.envelopes[0].Value * modEnvToFilterFc; if (centsFc > 13500) { centsFc = 13500; } voiceparams.filters[0].UpdateCoefficients(SynthHelper.KeyToFrequency(centsFc / 100.0, 69) / voiceparams.synth.SampleRate, filterQ); voiceparams.filters[0].ApplyFilter(voiceparams.blockBuffer); } //--Volume calculation float volume = (float)SynthHelper.DBtoLinear(voiceparams.volOffset + voiceparams.lfos[0].Value * modLfoToVolume) * voiceparams.envelopes[1].Value * voiceparams.synth.totalVolume[voiceparams.channel] * voiceparams.synth.MixGain; //--Mix block based on number of channels if (voiceparams.synth.AudioChannels == 2) { SynthHelper.MixMonoToStereoInterpolation(x, volume * pan.Left * voiceparams.synth.panPositions[voiceparams.channel].Left, volume * pan.Right * voiceparams.synth.panPositions[voiceparams.channel].Right, voiceparams); } else { SynthHelper.MixMonoToMonoInterpolation(x, volume, voiceparams); } //--Check and end early if necessary if ((voiceparams.envelopes[1].CurrentState > EnvelopeStateEnum.Hold && volume <= Synthesizer.NonAudible) || voiceparams.generatorParams[0].currentState == GeneratorStateEnum.Finished) { voiceparams.state = VoiceStateEnum.Stopped; return; } } }
public override void enforceSampleRate(int sampleRate) { if (sampleRate != this.SampleRate) { //Proper calculation of voice states _attack = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_ATTACK); _release = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_RELEASE); _decay = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_DECAY); _hold = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_HOLD); this.SampleRate = sampleRate; } }
protected PcmData(int bits, byte[] pcmData, bool isDataInLittleEndianFormat) { BytesPerSample = (byte)(bits / 8); //if (pcmData.Length % BytesPerSample != 0) // throw new Exception("Invalid PCM format. The PCM data was an invalid size."); Data = pcmData; Length = Data.Length / BytesPerSample; if (!isDataInLittleEndianFormat) { SynthHelper.SwapEndianess(Data, bits); } }
public void CalcPitchRatio(float pitchShift, float outSampleRate) { var note = PlayingKey + Region.Transpose + Region.Tune / 100.0; var adjustedPitch = Region.PitchKeyCenter + (note - Region.PitchKeyCenter) * (Region.PitchKeyTrack / 100.0); if (pitchShift != 0) { adjustedPitch += pitchShift; } PitchInputTimecents = adjustedPitch * 100.0; PitchOutputFactor = Region.SampleRate / (SynthHelper.Timecents2Secs(Region.PitchKeyCenter * 100.0) * outSampleRate); }
private void updateTimeControls(int current, int max) { max = (int)SynthHelper.TimeFromSamples(Properties.Settings.Default.SampleRate, max); current = (int)SynthHelper.TimeFromSamples(Properties.Settings.Default.SampleRate, current); current = Math.Min(max, current); if (trackBar1.Maximum != max) { trackBar1.Maximum = max; trackBar1.TickFrequency = Math.Max(1, trackBar1.Maximum / 20); } trackBar1.Value = current; label1.Text = new TimeSpan(0, 0, current).ToString(@"mm\:ss") + "/" + new TimeSpan(0, 0, max).ToString(@"mm\:ss"); }
//--Public Methods public FMInstrument(string fmProgramFile, int sampleRate) : base() { this.SampleRate = sampleRate; //Proper calculation of voice states _attack = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_ATTACK); _release = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_RELEASE); _decay = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_DECAY); _hold = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_HOLD); //open fm program file loadProgramFile(fmProgramFile); //set base attribute name base.Name = System.IO.Path.GetFileNameWithoutExtension(fmProgramFile); }
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); }
//--Public Methods public AnalogInstrument(SynthHelper.WaveFormType waveformtype, int sampleRate) : base() { //set type this.type = waveformtype; this.SampleRate = sampleRate; //Proper calculation of voice states _attack = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_ATTACK); _release = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_RELEASE); _decay = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_DECAY); _hold = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_HOLD); //set base attribute name base.Name = waveformtype.ToString(); }
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); }
private void LoadSfzLfos(SfzRegion region) { LfoDescriptions = new LfoDescriptor[3]; LfoDescriptions[0] = new LfoDescriptor(); LfoDescriptions[0].DelayTime = region.pitchLfoDelay; //make sure pitch lfo is enabled for midi mod event LfoDescriptions[0].Frequency = region.pitchLfoFrequency > 0 ? region.pitchLfoFrequency : (float)Synthesizer.DefaultLfoFrequency; LfoDescriptions[0].Depth = region.pitchLfoDepth; LfoDescriptions[1] = new LfoDescriptor(); LfoDescriptions[1].DelayTime = region.filterLfoDelay; LfoDescriptions[1].Frequency = region.filterLfoFrequency; LfoDescriptions[1].Depth = region.filterLfoDepth; LfoDescriptions[2] = new LfoDescriptor(); LfoDescriptions[2].DelayTime = region.ampLfoDelay; LfoDescriptions[2].Frequency = region.ampLfoFrequency; LfoDescriptions[2].Depth = (float)SynthHelper.DBtoLinear(region.ampLfoDepth); }
public override void Process(VoiceParameters voiceparams, int startIndex, int endIndex) { //--Base pitch calculation double basePitch = SynthHelper.CentsToPitch(voiceparams.pitchOffset + voiceparams.synthParams.currentPitch) * gen.Period * gen.Frequency / voiceparams.synthParams.synth.SampleRate; //--Base volume calculation float baseVolume = voiceparams.volOffset * voiceparams.synthParams.currentVolume; //--Main Loop for (int x = startIndex; x < endIndex; x += Synthesizer.DefaultBlockSize * voiceparams.synthParams.synth.AudioChannels) { //--Volume Envelope voiceparams.envelopes[0].Increment(Synthesizer.DefaultBlockSize); //--Lfo pitch modulation double pitchMod; if (voiceparams.synthParams.modRange.Combined != 0) { voiceparams.lfos[0].Increment(Synthesizer.DefaultBlockSize); pitchMod = SynthHelper.CentsToPitch((int)(voiceparams.lfos[0].Value * voiceparams.synthParams.currentMod)); } else { pitchMod = 1; } //--Get next block of samples gen.GetValues(voiceparams.generatorParams[0], voiceparams.blockBuffer, basePitch * pitchMod); //--Mix block based on number of channels float volume = baseVolume * voiceparams.envelopes[0].Value; if (voiceparams.synthParams.synth.AudioChannels == 2) { voiceparams.MixMonoToStereoInterp(x, volume * voiceparams.synthParams.currentPan.Left, volume * voiceparams.synthParams.currentPan.Right); } else { voiceparams.MixMonoToMonoInterp(x, volume); } //--Check and end early if necessary if (voiceparams.envelopes[0].CurrentState == EnvelopeStateEnum.None || voiceparams.generatorParams[0].currentState == GeneratorStateEnum.Finished) { voiceparams.state = VoiceStateEnum.Stopped; return; } } }
//--Public Methods public FMInstrument(string fmProgramFile, int sampleRate) : base() { this.SampleRate = sampleRate; //Proper calculation of voice states _attack = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_ATTACK); _release = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_RELEASE); _decay = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_DECAY); _hold = SynthHelper.getSampleFromTime(sampleRate, SynthHelper.DEFAULT_HOLD); //open fm program file loadProgramFile(fmProgramFile); //set base attribute name //base.Name = System.IO.Path.GetFileNameWithoutExtension(fmProgramFile); System.Diagnostics.Debug.WriteLine(fmProgramFile.LastIndexOf("/")); System.Diagnostics.Debug.WriteLine(fmProgramFile.Length); base.Name = fmProgramFile.Substring(fmProgramFile.LastIndexOf("/"), fmProgramFile.Length - fmProgramFile.LastIndexOf("/")); }
private static SampleArray CreateExponentialTable(int size, float coeff) { coeff = SynthHelper.ClampF(coeff, .001f, .9f); var graph = new SampleArray(size); var val = 0.0; for (int x = 0; x < size; x++) { graph[x] = (float)val; val += coeff * ((1 / 0.63) - val); } for (int x = 0; x < size; x++) { graph[x] = graph[x] / graph[graph.Length - 1]; } return(graph); }
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) { coeffUpdateRequired = false; cutOff = filterInfo.CutOff; resonance = filterInfo.Resonance; filterType = filterInfo.FilterMethod; a1 = 0; a2 = 0; b1 = 0; b2 = 0; m1 = 0f; m2 = 0f; m3 = 0f; if (cutOff <= 0 || resonance <= 0) { filterType = FilterTypeEnum.None; } if (filterType != FilterTypeEnum.None) { cutOff *= SynthHelper.CentsToPitch((note - filterInfo.RootKey) * filterInfo.KeyTrack + (int)(velocity * filterInfo.VelTrack)); UpdateCoeff(sampleRate); } }