用于创建简单MIDI速度曲线的公式

时间:2016-12-14 03:26:27

标签: math

我正在试图找出一个简单的数学公式,它允许我将各种速度曲线应用于传入的MIDI值。在下图中,起始x,y为(0,0),结束x,y为(127,127)。我试图得到一个带有单个变量的公式,这个公式允许我生成简单的扩展或收缩曲线,总是在中间碰撞(通过变量的程度)。我的输入将是0到127之间的值,我的输出将始终在0到127之间。这看起来应该很容易,但我的大学微积分现在正在逃避我。

enter image description here

2 个答案:

答案 0 :(得分:0)

让我们首先将四个角标记为:

S =(0,0)

E =(127,127)

U =(0,127)

V =(127,0)

你正在寻找一个圆形方程,它通过E和S以及U和V之间的第三个点Z.让我们把它标记为Z:

Z(t)= t * U +(1-t)* V

我将使用两个和弦的垂直平分线在中心相交的事实。

平分线B1和B2是:

B1 =(Xz / 2,Yz / 2)

B2 =((127 + Xz)/ 2,(127 + Yz)/ 2)

垂线的斜率是和弦斜率的负倒数,所以:

Slope1 = - (127-Xz)/(127-Yz)

Slope2 = - Xz / Yz

使用点和斜率的直线方程

L1 = y = Slope1 *(x-B1x)+ B1y

L2 = y = Slope2 *(x-B2x)+ B2y

圆圈C的中心是它们的交点:

Cx = [B2y-B1y + Slope1 * B1x - Slope2 * B2x] / [Slope1-Slope2]

Cy = [Slope2 *(B2y-B1y + Slope1 * B1x - Slope2 * B2x)] / [Slope1-Slope2] - Slope2 * B2x + B2y

所以我们有圆圈方程的左侧:

(x-Cx)^ 2 +(y-Cy)^ 2 = R ^ 2

缺少的是半径。但它只是C和我们任何初始点之间的距离。从S计算是最简单的,因为它是(0,0):

R =平方根([Cx-Sx] ^ 2 + [Cy-Sy] ^ 2)=平方根(Cx ^ 2 + Cy ^ 2)

所以最后如果你替换所有定义(在程序中可能更容易做到而不是在这里输入),那么你将获得单个变量t的函数:

(x-Cx)^ 2 +(y-Cy)^ 2 = Cx ^ 2 + Cy ^ 2

注意:你会得到t = 0.5的直线,但是你可以很容易地用t'= t-0.5代替并且只用t'

答案 1 :(得分:0)

基于可移动控制点p1,我想要一个从p0(0,0)到p2(127,127)的简单二次贝塞尔曲线,其范围在(0,127)和(127,0)之间。我希望控制点的位置由偏差变量确定。这就是我根据偏差变量是-100到100之间的数字来解决它的方法(0是线性线,负侧表示pic 2,正侧表示pic 3)。

    /// <summary>
    /// Converts a MIDI value based on a velocity curve
    /// </summary>
    /// <param name="value">The value to convert</param>
    /// <param name="deviation">The amount of deviation from a linear line from -100 to 100</param>
    private int ConvertMidiValue(int value, double deviation)
    {
        if (deviation < -100 || deviation > 100)
            throw new ArgumentException("Value must be between -100 and 100", "deviation");

        var minMidiValue = 0d;
        var maxMidiValue = 127d;
        var midMidiValue = 63.5d;

        // This is our control point for the quadratic bezier curve
        // We want this to be between 0 (min) and 63.5 (max)
        var controlPointX = midMidiValue + ((deviation / 100) * midMidiValue);

        // Get the percent position of the incoming value in relation to the max
        var t = (double)value / maxMidiValue;

        // The quadratic bezier curve formula
        // B(t) = ((1 - t) * (1 - t) * p0) + (2 * (1 - t) * t * p1) + (t * t * p2)

        // t  = the position on the curve between (0 and 1)
        // p0 = minMidiValue (0)
        // p1 = controlPointX (the bezier control point)
        // p2 = maxMidiValue (127)

        // Formula can now be simplified as:
        // B(t) = ((1 - t) * (1 - t) * minMidiValue) + (2 * (1 - t) * t * controlPointX) + (t * t * maxMidiValue)

        // What is the deviation from our value?
        var delta = (int)Math.Round((2 * (1 - t) * t * controlPointX) + (t * t * maxMidiValue));

        return (value - delta) + value;
    }

这导致值曲线在下面显示的三个之间(蓝色为-100,灰色为0,红色为100):

Velocity Curves