private async Task RunLocal() { var ct = ProcessCancel.Token; var taskSet = new HashSet <Task>(); var blockSize = (int)(Param.SamplingRate * Param.SampleLength); Logger.LogInformation($"[loop5] blockSize {blockSize}"); var audioInterval = (long)(10_000_000.0 * Param.SampleLength); Logger.LogInformation($"[loop5] audioInterval {audioInterval}"); var videoInterval = (long)(10_000_000.0 / Param.MaxFrameRate); Logger.LogInformation($"[loop5] videoInterval {videoInterval}"); var counter = new ElapsedTimeCounter(); using var audioWaiter = new Waiter(counter, audioInterval); using var videoWaiter = new Waiter(counter, videoInterval); using var buf = new IPCBuffer <float>(Param.EffectName, blockSize * 2 * Param.BufferCount, LoggerFactory); using var vstBufferPool = new BufferPool <VstBuffer2 <float> >(Param.BufferCount, () => new VstBuffer2 <float>(blockSize, 2, buf), LoggerFactory); using var pcmPool = new BufferPool <PcmBuffer <float> >(Param.BufferCount, () => new PcmBuffer <float>(blockSize, 2), LoggerFactory); using var audioPool = new BufferPool <OpusOutputBuffer>(Param.BufferCount, () => new OpusOutputBuffer(5000), LoggerFactory); using var pcmDrowPool = new BufferPool <PcmBuffer <float> >(Param.BufferCount, () => new PcmBuffer <float>(blockSize, 2), LoggerFactory); using var bmpPool = new BufferPool <H264InputBuffer>(Param.BufferCount, () => new H264InputBuffer(Param.Width, Param.Height), LoggerFactory); using var videoPool = new BufferPool <H264OutputBuffer>(Param.BufferCount, () => new H264OutputBuffer(200000), LoggerFactory); using var vst = new AudioMaster <float>(Param.SamplingRate, blockSize, LoggerFactory, counter, DllManager); using var toPcm = new ToPcm <float>(LoggerFactory, counter); using var opus = new OpusEncoder(SamplingRate.Sampling48000, Channels.Stereo, LoggerFactory, counter); using var fft = new FFTEncoder(Param.Width, Param.Height, Param.MaxFrameRate, LoggerFactory, counter); using var h264 = new H264Encoder(Param.Width, Param.Height, Param.TargetBitrate, Param.MaxFrameRate, LoggerFactory, counter); var effect = vst.AddEffect(Param.EffectName); var options = new ExecutionDataflowBlockOptions { CancellationToken = ct, MaxDegreeOfParallelism = 1, MaxMessagesPerTask = DataflowBlockOptions.Unbounded }; { var audioBlock = new ActionBlock <VstBuffer2 <float> >(async buffer => { var pcmTask = pcmPool.ReceiveAsync(ct); var audioTask = audioPool.ReceiveAsync(ct); buffer.Log.Clear(); audioWaiter.Wait(); buffer.Log.Add("[audio] start", counter.NowTicks); //VST var nowTime = counter.NowTicks / 10; effect.ProcessEvent(nowTime, MidiEventInput); effect.ProcessReplacing(nowTime, buffer); //trans var pcm = await pcmTask.ConfigureAwait(false); buffer.Log.Add("[audio] opus input get", counter.NowTicks); toPcm.Execute(buffer, pcm); vstBufferPool.Post(buffer); var audio = await audioTask.ConfigureAwait(false); pcm.Log.Add("[audio] opus output get", counter.NowTicks); opus.Execute(pcm, audio); pcmDrowPool.Post(pcm); //FTL // ftl.Execute(audio); audioPool.Post(audio); }, options); taskSet.Add(audioBlock.Completion); vstBufferPool.LinkTo(audioBlock); } { var midiDataStoreBlock = new ActionBlock <MIDIMessageEvent2>(buffer => { fft.Receive(buffer); }, options); taskSet.Add(midiDataStoreBlock.Completion); MidiEventOutput.LinkTo(midiDataStoreBlock); var pcmDataStoreBlock = new ActionBlock <PcmBuffer <float> >(buffer => { fft.Receive(buffer); pcmPool.Post(buffer); }, options); taskSet.Add(pcmDataStoreBlock.Completion); pcmDrowPool.LinkTo(pcmDataStoreBlock); var intraFrameCount = 0.0; var videoBlock = new ActionBlock <H264InputBuffer>(async buffer => { var videoTask = videoPool.ReceiveAsync(ct); buffer.Log.Clear(); videoWaiter.Wait(); buffer.Log.Add("[video] start", counter.NowTicks); //FFT fft.Execute(buffer); //H264 var video = await videoTask.ConfigureAwait(false); buffer.Log.Add("[video] h264 output get", counter.NowTicks); var insertIntraFrame = (intraFrameCount <= 0); h264.Execute(buffer, video, insertIntraFrame); bmpPool.Post(buffer); if (insertIntraFrame) { intraFrameCount = Param.IntraFrameIntervalUs; } intraFrameCount -= videoInterval; //FTL //ftl.Execute(video); videoPool.Post(video); }, options); taskSet.Add(videoBlock.Completion); bmpPool.LinkTo(videoBlock); } while (taskSet.Count > 0) { var task = await Task.WhenAny(taskSet).ConfigureAwait(false); taskSet.Remove(task); if (task.IsFaulted) { ProcessCancel.Cancel(); Logger.LogError(task.Exception, "Process Exception"); } } }