РЕДАКТИРОВАТЬ - Вот новая функция, которая включает в себя пребывание в 1,0 между outDuration
и следующим inDuration
. Обратите внимание, что я изменил вашу сигнатуру функции - теперь входные параметры inDuration
, holdDuration
и outDuration
. Функция остается в 0 между inDuration
и outDuration
для holdDuration
семплов, затем остается равной 1,0 после outDuration
для других holdDuration
семплов. Пандусы снова являются функциями Half-Hann, вы можете изменить их по своему усмотрению.
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);
альтернативный текст 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);
График с длительностью = 10000, вход = 2500, выход = 3000 http://img269.imageshack.us/img269/2969/oscfnxn.png
Функция понижается с 1,0 до 0 с индекса 0
до inDuration
, остается на 0 до индекса duration-outDuration
, затем поднимается до 1,0 с индексом duration
, поэтому она является точно периодической в выборках продолжительности.
Я не понял вашего комментария "Между ними и в течение некоторого времени 1". Вам не нужен другой параметр для указания времени удержания?