【问题标题】:How to implement this oscillation function如何实现这个振荡功能
【发布时间】:2009-11-28 08:47:48
【问题描述】:

什么是实现这种振荡功能的快速方法。 签名看起来像这样:

public static double Calculate(UInt64 currentCounter, uint duration, uint inDuration, uint outDuration)

结果应该是双倍,随着 currentCounter 的前进,在 0 和 1 之间振荡。振荡速度由 duration 参数定义(单次振荡的刻度数)。同样,上升和下降速度通过inDUrationoutDuration (inDUration + outDuration) 定义。

alt text http://img252.imageshack.us/img252/9457/graphuf.jpg

该图的 x 轴当然是 currentCounter

【问题讨论】:

  • inDuration 和 (Duration - outDuration) 之间的函数是如何定义的?它是零还是根本没有定义?
  • inDuration和outDuration的振荡函数是什么? (是线性的,X^2,sin(X)...?)
  • 不应将currentCounter 参数设为doublefloat
  • n 进出之间有一段时间为 0。在 out 和 in 之间是 1 一段时间(是的,这里的绘图是错误的)。为简单起见,输入和输出函数可以是线性的。但是一些easein和easout(比如sinus函数)会很酷。
  • @Darin currentCounter 只是整数。这是一个离散增量。

标签: c# algorithm math


【解决方案1】:

正如评论者所指出的,您必须了解这些功能。
程序结构类似于:

// Use modulo to get the counter within the range of the first duration
var phaseCounter = currentCounter % duration;

// Use the appropriate function
if( phaseCounter < inDuration )
{
  return InFunction( phaseCounter, inDuration );
}
if( phaseCounter > duration - outDuration )
{
  // Normalize the phaseCounter to the domain of definition for OutFunction()
  var outDurationOffset = duration - outDuration;
  return OutFuntion( phaseCounter - outDurationOffset, outDuration );
}
return 0;

如您所见,您必须填写InFunction()OutFunction()
他们都得到两个参数,x 位置在他们的定义域和他们的定义域。这样应该很容易实现功能。

编辑:
quadratic function 可能是您的InFunction示例

double InFunction( uint current, uint range )
{
  return Math.Pow( ( current / range ) - 1, 2 );
}

通过将电流除以范围,您会得到一个介于 0 和 1 之间的值 - 这将确保结果也在 0 和 1 之间(如您指定的那样)。

【讨论】:

    【解决方案2】:

    EDIT - 这是一个新功能,包括在 outDuration 和下一个 inDuration 之间保持 1.0。请注意,我已经更改了您的函数签名 - 输入参数现在是 inDurationholdDurationoutDuration。对于holdDuration 样本,该函数在inDurationoutDuration 之间保持在0,然后在outDuration 之后保持在1.0,对于另一个holdDuration 样本。斜坡又是半汉恩函数,您可以根据需要更改它们。

    public static double Calculate(UInt64 currentCounter, uint inDuration, uint holdDuration, uint outDuration)
    {
        UInt64 curTime;
        double ret;
    
        curTime = currentCounter % (inDuration + 2*holdDuration + outDuration); //this wrapping should really be handled by the caller
    
        if (curTime < inDuration)
        {
            ret = 0.5 * (1.0 - Math.Cos(2.0 * Math.PI * (inDuration - curTime) / (2.0 * inDuration)));
        }
        else if (curTime < inDuration + holdDuration)
        {
            ret = 0.0;
        }
        else if (curTime < inDuration + holdDuration + outDuration)
        {
            ret = 0.5 * (1.0 - Math.Cos(2.0 * Math.PI * (curTime - inDuration - holdDuration) / (2.0 * outDuration)));
        }
        else
        {
            ret = 1.0;
        }
    
        return ret;
    }
    

    这与以前的版本具有相同的周期性特征。

    这是一个显示函数的两个循环的图表。测试循环是

    for (ctr = 0; ctr < 20000; ctr++)
        Calculate(ctr, 2500, 2250, 3000);
    

    alt text http://img16.imageshack.us/img16/4443/oscfnxn2.png

    第一版
    我是 Hann function 的忠实粉丝。如果这是一个问题,它是连续的和可微的。这是一个简单的实现:

    public static double Calculate(UInt64 currentCounter, uint duration, uint inDuration, uint outDuration)
    {
        UInt64 curTime;
        double ret;
    
        //should check that inDuration + outDuration <= duration
        curTime = currentCounter % duration; //this wrapping should really be handled by the caller
    
        if (curTime < inDuration)
        {
            ret = 0.5 * (1.0 - Math.Cos(2.0 * Math.PI * (inDuration - curTime) / (2.0 * inDuration)));
        }
        else if (curTime >= (duration - outDuration))
        {
            ret = 0.5 * (1.0 - Math.Cos(2.0 * Math.PI * (outDuration + duration - curTime) / (2.0 * outDuration)));
        }
        else
        {
            ret = 1.0;
        }
    
        return ret;
    }
    

    这是一个示例图表。这是用循环生成的

    for (ctr = 0; ctr < 10000; ctr++)
        Calculate(ctr, 10000, 2500, 3000);
    

    Graph with duration = 10000, in = 2500, out = 3000 http://img269.imageshack.us/img269/2969/oscfnxn.png

    函数从索引 0inDuration 从 1.0 下降到 0,在索引 duration-outDuration 之前保持在 0,然后在索引 duration 处上升到 1.0,因此它在“持续时间”样本中是完全周期性的。

    我不明白您的评论“在一段时间内,在出入之间为 1”。不需要另外一个参数来指定保持时间吗?

    【讨论】:

    • 它在第一个周期之后(10000 之后)而不是 0 振荡,它保持 1(与它在第一周期保持 0 的时间相同)。
    • 目前我正在使用拉伸窦,其中顶部和底部振幅 a 使用 Math.Min,Math.Max
    猜你喜欢
    • 2022-07-28
    • 2021-11-23
    • 1970-01-01
    • 2016-12-07
    • 1970-01-01
    • 1970-01-01
    • 2012-09-26
    • 1970-01-01
    • 2020-12-07
    相关资源
    最近更新 更多