[英]Random Interval Generator For a Set Number of Instances Over a Set Period of Time
我在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或类似的东西。 不知道它是否会在四舍五入的过程中给您从double转换为long的错误,在这里很好。
您可以将其实现为一系列的一次性计时器。 当每个计时器到期(或“滴答”)时,您会发出哔声,然后随机确定下一个计时器的持续时间。 如果您选择的持续时间是介于1到1000(毫秒)之间的某个随机数,则您将平均每半秒一次“滴答”。
编辑:只是为了好玩,我想提一提,这对于行为心理学家进行由BF 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;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.