private Source GeneratePCMSource(ushort waveNumber)
        {
            Source source = new Source();

            VelocitySwitchSettings vel = new VelocitySwitchSettings();

            vel.SwitchKind        = VelocitySwitchKind.Off;
            vel.Threshold         = 68;
            source.VelocitySwitch = vel;

            source.Volume.Value       = 120;
            source.KeyOnDelay.Value   = 0;
            source.EffectPath         = EffectPath.Path1;
            source.BenderCutoff.Value = 12;
            source.BenderPitch.Value  = 2;
            source.Pan            = PanKind.Normal;
            source.PanValue.Value = 0;

            // DCO
            source.DCO.Wave         = new Wave(waveNumber);
            source.DCO.Coarse.Value = 0;
            source.DCO.Fine.Value   = 0;
            source.DCO.KSPitch      = KeyScalingToPitch.ZeroCent;
            source.DCO.FixedKey     = new FixedKey(); // OFF

            PitchEnvelope pitchEnv = new PitchEnvelope();

            pitchEnv.StartLevel.Value  = 0;
            pitchEnv.AttackTime.Value  = 4;
            pitchEnv.AttackLevel.Value = 0;
            pitchEnv.DecayTime.Value   = 64;
            pitchEnv.LevelVelocitySensitivity.Value = 0;
            pitchEnv.TimeVelocitySensitivity.Value  = 0;
            source.DCO.Envelope = pitchEnv;

            // DCF
            source.DCF.IsActive        = true;
            source.DCF.Cutoff.Value    = 55;
            source.DCF.Resonance.Value = 0;
            source.DCF.Level.Value     = 7;
            source.DCF.Mode            = FilterMode.LowPass;
            source.DCF.VelocityCurve   = VelocityCurve.Curve5;

            // DCF Envelope
            FilterEnvelope filterEnv = new FilterEnvelope();

            source.DCF.EnvelopeDepth.Value = 25;
            filterEnv.AttackTime.Value     = 0;
            filterEnv.Decay1Time.Value     = 120;
            filterEnv.Decay1Level.Value    = 63;
            filterEnv.Decay2Time.Value     = 80;
            filterEnv.Decay2Level.Value    = 63;
            filterEnv.ReleaseTime.Value    = 20;
            source.DCF.Envelope            = filterEnv;

            // DCF Modulation:
            source.DCF.KeyScalingToEnvelopeAttackTime.Value = 0;
            source.DCF.KeyScalingToEnvelopeDecay1Time.Value = 0;
            source.DCF.VelocityToEnvelopeDepth.Value        = 30;
            source.DCF.VelocityToEnvelopeAttackTime.Value   = 0;
            source.DCF.VelocityToEnvelopeDecay1Time.Value   = 0;

            // DCA Envelope
            AmplifierEnvelope ampEnv = new AmplifierEnvelope();

            ampEnv.AttackTime.Value  = 1;
            ampEnv.Decay1Time.Value  = 94;
            ampEnv.Decay1Level.Value = 127;
            ampEnv.Decay2Time.Value  = 80;
            ampEnv.Decay2Level.Value = 63;
            ampEnv.ReleaseTime.Value = 15;
            source.DCA.Envelope      = ampEnv;

            // DCA Modulation
            source.DCA.KeyScaling.Level.Value       = 0;
            source.DCA.KeyScaling.AttackTime.Value  = 0;
            source.DCA.KeyScaling.Decay1Time.Value  = 0;
            source.DCA.KeyScaling.ReleaseTime.Value = 0;

            source.DCA.VelocitySensitivity.Level.Value       = 20;
            source.DCA.VelocitySensitivity.AttackTime.Value  = 0;
            source.DCA.VelocitySensitivity.Decay1Time.Value  = 0;
            source.DCA.VelocitySensitivity.ReleaseTime.Value = 0;

            return(source);
        }
        private Source GenerateAdditiveSource(string waveformTemplateName, string harmonicLevelTemplateName, string harmonicEnvelopeTemplateName, string formantFilterTemplateName)
        {
            Source source = new Source();

            source.Zone = new Zone(0, 127);
            VelocitySwitchSettings vel = new VelocitySwitchSettings();

            vel.SwitchKind        = VelocitySwitchKind.Off;
            vel.Threshold         = 68;
            source.VelocitySwitch = vel;

            source.Volume.Value       = 120;
            source.KeyOnDelay.Value   = 0;
            source.EffectPath         = EffectPath.Path1;
            source.BenderCutoff.Value = 12;
            source.BenderPitch.Value  = 2;
            source.Pan            = PanKind.Normal;
            source.PanValue.Value = 0;

            // DCO settings for additive source
            source.DCO.Wave         = new Wave(AdditiveKit.WaveNumber);
            source.DCO.Coarse.Value = 0;
            source.DCO.Fine.Value   = 0;
            source.DCO.KSPitch      = KeyScalingToPitch.ZeroCent;
            source.DCO.FixedKey     = new FixedKey(); // OFF

            PitchEnvelope pitchEnv = new PitchEnvelope();

            pitchEnv.StartLevel.Value  = 0;
            pitchEnv.AttackTime.Value  = 4;
            pitchEnv.AttackLevel.Value = 0;
            pitchEnv.DecayTime.Value   = 64;
            pitchEnv.LevelVelocitySensitivity.Value = 0;
            pitchEnv.TimeVelocitySensitivity.Value  = 0;
            source.DCO.Envelope = pitchEnv;

            // DCF
            source.DCF.IsActive        = true;
            source.DCF.Cutoff.Value    = 55;
            source.DCF.Resonance.Value = 0;
            source.DCF.Level.Value     = 7;
            source.DCF.Mode            = FilterMode.LowPass;
            source.DCF.VelocityCurve   = VelocityCurve.Curve5;

            // DCF Envelope
            FilterEnvelope filterEnv = new FilterEnvelope();

            source.DCF.EnvelopeDepth.Value = 25;
            filterEnv.AttackTime.Value     = 0;
            filterEnv.Decay1Time.Value     = 120;
            filterEnv.Decay1Level.Value    = 63;
            filterEnv.Decay2Time.Value     = 80;
            filterEnv.Decay2Level.Value    = 63;
            filterEnv.ReleaseTime.Value    = 20;
            source.DCF.Envelope            = filterEnv;
            // DCF Modulation:
            source.DCF.KeyScalingToEnvelopeAttackTime.Value = 0;
            source.DCF.KeyScalingToEnvelopeDecay1Time.Value = 0;
            source.DCF.VelocityToEnvelopeDepth.Value        = 30;
            source.DCF.VelocityToEnvelopeAttackTime.Value   = 0;
            source.DCF.VelocityToEnvelopeDecay1Time.Value   = 0;

            // DCA Envelope
            AmplifierEnvelope ampEnv = new AmplifierEnvelope();

            ampEnv.AttackTime.Value  = 1;
            ampEnv.Decay1Time.Value  = 94;
            ampEnv.Decay1Level.Value = 127;
            ampEnv.Decay2Time.Value  = 80;
            ampEnv.Decay2Level.Value = 63;
            ampEnv.ReleaseTime.Value = 20;
            source.DCA.Envelope      = ampEnv;

            // DCA Modulation
            source.DCA.KeyScaling.Level.Value       = 0;
            source.DCA.KeyScaling.AttackTime.Value  = 0;
            source.DCA.KeyScaling.Decay1Time.Value  = 0;
            source.DCA.KeyScaling.ReleaseTime.Value = 0;

            source.DCA.VelocitySensitivity.Level.Value       = 20;
            source.DCA.VelocitySensitivity.AttackTime.Value  = 20;
            source.DCA.VelocitySensitivity.Decay1Time.Value  = 20;
            source.DCA.VelocitySensitivity.ReleaseTime.Value = 20;

            // Harmonic levels
            if (!string.IsNullOrEmpty(waveformTemplateName))
            {
                int    numHarmonics = 64;
                byte[] levels       = WaveformEngine.GetHarmonicLevels(waveformTemplateName, numHarmonics, 127); // levels are 0...127
                source.ADD.SoftHarmonics = levels;

                Console.WriteLine(String.Format("waveform template = {0}", waveformTemplateName));

                /*
                 * Console.WriteLine(String.Format("{0}, {1} harmonics:", waveformName, numHarmonics));
                 * for (int i = 0; i < levels.Length; i++)
                 * {
                 *  Console.WriteLine(String.Format("{0} = {1}", i + 1, levels[i]));
                 * }
                 */
            }
            else if (!string.IsNullOrEmpty(harmonicLevelTemplateName))
            {
                Console.WriteLine(String.Format("harmonic template = {0}", harmonicLevelTemplateName));

                int[] softLevels = this.harmonicLevelTemplates[harmonicLevelTemplateName].Low.ToArray();
                source.ADD.SoftHarmonics = softLevels.Select(i => (byte)i).ToArray();

                int[] loudLevels = this.harmonicLevelTemplates[harmonicLevelTemplateName].High.ToArray();
                source.ADD.LoudHarmonics = loudLevels.Select(i => (byte)i).ToArray();
            }
            else
            {
                Console.WriteLine("No template specified for waveform or harmonic levels, using defaults");

                int[] softLevels = this.harmonicLevelTemplates["Init"].Low.ToArray();
                source.ADD.SoftHarmonics = softLevels.Select(i => (byte)i).ToArray();

                int[] loudLevels = this.harmonicLevelTemplates["Init"].High.ToArray();
                source.ADD.LoudHarmonics = loudLevels.Select(i => (byte)i).ToArray();
            }

            // Harmonic envelopes. Initially assign the same envelope for each harmonic.
            string harmEnvName = harmonicEnvelopeTemplateName;

            if (string.IsNullOrEmpty(harmonicEnvelopeTemplateName))
            {
                harmEnvName = "Init";
            }
            Console.WriteLine(String.Format("harmonic envelope template = {0}", harmEnvName));
            HarmonicEnvelope harmEnv = this.harmonicEnvelopeTemplates[harmEnvName];

            for (int i = 0; i < AdditiveKit.HarmonicCount; i++)
            {
                source.ADD.HarmonicEnvelopes[i] = harmEnv;
            }

            // Formant filter
            string formantName = formantFilterTemplateName;

            if (string.IsNullOrEmpty(formantFilterTemplateName))
            {
                formantName = "Init";
            }
            Console.WriteLine(String.Format("formant filter template = {0}", formantName));
            int[] formantLevels = this.formantFilterTemplates[formantName].ToArray();
            source.ADD.FormantFilter = formantLevels.Select(i => (byte)i).ToArray();

            return(source);
        }