我一直在与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生成的格式值存在问题,或者客户端属性存在问题。我会检查这两个问题,但任何指针都会有所帮助。
再次感谢你。
答案 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;
}
}
我会说这是处理音频和音频编解码器的一个非常有趣的课程。
希望这有助于其他人。
再次感谢你。