This project has moved. For the latest updates, please go here.

WASAPI recording device with more then 2 channels

Jun 25, 2014 at 12:11 PM
Hello,
I faced a problem with recording loopback device having more then 2 channels
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");
            }
Is there any walk around this problem? Can I change MMDevice wave format?
Jun 27, 2014 at 8:42 AM
Edited Jun 27, 2014 at 8:43 AM
I investigated 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;
            var wfe = waveFormat as WaveFormatExtensible;
            if (wfe != null)
            {
                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
            //var wfe = waveFormat as WaveFormatExtensible;
            //if (wfe != null)
            //{
            //    try
            //    {
            //        waveFormat = wfe.ToStandardWaveFormat();
            //    }
            //    catch (InvalidOperationException)
            //    {
            //        // couldn't convert to a standard format
            //    }
            //}
So 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 I'm getting data. Though I didn't find what to do with this format yet. Actually I need only two channels left and right.
Any suggestions aprpeciated.
Coordinator
Jun 27, 2014 at 8:48 AM
OK makes sense. The conversion to a standard format was because lots of users write the WasapiCapture direct to WAV file using the WaveFormat, but if it is a WaveFormatExtensible (which WASAPI always seems to use), then a lot of players won't play the file).

If you only need two channels, then you need to keep every 8 bytes (two 32 bit samples) and throw away 16 (remaining four channels).
Jun 27, 2014 at 8:58 AM
The problem is that I don't know in advance what will be format. 1 channel, 2 or 6,8. As I'm recording both Mic and speakers I downmixing to 1 channel speakers and to another mic. Sometimes I use MediaFoundationTransform to adjust Samplerate
I'm wandering if MediaFoundationTransform can help me with this transformation as well?
Jun 27, 2014 at 1:38 PM
It looks like MediaFoundationTransform is the solution
  • I'm leaving the original format in WasapiCapture as shown above
  • saving data to buffer
  • passing it through MediaFoundationTransform. At the end I have format I need with number of channels I need.
Thanks a lot Mark for creating such a great library
Coordinator
Jun 27, 2014 at 1:40 PM
great, glad you found a solution