我一直在与C#项目与NAudio一起工作,在那里我需要发送特定的音频信号给特定的扬声器在一个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是一个设置为44.1Khz、32位、1通道的WaveFormatExtensible类。
在我调用_OutputDev.Init( p_Volume )之前,一切都会正常工作,这就是我得到“值不属于预期范围”的地方。异常。
知道我为什么要得到这个例外吗?我怎样才能解决这个问题?
谢谢。
编辑
这是我得到的堆栈追踪。
System.ArgumentException:值不属于预期范围。在System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode,IntPtr errorInfo在NAudio.Wave.WasapiOut.Init(IWaveProvider waveProvider)在NAudio.Wave.WaveExtensionMethods.Init(IWavePlayer wavePlayer,ISampleProvider sampleProvider,Boolean convertTo16Bit在GSound.Audio.Player..ctor(Int32通道),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生成的格式值的问题,或客户端属性的问题。我将研究这两个问题,但任何指示都会有帮助。
再次感谢您。
发布于 2017-08-14 18:03:15
我已经获得了4声道音频工作在一个系统(仍然需要测试在另一个系统,但不知道为什么它不会)。
作了下列调整:
我删除了MultiplexingSampleProvider,并更改了我的自定义SampleProvider,只将信号数据复制到所需的通道,并将0数据复制到其他通道,从而处理多个通道的输出。其中一个问题是,MultiplexingSampleProvider使用输入示例提供者的波形格式作为其输出,包括所述输入示例提供者的信道数。由于最初的自定义示例提供程序是单通道,所以当我尝试将它与4个通道一起使用时,复用器会出错。我想知道重写复用器使用自己的波形格式有多难,这与输入格式相同,但通道号是通过构造函数设置的。
MultiplexingSampleProvider和WasapiOut类的另一个问题是它们不处理WaveFormatExtensible类,我最终修改了MixingSampleProvider和SampleToWaveProvider类,以允许WaveFormat.Encoding的类型是可扩展的(subFormat 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;
}
}我要说,这是一个非常有趣的教训,处理音频和音频编解码器。
希望这对其他人有帮助。
再次感谢您。
https://stackoverflow.com/questions/45554340
复制相似问题