static bool CurveDisplay(IAudioEffectPlugin plugin, Rect r0, ref float threshold, ref float ratio, ref float makeupGain, ref float attackTime, ref float releaseTime, ref float knee, float sidechainLevel, float outputLevel, float blend)
        {
            Event evt       = Event.current;
            int   controlID = GUIUtility.GetControlID(FocusType.Passive);

            Rect r = AudioCurveRendering.BeginCurveFrame(r0);

            const float thresholdActiveWidth = 10f;
            float       vuWidth = 10f;

            float minThreshold, maxThreshold, defThreshold;

            plugin.GetFloatParameterInfo(kThresholdName, out minThreshold, out maxThreshold, out defThreshold);
            float minRatio, maxRatio, defRatio;

            plugin.GetFloatParameterInfo(kRatioName, out minRatio, out maxRatio, out defRatio);
            float minMakeupGain, maxMakeupGain, defMakeupGain;

            plugin.GetFloatParameterInfo(kMakeupGainName, out minMakeupGain, out maxMakeupGain, out defMakeupGain);
            float minKnee, maxKnee, defKnee;

            plugin.GetFloatParameterInfo(kKneeName, out minKnee, out maxKnee, out defKnee);

            float dbRange = 100.0f, dbMin = -80.0f;
            float thresholdPosX = r.width * (threshold - dbMin) / dbRange;

            bool modifiedValue = false;

            switch (evt.GetTypeForControl(controlID))
            {
            case EventType.MouseDown:
                if (r.Contains(Event.current.mousePosition) && evt.button == 0)
                {
                    dragtype = DragType.None;
                    GUIUtility.hotControl = controlID;
                    EditorGUIUtility.SetWantsMouseJumping(1);
                    evt.Use();

                    // Ensure visible state change on mousedown to make it clear that interaction is possible
                    if ((Mathf.Abs(r.x + thresholdPosX - evt.mousePosition.x) >= thresholdActiveWidth))
                    {
                        dragtype = (evt.mousePosition.x < r.x + thresholdPosX) ? DragType.MakeupGain : DragType.Ratio;
                    }
                    else
                    {
                        dragtype = DragType.ThresholdAndKnee;
                    }
                }

                break;

            case EventType.MouseUp:
                if (GUIUtility.hotControl == controlID && evt.button == 0)
                {
                    dragtype = DragType.None;
                    GUIUtility.hotControl = 0;
                    EditorGUIUtility.SetWantsMouseJumping(0);
                    evt.Use();
                    AudioMixerEffectPlugin.OnParameterChangesDone();
                }

                break;

            case EventType.MouseDrag:
                if (GUIUtility.hotControl == controlID)
                {
                    float dragAcceleration = evt.alt ? .25f : 1f;
                    if (dragtype == DragType.ThresholdAndKnee)
                    {
                        bool dragKnee = Mathf.Abs(evt.delta.x) < Mathf.Abs(evt.delta.y);
                        if (dragKnee)
                        {
                            knee = Mathf.Clamp(knee + evt.delta.y * 0.5f * dragAcceleration, minKnee, maxKnee);
                        }
                        else
                        {
                            threshold = Mathf.Clamp(threshold + evt.delta.x * 0.1f * dragAcceleration, minThreshold, maxThreshold);
                        }
                    }
                    else if (dragtype == DragType.Ratio)
                    {
                        ratio = Mathf.Clamp(ratio + evt.delta.y * (ratio > 1.0f ? 0.05f : 0.003f) * dragAcceleration, minRatio, maxRatio);
                    }
                    else if (dragtype == DragType.MakeupGain)
                    {
                        makeupGain = Mathf.Clamp(makeupGain - evt.delta.y * 0.5f * dragAcceleration, minMakeupGain, maxMakeupGain);
                    }
                    else
                    {
                        Debug.LogError("Drag: Unhandled enum");
                    }

                    modifiedValue = true;
                    evt.Use();
                }

                break;
            }

            if (evt.type == EventType.Repaint)
            {
                // Curve
                HandleUtility.ApplyWireMaterial();

                //float sidechainPosX = r.width * (sidechainLevel - dbMin) / dbRange;
                float thresholdPosY  = r.height * (1.0f - ((threshold - dbMin + makeupGain) / dbRange));
                Color thresholdColor = new Color(0.7f, 0.7f, 0.7f);
                Color sidechainColor = Color.black;


                float duckGradient       = 1.0f / ratio;
                float duckThreshold      = threshold;
                float duckSidechainLevel = sidechainLevel;
                float duckMakeupGain     = makeupGain;
                float duckKnee           = knee;
                float duckKneeC1         = (knee > 0.0f) ? ((duckGradient - 1.0f) / (4.0f * knee)) : 0.0f;
                float duckKneeC2         = duckThreshold - knee;

                // Main filled curve
                AudioCurveRendering.DrawFilledCurve(
                    r,
                    delegate(float x, out Color col)
                {
                    float level = x * dbRange + dbMin;
                    float gain  = level;
                    float t     = level - duckThreshold;
                    col         = ScaleAlpha(duckSidechainLevel > level ? AudioCurveRendering.kAudioOrange : Color.grey, blend);
                    if (t > -duckKnee && t < duckKnee)
                    {
                        t   += duckKnee;
                        gain = t * (duckKneeC1 * t + 1.0f) + duckKneeC2;

                        if (dragtype == DragType.ThresholdAndKnee)
                        {
                            const float mult = 1.2f;
                            col = new Color(col.r * mult, col.g * mult, col.b * mult);
                        }
                    }
                    else if (t > 0.0f)
                    {
                        gain = duckThreshold + duckGradient * t;
                    }

                    return((2.0f * (gain + duckMakeupGain - dbMin) / dbRange) - 1.0f);
                }
                    );

                // Curve shown when modifying MakeupGain
                if (dragtype == DragType.MakeupGain)
                {
                    AudioCurveRendering.DrawCurve(
                        r,
                        delegate(float x)
                    {
                        float level = x * dbRange + dbMin;
                        float gain  = level;
                        float t     = level - duckThreshold;
                        if (t > -duckKnee && t < duckKnee)
                        {
                            t   += duckKnee;
                            gain = t * (duckKneeC1 * t + 1.0f) + duckKneeC2;
                        }
                        else if (t > 0.0f)
                        {
                            gain = duckThreshold + duckGradient * t;
                        }

                        return((2.0f * (gain + duckMakeupGain - dbMin) / dbRange) - 1.0f);
                    },
                        Color.white
                        );
                }


                // Threshold text and line
                textStyle10.normal.textColor = ScaleAlpha(thresholdColor, blend);
                EditorGUI.DrawRect(new Rect(r.x + thresholdPosX, r.y, 1, r.height), textStyle10.normal.textColor);
                DrawText(r.x + thresholdPosX + 4, r.y + 6, string.Format(CultureInfo.InvariantCulture.NumberFormat, "Threshold: {0:F1} dB", threshold));

                // Sidechain text and line
                textStyle10.normal.textColor = ScaleAlpha(sidechainColor, blend);
                DrawText(r.x + 4, r.y + r.height - 10, sidechainLevel < -80 ? "Input: None" : string.Format(CultureInfo.InvariantCulture.NumberFormat, "Input: {0:F1} dB", sidechainLevel));

                if (dragtype == DragType.Ratio)
                {
                    float aspect = r.height / r.width;
                    Handles.DrawAAPolyLine(2.0f,
                                           new[] { Color.black, Color.black },
                                           new[]
                    {
                        new Vector3(r.x + thresholdPosX + r.width, r.y + thresholdPosY - aspect * r.width, 0.0f),
                        new Vector3(r.x + thresholdPosX - r.width, r.y + thresholdPosY + aspect * r.width, 0.0f)
                    });
                    Handles.DrawAAPolyLine(3.0f,
                                           new[] { Color.white, Color.white },
                                           new[]
                    {
                        new Vector3(r.x + thresholdPosX + r.width, r.y + thresholdPosY - aspect * duckGradient * r.width, 0.0f),
                        new Vector3(r.x + thresholdPosX - r.width, r.y + thresholdPosY + aspect * duckGradient * r.width, 0.0f)
                    });
                }
                else if (dragtype == DragType.ThresholdAndKnee)
                {
                    // Knee min and max lines
                    float normalizedKnee1 = (threshold - knee - dbMin) / dbRange;
                    float normalizedKnee2 = (threshold + knee - dbMin) / dbRange;
                    float y1        = EvaluateDuckingVolume(normalizedKnee1, ratio, threshold, makeupGain, knee, dbRange, dbMin);
                    float y2        = EvaluateDuckingVolume(normalizedKnee2, ratio, threshold, makeupGain, knee, dbRange, dbMin);
                    float knee1PosY = r.yMax - (y1 + 1f) * 0.5f * r.height;
                    float knee2PosY = r.yMax - (y2 + 1f) * 0.5f * r.height;
                    EditorGUI.DrawRect(new Rect(r.x + normalizedKnee1 * r.width, knee1PosY, 1, r.height - knee1PosY), new Color(0, 0, 0, 0.5f));
                    EditorGUI.DrawRect(new Rect(r.x + normalizedKnee2 * r.width - 1, knee2PosY, 1, r.height - knee2PosY), new Color(0, 0, 0, 0.5f));

                    // Enhanced threshold
                    EditorGUI.DrawRect(new Rect(r.x + thresholdPosX - 1, r.y, 3, r.height), Color.white);
                }

                outputLevel = (Mathf.Clamp(outputLevel - makeupGain, dbMin, dbMin + dbRange) - dbMin) / dbRange;
                if (EditorApplication.isPlaying)
                {
                    const int margin = 2;
                    Rect      vuRect = new Rect(r.x + r.width - vuWidth + margin, r.y + margin, vuWidth - 2 * margin, r.height - 2 * margin);
                    DrawVU(vuRect, outputLevel, blend, true);
                }
            }

            AudioCurveRendering.EndCurveFrame();

            return(modifiedValue);
        }
