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