public void Start(RegionPair region, int channel, int key, int velocity) { this.exclusiveClass = region.ExclusiveClass; this.channel = channel; this.key = key; this.velocity = velocity; if (velocity > 0) { // According to the Polyphone's implementation, the initial attenuation should be reduced to 40%. // I'm not sure why, but this indeed improves the loudness variability. var sampleAttenuation = 0.4F * region.InitialAttenuation; var filterAttenuation = 0.5F * region.InitialFilterQ; var decibels = 2 * SoundFontMath.LinearToDecibels(velocity / 127F) - sampleAttenuation - filterAttenuation; noteGain = SoundFontMath.DecibelsToLinear(decibels); } else { noteGain = 0F; } cutoff = region.InitialFilterCutoffFrequency; resonance = SoundFontMath.DecibelsToLinear(region.InitialFilterQ); vibLfoToPitch = 0.01F * region.VibratoLfoToPitch; modLfoToPitch = 0.01F * region.ModulationLfoToPitch; modEnvToPitch = 0.01F * region.ModulationEnvelopeToPitch; modLfoToCutoff = region.ModulationLfoToFilterCutoffFrequency; modEnvToCutoff = region.ModulationEnvelopeToFilterCutoffFrequency; dynamicCutoff = modLfoToCutoff != 0 || modEnvToCutoff != 0; modLfoToVolume = region.ModulationLfoToVolume; dynamicVolume = modLfoToVolume > 0.05F; instrumentPan = SoundFontMath.Clamp(region.Pan, -50F, 50F); instrumentReverb = 0.01F * region.ReverbEffectsSend; instrumentChorus = 0.01F * region.ChorusEffectsSend; volEnv.Start(region, key, velocity); modEnv.Start(region, key, velocity); vibLfo.StartVibrato(region, key, velocity); modLfo.StartModulation(region, key, velocity); oscillator.Start(synthesizer.SoundFont.WaveDataArray, region); filter.ClearBuffer(); filter.SetLowPassFilter(cutoff, resonance); smoothedCutoff = cutoff; voiceState = VoiceState.Playing; voiceLength = 0; }
public static void Start(this ModulationEnvelope envelope, RegionPair region, int key, int velocity) { // According to the implementation of TinySoundFont, the attack time should be adjusted by the velocity. var delay = region.DelayModulationEnvelope; var attack = region.AttackModulationEnvelope * ((145 - velocity) / 144F); var hold = region.HoldModulationEnvelope * SoundFontMath.KeyNumberToMultiplyingFactor(region.KeyNumberToModulationEnvelopeHold, key); var decay = region.DecayModulationEnvelope * SoundFontMath.KeyNumberToMultiplyingFactor(region.KeyNumberToModulationEnvelopeDecay, key); var sustain = 1F - region.SustainModulationEnvelope / 100F; var release = region.ReleaseModulationEnvelope; envelope.Start(delay, attack, hold, decay, sustain, release); }