2017-08-07 90 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; 
    } 
} 

我會說這是處理音頻和音頻編解碼器的一個非常有趣的課程。

希望這可以幫助別人。

再次感謝您。