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