我在c#中遇到了一个令人感兴趣的问题,我不知道该怎么做。随机间隔发生器对于设定的时间段内的实例数量
我需要有两个轨道顶部彼此玩。一定数量的嘟嘟声需要在一段时间内播放。其中一个会有一个设定的时间间隔(想想节拍器),但另一个需要随机播放。
我不确定如何解决第二个问题,在设定的时间内随机播放一组嘟嘟声。
我在c#中遇到了一个令人感兴趣的问题,我不知道该怎么做。随机间隔发生器对于设定的时间段内的实例数量
我需要有两个轨道顶部彼此玩。一定数量的嘟嘟声需要在一段时间内播放。其中一个会有一个设定的时间间隔(想想节拍器),但另一个需要随机播放。
我不确定如何解决第二个问题,在设定的时间内随机播放一组嘟嘟声。
只需要设置一定的时间量T即可表示为某种足够细化的结构,也就是说毫秒。如果您需要发出N次哔哔声,则需要将时间段拆分N次。因此,建立一个循环,运行N次,并且在每次迭代中,在时间间隔中选择随机位置以发出嘟嘟声。根据您之后对数据所做的操作,您可能需要对哔声点进行排序。
使用随机数生成在总时间范围内生成日期时间。当你完成随机发出的嘟嘟声时,间隔当然是随机的。像这样:
List<DateTime> randomBeeps = new List<DateTime>();
Random rand = new Random();
for(int j = 0; j < numberBeepsNeeded; j++)
{
int randInt = rand.Next();
double percent = ((double)randInt)/Int32.MaxValue;
double randTicksOfTotal = ((double)setAmountOfTime.Ticks) * percent;
DateTime randomBeep = new DateTime((long)randTicksOfTotal);
randomBeeps.Add(randomBeep);
}
您可能需要使用Convert.ToLong或类似的东西。不知道它是否会给你一个从双倍到长整数的错误,因为它正在四舍五入,这在这里很好。
您可以将其作为一系列单次定时器来实现。当每个定时器到期(或“滴答”)时,您会播放蜂鸣声,然后随机确定用于下一个单次定时器的持续时间。如果您选择的持续时间是1到1000(毫秒)之间的某个随机数,则您将每半秒平均一次“打勾”。
编辑:只是为了好玩,我想我会提一下,这是行为心理学家运行由B.F. Skinner启发的各种实验的老问题。他们有时使用称为“可变间隔”的加固时间表,其中加固之间的时间在某个预定平均间隔内随机变化。请参阅http://www.ncbi.nlm.nih.gov/pmc/articles/PMC1404199/pdf/jeabehav00190-0145.pdf以了解涉及的公式。
像这样的东西应该做的伎俩(此代码没有测试...但它编译干净的)
using System;
using System.Security.Cryptography;
using System.Threading;
class BeatBox : IDisposable
{
private RandomNumberGenerator RNG;
private DateTime dtStarted;
private TimeSpan TimeElapsed { get { return DateTime.Now - dtStarted; } }
private TimeSpan Duration;
private TimeSpan BeatInterval;
private uint MinRandomInterval;
private uint MaxRandomInterval;
private uint RandomIntervalDomain;
private Timer RegularIntervalTimer;
private Timer RandomIntervalTimer;
public delegate void TickHandler(object sender , bool isRandom);
public event TickHandler TickEvent;
private EventWaitHandle CompletionEventWaitHandle;
public BeatBox(TimeSpan duration , TimeSpan beatInterval , uint minRandomInterval , uint maxRandomInterval)
{
this.RNG = RandomNumberGenerator.Create();
this.Duration = duration ;
this.BeatInterval = beatInterval ;
this.MinRandomInterval = minRandomInterval ;
this.MaxRandomInterval = maxRandomInterval ;
this.RandomIntervalDomain = (maxRandomInterval - minRandomInterval) + 1 ;
this.dtStarted = DateTime.MinValue ;
this.RegularIntervalTimer = null ;
this.RandomIntervalTimer = null ;
return;
}
private long NextRandomInterval()
{
byte[] entropy = new byte[sizeof(long)] ;
RNG.GetBytes(entropy);
long randomValue = BitConverter.ToInt64(entropy , 0) & long.MaxValue; // ensure that its positive
long randomoffset = (randomValue % this.RandomIntervalDomain);
long randomInterval = this.MinRandomInterval + randomoffset;
return randomInterval;
}
public EventWaitHandle Start()
{
long randomInterval = NextRandomInterval();
this.CompletionEventWaitHandle = new ManualResetEvent(false);
this.RegularIntervalTimer = new Timer(RegularBeat , null , BeatInterval , BeatInterval);
this.RandomIntervalTimer = new Timer(RandomBeat , null , randomInterval , Timeout.Infinite);
return this.CompletionEventWaitHandle;
}
private void RegularBeat(object timer)
{
if (this.TimeElapsed >= this.Duration)
{
MarkComplete();
}
else
{
this.TickEvent.Invoke(this , false);
}
return;
}
private void RandomBeat(object timer)
{
if (this.TimeElapsed >= this.Duration)
{
MarkComplete();
}
else
{
this.TickEvent.Invoke(this , true);
long nextInterval = NextRandomInterval();
this.RandomIntervalTimer.Change(nextInterval , Timeout.Infinite);
}
return;
}
private void MarkComplete()
{
lock (this.CompletionEventWaitHandle)
{
bool signaled = this.CompletionEventWaitHandle.WaitOne(0);
if (!signaled)
{
this.RegularIntervalTimer.Change(Timeout.Infinite , Timeout.Infinite);
this.RandomIntervalTimer.Change(Timeout.Infinite , Timeout.Infinite);
this.CompletionEventWaitHandle.Set();
}
}
return;
}
public void Dispose()
{
if (RegularIntervalTimer != null)
{
WaitHandle handle = new ManualResetEvent(false);
RegularIntervalTimer.Dispose(handle);
handle.WaitOne();
}
if (RandomIntervalTimer != null)
{
WaitHandle handle = new ManualResetEvent(false);
RegularIntervalTimer.Dispose(handle);
handle.WaitOne();
}
return;
}
}
class Program
{
static void Main(string[] args)
{
TimeSpan duration = new TimeSpan(0 , 5 , 0); // run for 5 minutes total
TimeSpan beatInterval = new TimeSpan(0 , 0 , 1); // regular beats every 1 second
uint minRandomInterval = 5; // minimum random interval is 5ms
uint maxRandomInterval = 30; // maximum random interval is 30ms
using (BeatBox beatBox = new BeatBox(duration , beatInterval , minRandomInterval , maxRandomInterval))
{
beatBox.TickEvent += TickHandler;
EventWaitHandle completionHandle = beatBox.Start();
completionHandle.WaitOne();
}
return;
}
static void TickHandler(object sender , bool isRandom)
{
Console.WriteLine(isRandom ? "Random Beep!" : "Beep!");
return;
}
}
您可能还需要验证您没有选择同一个点的两倍。 – Fantius
这里的哔哔声是划分点,而不是块,所以对于N次哔哔声,您需要在时间间隔内有N个随机位置。当然,这将导致N + 1个块。 – phoog
OP也可能希望确保哔哔声的时间不超过某个最小跨度。例如,如果哔哔声本身需要500毫秒才能发声,则可能需要将哔声至少保持半秒钟。 – phoog