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

Math 创建简单MIDI速度曲线的公式,math,Math,我试图找出一个简单的数学公式,它允许我将各种速度曲线应用于传入的MIDI值。在下图中,起始x,y为(0,0),结束x,y为(127127)。我试图得到一个单一变量的公式,这将允许我产生简单的扩展或收缩曲线总是在中间颠簸(通过变量的程度)。我的输入值将介于0和127之间,而我的输出值将始终介于0和127之间。这看起来应该很容易,但我的大学微积分现在已经不在我的掌握之中了 让我们首先将四个角标记为: S=(0,0) E=(127127) U=(0127) V=(127,0) 你正在寻找一个圆方程,它

我试图找出一个简单的数学公式,它允许我将各种速度曲线应用于传入的MIDI值。在下图中,起始x,y为(0,0),结束x,y为(127127)。我试图得到一个单一变量的公式,这将允许我产生简单的扩展或收缩曲线总是在中间颠簸(通过变量的程度)。我的输入值将介于0和127之间,而我的输出值将始终介于0和127之间。这看起来应该很容易,但我的大学微积分现在已经不在我的掌握之中了


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

S=(0,0)

E=(127127)

U=(0127)

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)

垂直度的斜率与弦的斜率成负反比,因此:

斜率1=-(127 Xz)/(127 Yz)

斜率2=-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'

让我们从标记四个角开始:

S=(0,0)

E=(127127)

U=(0127)

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)

垂直度的斜率与弦的斜率成负反比,因此:

斜率1=-(127 Xz)/(127 Yz)

斜率2=-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'

我想要一条简单的二次贝塞尔曲线,从p0(0,0)到p2(127127),该曲线基于一个范围介于(0127)和(127,0)之间的可移动控制点p1。我希望控制点的位置由偏差变量确定。这就是我如何根据偏差变量是一个介于-100和100之间的数字(0是一条线性线,负边代表pic2,正边代表pic3)来解决它的方法

//
///基于速度曲线转换MIDI值
/// 
///要转换的值
///从-100到100的线性线的偏差量
私有int值(int值,双偏差)
{
如果(偏差<-100 | |偏差>100)
抛出新ArgumentException(“值必须介于-100和100之间”,“偏差”);
var minMidiValue=0d;
var maxMidiValue=127d;
var中值=63.5d;
//这是二次贝塞尔曲线的控制点
//我们希望该值介于0(最小值)和63.5(最大值)之间
var控制点X=中间值+((偏差/100)*中间值);
//获取传入值相对于最大值的百分比位置
var t=(双)值/maxmidi值;
//二次贝塞尔曲线公式
//B(t)=(1-t)*(1-t)*p0)+(2*(1-t)*t*p1)+(t*t*p2)
//t=曲线上介于(0和1)之间的位置
//p0=最小值(0)
//p1=控制点X(贝塞尔控制点)
//p2=最大值(127)
//公式现在可以简化为:
//B(t)=(1-t)*(1-t)*minMidiValue)+(2*(1-t)*t*控制点x)+(t*t*最大midivalue)
//与我们价值观的偏差是什么?
var delta=(int)数学圆((2*(1-t)*t*controlPointX)+(t*t*maxMidiValue));
返回值(值-增量)+值;
}
这将导致值曲线介于以下三个值之间
    /// <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;
    }