NAudio with MultiplexingSampleProvider和WasapiOut

时间:2017-08-07 19:26:41

标签: c# naudio wasapi

我一直在与NAudio合作开展一个C#项目,我需要在4通道系统上向特定扬声器发送特定的音频信号。基本上,我需要发送环境声音'到左后方扬声器,前面板显示声音'到前右扬声器,以及'预先录制的说明'到左前方的扬声器。 我目前的设计适用于台式电脑支持的2通道设置,但当我尝试将其扩展到测试硬件上的4个通道时,我不断收到以下错误:'值不在预期范围内。&#39 39;当我打电话给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),这是我得到的值&#39;值不在预期的范围内。&#39;异常。

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

谢谢。

修改

这是我得到的堆栈跟踪。

  

System.ArgumentException:值不在预期范围内   范围。在   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:第220行   GSound.Audio.Handler..ctor(Config TheConfig)in   E:\ Dev \ GSound_Wasapi \ Projects \ GSound \ Audio \ Handler.cs:第78行at   GSound.UIData..ctor()in   E:\ Dev \ GSound_Wasapi \ Projects \ GSound \ UIData.cs:第63行

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

再次感谢你。

1 个答案:

答案 0 :(得分:0)

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

进行了以下调整:

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

MultiplexingSampleProvider以及WasapiOut类的另一个问题是它们不处理WaveFormatExtensible类,我最后修改了MixingSampleProvider和SampleToWaveProvider类,以允许WaveFormat.Encoding为Extensible类型(subFormat MEDIASUBTYPE_IEEE_FLOAT)as以及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;
    }
}

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

希望这有助于其他人。

再次感谢你。