Exemple #2
0
        static bool ParamEqualizerCurveEditor(IAudioEffectPlugin plugin, Rect r, ref float centerFreq, ref float bandwidth, ref float gain, float blend)
        {
            Event evt       = Event.current;
            int   controlID = GUIUtility.GetControlID(FocusType.Passive);

            r = AudioCurveRendering.BeginCurveFrame(r);

            float minCenterFreq, maxCenterFreq, defCenterFreq;

            plugin.GetFloatParameterInfo(kCenterFreqName, out minCenterFreq, out maxCenterFreq, out defCenterFreq);
            float minOctaveRange, maxOctaveRange, defOctaveRange;

            plugin.GetFloatParameterInfo(kOctaveRangeName, out minOctaveRange, out maxOctaveRange, out defOctaveRange);
            float minGain, maxGain, defGain;

            plugin.GetFloatParameterInfo(kFrequencyGainName, out minGain, out maxGain, out defGain);

            bool modifiedValue = false;

            switch (evt.GetTypeForControl(controlID))
            {
            case EventType.MouseDown:
                if (r.Contains(Event.current.mousePosition) && evt.button == 0)
                {
                    GUIUtility.hotControl = controlID;
                    EditorGUIUtility.SetWantsMouseJumping(1);
                    evt.Use();
                }

                break;

            case EventType.MouseUp:
                // Signal
                if (GUIUtility.hotControl == controlID && evt.button == 0)
                {
                    GUIUtility.hotControl = 0;
                    EditorGUIUtility.SetWantsMouseJumping(0);
                    evt.Use();
                    AudioMixerEffectPlugin.OnParameterChangesDone();
                }

                break;

            case EventType.MouseDrag:
                if (GUIUtility.hotControl == controlID)
                {
                    float dragAcceleration = Event.current.alt ? .25f : 1f;
                    centerFreq = Mathf.Clamp((float)MapNormalizedFrequency(MapNormalizedFrequency(centerFreq, plugin.GetSampleRate(), useLogScale, false) + evt.delta.x / r.width, plugin.GetSampleRate(), useLogScale, true), minCenterFreq, maxCenterFreq);
                    if (Event.current.shift)
                    {
                        bandwidth = Mathf.Clamp(bandwidth - evt.delta.y * 0.02f * dragAcceleration, minOctaveRange, maxOctaveRange);
                    }
                    else
                    {
                        gain = Mathf.Clamp(gain - evt.delta.y * 0.01f * dragAcceleration, minGain, maxGain);
                    }
                    modifiedValue = true;
                    evt.Use();
                }

                break;
            }

            if (Event.current.type == EventType.Repaint)
            {
                // Mark CenterFreq with a vertical line
                float c = (float)MapNormalizedFrequency(centerFreq, plugin.GetSampleRate(), useLogScale, false);
                EditorGUI.DrawRect(new Rect(c * r.width + r.x, r.y, 1f, r.height), GUIUtility.hotControl == controlID ? new Color(0.6f, 0.6f, 0.6f) : new Color(0.4f, 0.4f, 0.4f));

                // Curve
                HandleUtility.ApplyWireMaterial();
                double kPI   = 3.1415926;
                double wm    = -2.0f * kPI / plugin.GetSampleRate();
                double w0    = 2.0 * kPI * centerFreq / plugin.GetSampleRate();
                double Q     = 1.0 / bandwidth;
                double A     = gain;
                double alpha = Math.Sin(w0) / (2.0 * Q);
                double b0    = 1.0 + alpha * A;
                double b1    = -2.0 * Math.Cos(w0);
                double b2    = 1.0 - alpha * A;
                double a0    = 1.0 + alpha / A;
                double a1    = -2.0 * Math.Cos(w0);
                double a2    = 1.0 - alpha / A;
                AudioCurveRendering.DrawCurve(
                    r,
                    delegate(float x)
                {
                    double f   = MapNormalizedFrequency(x, plugin.GetSampleRate(), useLogScale, true);
                    ComplexD w = ComplexD.Exp(wm * f);
                    ComplexD n = w * (w * b2 + b1) + b0;
                    ComplexD d = w * (w * a2 + a1) + a0;
                    ComplexD h = n / d;
                    double mag = Math.Log10(h.Mag2());
                    return((float)(0.5 * mag));    // 20 dB range
                },
                    ScaleAlpha(AudioCurveRendering.kAudioOrange, blend)
                    );
            }

            DrawFrequencyTickMarks(r, plugin.GetSampleRate(), useLogScale, new Color(1.0f, 1.0f, 1.0f, 0.3f * blend));

            AudioCurveRendering.EndCurveFrame();

            return(modifiedValue);
        }