带有 MultiplexingSampleProvider 和 WasapiOut 的 NAudio

NAudio with MultiplexingSampleProvider and WasapiOut

我一直在使用 NAudio 开发一个 C# 项目,我需要将特定的音频信号发送到 4 声道系统上的特定扬声器。基本上,我需要将 'Environmental sounds' 发送到左后扬声器,将 'Front Panel display sounds' 发送到右前扬声器,将 'Pre-recorded instructions' 发送到左前扬声器。 我当前的设计适用于我的台式计算机支持的 ​​2 通道设置,但是当我尝试在我的测试硬件上将它扩展到 4 通道时,我不断收到以下错误:'Value does not fall within the expected range.' 当我调用 WasapiOut.init() .我认为该问题是由 MultiplexingSampleProvider 以某种方式引起的,但我无法找出 why/how 来解决该问题。在我尝试加载它之前,我验证了我使用的 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 class,设置为 44.1Khz、32 位、1 通道。

一切正常,直到我调用 _OutputDev.Init( p_Volume ),这是我得到 'Value does not fall within the expected range.' 异常的地方。

知道我为什么会收到此异常,以及如何解决该问题吗?

谢谢。

编辑

这是我得到的堆栈跟踪。

System.ArgumentException: Value does not fall within the expected range. at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo) at NAudio.Wave.WasapiOut.Init(IWaveProvider waveProvider) at NAudio.Wave.WaveExtensionMethods.Init(IWavePlayer wavePlayer, ISampleProvider sampleProvider, Boolean convertTo16Bit) at GSound.Audio.Player..ctor(Int32 Channels, Int32 Device) in E:\Dev\GSound_Wasapi\Projects\GSound\Audio\Player.cs:line 220 at GSound.Audio.Handler..ctor(Config TheConfig) in E:\Dev\GSound_Wasapi\Projects\GSound\Audio\Handler.cs:line 78 at GSound.UIData..ctor() in E:\Dev\GSound_Wasapi\Projects\GSound\UIData.cs:line 63

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

再次感谢。

我已经获得了可在一个系统上工作的 4 声道音频(仍需要在另一个系统上进行测试,但不明白为什么不能。)

进行了以下调整:

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

MultiplexingSampleProvider 和 WasapiOut class 的另一个问题是它们不处理 WaveFormatExtensible class,我最终将 MixingSampleProvider 和 SampleToWaveProvider classes 修改为允许 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;
    }
}

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

希望这对其他人有帮助。

再次感谢。