naudio 在使用 MultiplexingWaveProvider 时无法处理 Asio

naudio Can't dispose of Asio when using MultiplexingWaveProvider

如果我创建一个 AsioOut 并使用 MultiplexingWaveProvider 它工作正常(播放/处理等..)只有当我在 MultiplexingWaveProvider 有 运行 数据不足之前调用 AsioOut.Stop() 时。

如果我等到 MultiplexingWaveProvider 运行 没有数据(并且 AsioOut 触发了 PlaybackStopped 事件)我无法处理 AsioOut 它只是挂起并且永远不会 returns(没有错误) .注意:MultiplexingWaveProvider 上没有 Dispose(),但我尝试在用于 MultiplexingWaveProvider 的所有 WaveFileReader 上调用 dispose。

有几个人在尝试自动停止时报告了 ASIO 驱动程序的问题。如果在缓冲区交换回调中调用停止,可能有些驱动程序不喜欢它。

理想情况下 AsioOut 应该更新为提供禁用自动停止的选项。您可以通过创建一个永无止境的 ISampleProvider 来模拟这一点,其 Read 方法 returns 在到达源结束后保持沉默。然后您可以轮询以查看何时到达输入的末尾,然后 StopDispose 完成时

这是我对马克回答的理解。我不得不使用 IWaveProvidor,因为我使用的 MultiplexingWaveProvider 不支持 ISampleProvidor。 (我也可以实现一个 MultiplexingWaveProvider 来获得我认为相同的结果)。请注意,该任务过去不会在数据处理程序中调用停止。

  public class AsioWavProvidor :IWaveProvider
        {
            private bool EndSignaled = false;
            public Action EndofAudioData;
            public Mp3FileReader Mp3Reader;
            public AsioWavProvidor(string mp3File)
            {
                Mp3Reader = new Mp3FileReader(mp3File);
            }
            public TimeSpan CurrentTime { get { return Mp3Reader.CurrentTime; } }


 public int Read(byte[] buffer, int offset, int count)
            {
                var retCount = Mp3Reader.Read(buffer, offset, count);
                if (retCount == 0)
                {
                   if (EndofAudioData != null && !EndSignaled)
                    {

                        EndSignaled = true;
                        System.Threading.Tasks.Task.Run(() =>
                        {
                            try
                            {
                                EndofAudioData();
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex);
                            }
                        });

                    }
                    return count;
                }
                return retCount;
            }