带有 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;
}
}
我会说这是处理音频和音频编解码器的非常有趣的一课。
希望这对其他人有帮助。
再次感谢。
我一直在使用 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;
}
}
我会说这是处理音频和音频编解码器的非常有趣的一课。
希望这对其他人有帮助。
再次感谢。