NAudio 与 MultiplexingSampleProvider 和 WasapiOut

Posted

技术标签:

【中文标题】NAudio 与 MultiplexingSampleProvider 和 WasapiOut【英文标题】:NAudio with MultiplexingSampleProvider and WasapiOut 【发布时间】:2017-08-07 19:26:41 【问题描述】:

我一直在使用 NAudio 开发一个 C# 项目,我需要将特定的音频信号发送到 4 声道系统上的特定扬声器。基本上,我需要向左后扬声器发送“环境声音”,向右前扬声器发送“前面板显示声音”,向左前扬声器发送“预先录制的说明”。 我当前的设计适用于我的台式计算机支持的 ​​2 通道设置,但是当我尝试在我的测试硬件上将其扩展到 4 通道时,我不断收到以下错误:“值不在预期范围内。”当我调用 WasapiOut.init() 时。我认为这个问题是由 MultiplexingSampleProvider 以某种方式引起的,但我无法弄清楚为什么/如何解决这个问题。在尝试加载之前,我会验证我正在使用的 AudioDevice 是否支持足够的通道,因此不是缺少通道导致问题。

这是导致问题的代码:

// Create mixer provider for each channel.
for( int Count = 0; Count < Channels; Count++ )

    _Mixers.Add( new MixingSampleProvider( _Format.AsStandardWaveFormat() ) );
    _Mixers[Count].MixerInputEnded += SoundEndedEvent;


// Create and configure multiplexer provider.
_Multi = new MultiplexingSampleProvider( _Mixers, Channels );
for( int count = 0; count < Channels; count++ )

    _Multi.ConnectInputToOutput( count, 0 );


// Add master volume control provider.
_Volume = new VolumeSampleProvider( _Multi );
_Volume.Volume = 1.0f;

// Initialize output device.
_OutputDev.Init( p_Volume );

_Format 是一个 WaveFormatExtensible 类,设置为 44.1Khz、32 位、1 通道。

在我调用 _OutputDev.Init(p_Volume) 之前一切正常,这是我得到“值不在预期范围内”的地方。例外。

任何想法为什么我会收到此异常,以及如何解决此问题?

谢谢。

编辑

这是我得到的堆栈跟踪。

System.ArgumentException:值不在预期范围内 范围。在 System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 错误代码,IntPtr 错误信息)在 NAudio.Wave.WasapiOut.Init(IWaveProvider waveProvider) 在 NAudio.Wave.WaveExtensionMethods.Init(IWavePlayer wavePlayer, ISampleProvider sampleProvider, Boolean convertTo16Bit) at GSound.Audio.Player..ctor(Int32 Channels, Int32 Device) 在 E:\Dev\GSound_Wasapi\Projects\GSound\Audio\Player.cs:line 220 at GSound.Audio.Handler..ctor(Config TheConfig) 在 E:\Dev\GSound_Wasapi\Projects\GSound\Audio\Handler.cs:第 78 行 GSound.UIData..ctor() 在 E:\Dev\GSound_Wasapi\Projects\GSound\UIData.cs:第 63 行

我认为问题出现在 AudioClient.Initialize 调用中,该调用会生成 E_INVALIDARG 错误。这表明 WasapiOut 生成的格式值存在问题,或者客户端属性存在问题。我将研究这两个问题,但任何指针都会有所帮助。

再次感谢您。

【问题讨论】:

WASAPI 设备不一定允许您打开多声道音频(即 > 2 声道)。我自己当然没有做到这一点。使用 ASIO,您可能会取得更大的成功 有趣,所以即使选定的设备通过 MMDevice.Properties PKEY_AudioEndPoint_PhysicalSpeakers 掩码表明它有 4 个扬声器,实际上并不能保证访问它们。我必须看看我是否可以获得 ASIO 驱动程序我们正在使用的声卡。除了尝试了解有关 Wasapi 的更多信息,因为这看起来很奇怪。 【参考方案1】:

我已经让 4 声道音频在一个系统上工作(仍然需要在另一个系统上进行测试,但不明白为什么它不会。)

做了以下调整:

我删除了 MultiplexingSampleProvider 并更改了我的自定义 SampleProvider 以通过仅将信号数据复制到所需通道并将 0 数据复制到其他通道来处理多通道输出。问题之一是 MultiplexingSampleProvider 使用输入样本提供者波形作为其输出,包括所述输入样本提供者的通道数。由于最初的自定义样本提供程序是单声道,当我尝试将其与 4 个通道一起使用时,多路复用器会出错。我想知道重写多路复用器以改用自己的波形有多难,这与输入格式相同,但通道号是通过构造函数设置的。

MultiplexingSampleProvider 和 WasapiOut 类的另一个问题是它们不处理 WaveFormatExtensible 类,我最终修改了 MixingSampleProvider 和 SampleToWaveProvider 类以允许 WaveFormat.Encoding 为可扩展类型(子格式 MEDIASUBTYPE_IEEE_FLOAT)为以及 IeeeFloat。

/// <summary>
/// Creates a new MixingSampleProvider, with no inputs, but a specified WaveFormat
/// </summary>
/// <param name="waveFormat">The WaveFormat of this mixer. All inputs must be in this format</param>
public MixingSampleProvider( WaveFormat waveFormat )

    if( waveFormat.Encoding == WaveFormatEncoding.Extensible )
    
        if( ( ( WaveFormatExtensible )waveFormat ).SubFormat != NAudio.Dmo.AudioMediaSubtypes.MEDIASUBTYPE_IEEE_FLOAT )
        
            throw new ArgumentException( "Must be already floating point" );
        
    
    else if( waveFormat.Encoding != WaveFormatEncoding.IeeeFloat )
    
        throw new ArgumentException( "Mixer wave format must be IEEE float" );
    
    sources = new List<ISampleProvider>( );
    WaveFormat = waveFormat;

我做的最后一件事是向 WaveFormatExtensible 添加一个属性,以允许我设置 dwChannelMask 设置。此设置向系统指示实际使用哪些扬声器进行输出,在我的例子中是 0x33(FL、FR、RL、RR 扬声器)。普通 WaveFormatExtensible 构造函数假定 dwChannelMask 将设置为 0x7,(FL、FR、FC、LowFreq 扬声器),因为这是前 4 个扬声器值。通过设置 dwChannelMask,我可以指示要使用的扬声器。

/// <summary>Gets or sets the channel mask.</summary>
/// <value>The channel mask.</value>
public int ChannelMask

    get
    
        return dwChannelMask;
    
    set
    
        dwChannelMask = value;
    

我会说这是处理音频和音频编解码器的非常有趣的一课。

希望这对其他人有所帮助。

再次感谢您。

【讨论】:

以上是关于NAudio 与 MultiplexingSampleProvider 和 WasapiOut的主要内容,如果未能解决你的问题,请参考以下文章

NAudio - WaveOut 与 WaveOffsetStream 一起使用时不会引发 PlaybackStopped 事件

VST.NET 与 NAUDIO(vstaudiobuffer 与 pcmstream 缓冲区)

wav 文件连接异常与 naudio 库

有没有办法将 NAudio.Lame 与 Xamarin (Android/iOS) 应用程序一起使用?

如何使用 NAudio 将两个 wav 音频文件与 30 秒的白色声音连接起来

为啥我的 NAudio FFT 结果与 MATLAB 相差 4 倍?