2009-11-28 6 views
2

이 오실 레이션 기능을 구현하는 가장 빠른 방법은 무엇입니까? 서명은 다음과 같을 것이다 :이 발진 기능을 구현하는 방법

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

및 결과는 배정되어야한다는 currentCounter이 진행으로 0과 1 osscialtion 속도가 duration 파라미터 (진드기의 수에 의해 정의 사이 ossciates 단일 osccilation). 유사하게 상승 및 하강 속도는 inDUrationoutDuration (inDUration + outDuration)을 통해 정의됩니다.

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

이 그래프의 x 축은 물론 currentCounter 것이다.

+0

함수는'inDuration'과 ('Duration' -'outDuration') 사이에 어떻게 정의되어 있습니까? 그것이 0이거나 정의되지 않았습니까? –

+0

inDuration 및 outDuration 동안의 진동 기능은 무엇입니까? (선형입니까, X^2, sin (X) ...?) – Elisha

+0

'currentCounter' 매개 변수가'double' 또는'float'이 아니어야합니까? –

답변

1

편집 - 다음은 outDuration과 그 다음 inDuration 사이의 1.0에 머무르는 새로운 기능입니다. 함수 서명을 변경했음을 유의하십시오. 입력 매개 변수는 이제 inDuration, holdDurationoutDuration입니다. 이 함수는 holdDuration 샘플의 경우 inDurationoutDuration 사이의 0에 머무른 다음 다른 holdDuration 샘플의 경우 outDuration 이후에 1.0으로 유지됩니다. 램프는 하프 칸 기능이며 원하는대로 변경할 수 있습니다.

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; 
} 

이것은 이전 버전과 동일한 주기성 기능을 가지고 있습니다.

다음은 두 사이클의 기능을 보여주는 그래프입니다. 테스트 루프는 내가 그런 것들에 대한 Hann function의 큰 팬이에요

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

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

첫 번째 버전이었다. 이것이 문제가된다면 그것은 지속적이고 차별화됩니다.다음은 간단한 구현입니다.

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

함수는 inDuration에 인덱스 0에서 1.0 0 가져갈

생성 지수 duration-outDuration는 다음 인덱스 duration에서 1.0으로 상승 할 때까지 0으로 유지되므로 정확히하였습니다 'duration'샘플에서 주기적입니다.

"귀하의 의견을 이해하지 못했습니다. 시간이 지나면 1 시가됩니다." 대기 시간을 지정하는 데 다른 매개 변수가 필요하지 않습니까?

+0

첫 번째 마침표 (10000 이후)가 0 대신에 1을 유지하면 (첫 번째 마침표가 0 인 것과 같은 시간 동안) osscilating됩니다. – bitbonk

+0

현재 상단 및 하단 진폭 a가 'Math.Min, Math.Max' 및 – bitbonk

2

코멘트 작성자가 지적한대로 기능을 알아야합니다. 당신이 볼 수 있듯이, 당신이 InFunction()OutFunction()을 작성해야

// 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; 

: 뭔가처럼
프로그램 구조가 될 것이다.
둘 다 정의 도메인에 이라는 두 개의 매개 변수 x 위치와 정의 도메인이 있습니다. 이 방법은 기능을 구현하는 것이 쉬워야합니다.

는 편집 :
quadratic functionInFunction에 대한 예를 수 :

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

는 0과 1 사이의 값을 얻을 범위에 의해 현재 나누면 - 결과 있는지 확인합니다 0에서 1 사이입니다 (지정한대로).

관련 문제