Search code examples
c#naudiowasapi

NAudio WASAPI recording device with more then 2 channels throws unsupported format error


I faced a problem with recording WASAPI loopback device having 6 or 8 channels using NAdio library. E.g. Device has following wave format: 32 bit PCM: 44kHz 6 channels wBitsPerSample:32

public MMDevice Device;
private WasapiCapture _waveIn;

...

_waveIn = IsLoopback ? new WasapiLoopbackCapture(Device) : new WasapiCapture(Device);
_waveIn.DataAvailable += OnDataAvailable;
_waveIn.RecordingStopped += OnRecordingStopped;
_waveIn.StartRecording();

It crashes on StartRecording with "Unsupported Wave Format" error Error is coming from WasapiCapture.InitializeCaptureDevice() while it calls

if (!audioClient.IsFormatSupported(ShareMode, WaveFormat))
    throw new ArgumentException("Unsupported Wave Format");

The code works fine if I switch device to 2 channel using windows->control panel_>Sound settings Is there any walk around this problem? Can I somehow change Device mixformat on the fly


Solution

  • I found what is happening. There is a constructor of WasapiCapture class in NAudio library

    public WasapiCapture(MMDevice captureDevice)
    {
         syncContext = SynchronizationContext.Current;
         audioClient = captureDevice.AudioClient;
         ShareMode = AudioClientShareMode.Shared;
         waveFormat = audioClient.MixFormat;
    
         if (waveFormat is WaveFormatExtensible wfe)
             try
             {
                 waveFormat = wfe.ToStandardWaveFormat();
             }
             catch (InvalidOperationException)
             {
                 // couldn't convert to a standard format
             }
    }
    

    It is using WaveFormat.ToStandardWaveFormat(). I tried to comment out part which changes format to standard one

    // if (waveFormat is WaveFormatExtensible wfe)
    //     try
    //     {
    //         waveFormat = wfe.ToStandardWaveFormat();
    //     }
    //     catch (InvalidOperationException)
    //     {
    //         // couldn't convert to a standard format
    //     }
    

    In my case I just leaving original [NAudio.Wave.WaveFormatExtensible] = {32 bit PCM: 44kHz 6 channels wBitsPerSample:32 dwChannelMask:1551 subFormat:00000003-0000-0010-8000-00aa00389b71 extraSize:22}

    Now WasapiCapture.InitializeCaptureDevice() is running successfully and I'm getting data.

    • I created MyWasapiCapture class which is copy of original WasapiCapture except am code commented out
    • saving data to buffer as it is
    • passing it through NAudio.Wave.MediaFoundationResampler, which allow to resample and change number of channels. At the end I have format I need with number of channels I need.