2017-08-07 197 views
1

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

这里是导致问题的代码:

// 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与设置44.1kHz的,32位,1个信道一个WAVEFORMATEXTENSIBLE类。

一切工作,直到我打电话_OutputDev.Init(p_Volume),这是我得到'价值不在预期范围内'。例外。

任何想法,为什么我得到这个异常,以及如何解决这个问题?

谢谢。

编辑

这是堆栈跟踪我得到。

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生成的格式值出现问题,或与客户端属性有关的问题。我将检查这两个问题,但任何指针都会有所帮助。

再次感谢您。

+0

WASAPI设备不一定允许您打开多声道音频(即> 2个声道)。我当然没有设法达到这个目标。 ASIO –

+0

可能会有更多的成功,所以即使所选设备通过MMDevice.Properties指示PKEY_AudioEndPoint_PhysicalSpeakers掩盖了它具有4个扬声器,但实际上并未保证访问它们。我将不得不查看是否可以获得ASIO驱动程序我们正在使用的声卡。以及试图找出更多关于Wasapi,因为这似乎很奇怪。 – JonDemers

回答

0

我已经得到了4声道音频到一个系统上工作(还是需要测试另一个系统上,但不明白为什么它不会。)

下作了调整:

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

与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; 
    } 
} 

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

希望这可以帮助别人。

再次感谢您。