Beispiel #1
0
        public bool Process()
        {
            if (noteGain < SoundFontMath.NonAudible)
            {
                return(false);
            }

            var channelInfo = synthesizer.Channels[channel];

            ReleaseIfNecessary(channelInfo);

            if (!volEnv.Process())
            {
                return(false);
            }

            modEnv.Process();
            vibLfo.Process();
            modLfo.Process();

            var vibPitchChange     = (0.01F * channelInfo.Modulation + vibLfoToPitch) * vibLfo.Value;
            var modPitchChange     = modLfoToPitch * modLfo.Value + modEnvToPitch * modEnv.Value;
            var channelPitchChange = channelInfo.Tune + channelInfo.PitchBend;
            var pitch = key + vibPitchChange + modPitchChange + channelPitchChange;

            if (!oscillator.Process(block, pitch))
            {
                return(false);
            }

            if (dynamicCutoff)
            {
                var cents     = modLfoToCutoff * modLfo.Value + modEnvToCutoff * modEnv.Value;
                var factor    = SoundFontMath.CentsToMultiplyingFactor(cents);
                var newCutoff = factor * cutoff;

                // The cutoff change is limited within x0.5 and x2 to reduce pop noise.
                var lowerLimit = 0.5F * smoothedCutoff;
                var upperLimit = 2F * smoothedCutoff;
                if (newCutoff < lowerLimit)
                {
                    smoothedCutoff = lowerLimit;
                }
                else if (newCutoff > upperLimit)
                {
                    smoothedCutoff = upperLimit;
                }
                else
                {
                    smoothedCutoff = newCutoff;
                }

                filter.SetLowPassFilter(smoothedCutoff, resonance);
            }
            filter.Process(block);

            previousMixGainLeft  = currentMixGainLeft;
            previousMixGainRight = currentMixGainRight;
            previousReverbSend   = currentReverbSend;
            previousChorusSend   = currentChorusSend;

            // According to the GM spec, the following value should be squared.
            var ve          = channelInfo.Volume * channelInfo.Expression;
            var channelGain = ve * ve;

            var mixGain = noteGain * channelGain * volEnv.Value;

            if (dynamicVolume)
            {
                var decibels = modLfoToVolume * modLfo.Value;
                mixGain *= SoundFontMath.DecibelsToLinear(decibels);
            }

            var angle = (MathF.PI / 200F) * (channelInfo.Pan + instrumentPan + 50F);

            if (angle <= 0F)
            {
                currentMixGainLeft  = mixGain;
                currentMixGainRight = 0F;
            }
            else if (angle >= SoundFontMath.HalfPi)
            {
                currentMixGainLeft  = 0F;
                currentMixGainRight = mixGain;
            }
            else
            {
                currentMixGainLeft  = mixGain * MathF.Cos(angle);
                currentMixGainRight = mixGain * MathF.Sin(angle);
            }

            currentReverbSend = SoundFontMath.Clamp(channelInfo.ReverbSend + instrumentReverb, 0F, 1F);
            currentChorusSend = SoundFontMath.Clamp(channelInfo.ChorusSend + instrumentChorus, 0F, 1F);

            if (voiceLength == 0)
            {
                previousMixGainLeft  = currentMixGainLeft;
                previousMixGainRight = currentMixGainRight;
                previousReverbSend   = currentReverbSend;
                previousChorusSend   = currentChorusSend;
            }

            voiceLength += synthesizer.BlockSize;

            return(true);
        }