2

在声音处理应用程序中,许多事件是在音频流时间(在第一个近似值中,只是消耗样本的计数乘以一个系数)而不是系统时间,在这种情况下通常称为壁时间。例如,通常希望根据流时间对未来事件进行计时。例如,如果在一定时间内没有语音活动,则可以安排计时器接受录音;为此目的,流时间比挂钟时间更好地表示时间。

我正在考虑使用HistoricalScheduler为此类活动计时。据我了解,它在调用AdvanceBy/To. 此外,整个应用程序都在我们的控制之下,从某种意义上说,没有第 3 方部分——至少这样会使用 RX。

问题 1:这个想法是正确的、好的还是非常愚蠢的?我理解RX,没有经验,如果你愿意的话,直觉。

流通过 .NET 事件回调传递。传递流缓冲区(并调用事件)的线程应该尽可能少地被阻塞。音频被传输到一个有限长度的无限缓冲区中,这个实际的缓冲将发生在一个观察者中,在一个专用线程上观察这个事件,这就是调度器时间提前的地方。本质上,这归结为

IDisposable _sub;

// The historic scheduler that reflects the time of 
// the last sample in the endless buffer.
HistoricalScheduler _hisch = new HistoricalScheduler();

// This must be disposed of.
EventLoopScheduler _eventLoopSch = new EventLoopScheduler();

public IScheduler StreamTimeScheduler => _hisch;

// Subscribing to the stream.
void Initialize() {
  _sub = Observable.FromEventPattern<TEventHandler, TEventArgs>(
                     h => ReceivedAudio += h,
                     h => ReceivedAudio -= h)
                   .ObserveOn(_eventLoopSch)
                   .Subscribe(b => Append(b));
}

// The function that puts samples into the endless buffer. 
void Append(byte[] sample) {
  // ...put the sample into the array...
  _hisch.AdvanceBy(TimeSpan.FromSeconds(sample.Length / _avgBytesPerSecond));
}

问题 2:我觉得从观察函数中推进调度程序很奇怪,如上例所示。这是一种可接受的做法,还是立即闻起来有腥味(或者它可能介于两个极端之间)?

另一个可能的复杂情况是流最终停止生成数据,流时间也是如此。

问题 3:如果有的话,在调度程序中停止时间意味着什么,这样一些调度的操作将永远不会执行并且将永远保留在队列中?简单地删除对调度程序的引用会导致一次性资源泄漏吗?

并且流时间也不同于挂钟时间。

问题 4:如果有的话,不同的调度程序提供不连贯的概念意味着Now什么?

我在这里最好的猜测是“根本没有”,因为HistoricScheduler在其他情况下,实时调度程序和平共存,但我不确定我是否足够了解 RX 的这一部分,所以也不要问这个问题。

4

0 回答 0