private List <IndividualTwinkleDetails> GenerateTwinkleData() { List <IndividualTwinkleDetails> result = new List <IndividualTwinkleDetails>(); // the mean interval between individual flickers (used for random generation later) // avoid any divide-by-zeros -- if it was <= 0, cap it to 1% at least double averageCoverage = ((AverageCoverage <= 0) ? 1.0 : AverageCoverage) / 100.0; double meanMillisecondsBetweenTwinkles = AveragePulseTime / averageCoverage / 2.0; double maxMillisecondsBetweenTwinkles = AveragePulseTime / averageCoverage; // the maximum amount of time an individual flicker/twinkle can vary off the average by int maxDurationVariation = (int)((PulseTimeVariation / 100.0) * AveragePulseTime); for (TimeSpan current = TimeSpan.Zero; current < TimeSpan;) { // calculate how long until the next flicker, and clamp it (since there's a small chance it's huge) //Replaced the number generator to a version that provides a better distribution around the mean //to prevent excessive twinkles from being gnerated. JU //double nextTime = Math.Log(1.0 - _random.NextDouble())*-meanMillisecondsBetweenTwinkles; double nextTime = RandomGenerator.GetExponential(meanMillisecondsBetweenTwinkles); if (nextTime > maxMillisecondsBetweenTwinkles) { nextTime = maxMillisecondsBetweenTwinkles; } // check if the timespan will be off the end, if so, bail current += TimeSpan.FromMilliseconds(nextTime); if (current >= TimeSpan) { break; } // generate a time length for it (all in ms) int twinkleDurationMs = _random.Next(AveragePulseTime - maxDurationVariation, AveragePulseTime + maxDurationVariation + 1); TimeSpan twinkleDuration = TimeSpan.FromMilliseconds(twinkleDurationMs); // it might have to be capped to fit within the duration of the whole effect, so figure that out if (current + twinkleDuration > TimeSpan) { // it's past the end of the effect. If it can be reduced to fit in the acceptable range, do that, otherwise skip it if ((TimeSpan - current).TotalMilliseconds >= AveragePulseTime - maxDurationVariation) { twinkleDuration = (TimeSpan - current); } else { // if we can't fit anything else into this time gap, not much point continuing the iteration break; } } // generate the levels/curve for it double minLevel = MinimumLevel; int maxLevelVariation = (int)((LevelVariation / 100.0) * (MaximumLevel - MinimumLevel)); int reduction = _random.Next(maxLevelVariation); double maxLevel = MaximumLevel - reduction; IndividualTwinkleDetails occurance = new IndividualTwinkleDetails(); occurance.StartTime = current; occurance.Duration = twinkleDuration; occurance.curvePoints = new [] { minLevel *100, maxLevel *100, minLevel *100 }; result.Add(occurance); } return(result); }
private List<IndividualTwinkleDetails> GenerateTwinkleData() { List<IndividualTwinkleDetails> result = new List<IndividualTwinkleDetails>(); // the mean interval between individual flickers (used for random generation later) // avoid any divide-by-zeros -- if it was <= 0, cap it to 1% at least double averageCoverage = ((AverageCoverage <= 0) ? 1.0 : AverageCoverage) / 100.0; double meanMillisecondsBetweenTwinkles = AveragePulseTime / averageCoverage / 2.0; double maxMillisecondsBetweenTwinkles = AveragePulseTime / averageCoverage; // the maximum amount of time an individual flicker/twinkle can vary off the average by int maxDurationVariation = (int)((PulseTimeVariation / 100.0) * AveragePulseTime); for (TimeSpan current = TimeSpan.Zero; current < TimeSpan; ) { // calculate how long until the next flicker, and clamp it (since there's a small chance it's huge) double nextTime = Math.Log(1.0 - _random.NextDouble()) * -meanMillisecondsBetweenTwinkles; if (nextTime > maxMillisecondsBetweenTwinkles) nextTime = maxMillisecondsBetweenTwinkles; // check if the timespan will be off the end, if so, bail current += TimeSpan.FromMilliseconds(nextTime); if (current >= TimeSpan) break; // generate a time length for it (all in ms) int twinkleDurationMs = _random.Next(AveragePulseTime - maxDurationVariation, AveragePulseTime + maxDurationVariation + 1); TimeSpan twinkleDuration = TimeSpan.FromMilliseconds(twinkleDurationMs); // it might have to be capped to fit within the duration of the whole effect, so figure that out if (current + twinkleDuration > TimeSpan) { // it's past the end of the effect. If it can be reduced to fit in the acceptable range, do that, otherwise skip it if ((TimeSpan - current).TotalMilliseconds >= AveragePulseTime - maxDurationVariation) { twinkleDuration = (TimeSpan - current); } else { // if we can't fit anything else into this time gap, not much point continuing the iteration break; } } // generate the levels/curve for it double minLevel = MinimumLevel; int maxLevelVariation = (int)((LevelVariation / 100.0) * (MaximumLevel - MinimumLevel)); int reduction = _random.Next(maxLevelVariation); double maxLevel = MaximumLevel - reduction; Curve curve = new Curve(new PointPairList(new double[] { 0, 50, 100 }, new double[] { minLevel * 100, maxLevel * 100, minLevel * 100 })); IndividualTwinkleDetails occurance = new IndividualTwinkleDetails(); occurance.StartTime = current; occurance.Duration = twinkleDuration; occurance.TwinkleCurve = curve; result.Add(occurance); } return result; }