Multiple WaveIn MMException

Nov 27, 2012 at 8:09 AM

Hi all,

I must mix multiple wavein sources from different wavein devices for switching the output of mixer to another waveOut device.

Also, I must mix udp source wave streams with wavein streams, too.

First of all, I have decided to code the analog part like this below.

public void LoadWaveInToMixer(int deviceNumberIN)           

{

WaveIn ss = new WaveIn();               

ss.DeviceNumber = deviceNumberIN;     //always different device numbers           

ss.WaveFormat = new WaveFormat(8000, 16, 2);               

ss.StartRecording();                               

WaveInProvider wp = new WaveInProvider(ss);               

WaveProviderToWaveStream ws = new WaveProviderToWaveStream(wp); 

WaveChannel32 wc = new WaveChannel32(ws);

mixer.AddInputStream(wc);  //WaveMixerStream32 object

if (mixer.InputCount == 1)                

{                   

waveOutDevice.Init(mixer);                   

waveOutDevice.Play();               

}

}

 

My problem is if I add second waveIn device to the mixer(call this functon twice), I am getting and MMEXception (already allocated)

I have set deviceNumberIN to different device numbers every time I call this function. I have collected devices present in the system at the beginning of the program.

Thanks,

Coordinator
Nov 27, 2012 at 1:07 PM

what device IDs are you using? Do you definitely have two soundcards?

Nov 27, 2012 at 2:14 PM
Edited Nov 27, 2012 at 2:23 PM

No, I have one soundcard, but WaveIn.DeviceCount equals three. (deviceIDs 0,1,2, respectively)

WaveIn.GetCapabilities(i).ProductName and is different for all. (Microphone1, Microphone2 and LineIn)

Should I have to have more than one sound card for same time recording independently from two inputs?

Also, another question: my requirement is to capture 16 analog sound inputs independently, and I am planning to purchase two sound cards with 8 wave-in channels each.

Can't I capture these input channels independently using NAudio?

Should I have to buy 16 sound cards? (That is impossible)

Nov 27, 2012 at 2:50 PM

Also, my problem exists with .NET Voice Recorder demo project. (for true understanding)

If I execute VoiceRecorder.exe while an other instance is running, it crashes when I try to record. 

As you know, recording devices are listed at the startup screen.

Three devices listed for recording device at the demo screen.(like my project)

My test case is below:

1)Run voicerecorder.exe

2)Select first device (Microphone2)

3)Start recording

4)While first exe is running, run second voicerecorder.exe

5)Select second device listed (Microphone1)

6)Start recording

7)Crash.

 

 

Coordinator
Nov 27, 2012 at 2:55 PM

It is completely down to your soundcard manufacturer's drivers whether they allow you to open the same device for recording more than once. Why would you need to in any case? They would record the same audio.

If you have an 8 input soundcard, it again depends on the drivers as to whether it appears as several stereo cards, on one 8 input card. For this type of use, you'd probably be better off using WASAPI or ASIO than WaveIn.

Nov 27, 2012 at 3:01 PM

Thanks for your fast reply,

 

My requirement is:

Record 16 different/independent analog sounds by a standard PC + soundcards by using WinAPI.

I think I must select the appropriate card for this. Do you have any advice or experience about this?

Coordinator
Nov 27, 2012 at 4:56 PM

You will have to do some research on the drivers that come with the soundcard. When you say WinAPI, so you mean the WaveIn functions? If so, the way the drivers present themselves to Windows will be crucial. Often multiple-input soundcards don't bother too much with making all their features available with the old waveIn functions as they expect you to be using ASIO, WDM or WASAPI.

Nov 28, 2012 at 1:11 PM
Edited Nov 28, 2012 at 1:12 PM

Hi again,

I have changed the code and recorded from one input channel with WASAPI like RecordingPanel.cs. And then I have selected second microphone and recorded successfully with WASAPI. (changing deviceNumber on the second line below).

 

MMDeviceEnumerator deviceEnum = new MMDeviceEnumerator(); //three devices listed
MMDevice wspidevice = deviceEnum.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active)[deviceNumber];//changed this line for every other device, respectively 0,1,2
waveIn = new WasapiCapture(wspidevice);

 

But again if I tried to record two inputs at the same time, same problem has been existed.

I think the problem is regardless of the method or objects used (traditional WaveIn, or WASAPI can't work without the soundcard drivers' ability).

The main problem is all about windows detection of souncards' channels. All input channels must be detected as a seperate device. 

Am I thinking true? Or in any case(regardless of the driver), if I use WASAPI, it should work?

Thanks again.

Coordinator
Nov 28, 2012 at 1:13 PM

Windows won't present the channels as separate devices unless the soundcard driver has set it up that way. The best way is to capture all your soundcard inputs at once, and route the captured audio separately within your program.

Nov 28, 2012 at 1:20 PM

MMDeviceEnumerator deviceEnum = new MMDeviceEnumerator(); 
MMDevice wspidevice = DeviceEnum.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active) [deviceNumber];
waveIn = new WasapiCapture(wspidevice);
waveIn.DataAvailable += OnDataAvailable;
waveWriter = new WaveFileWriter(fileName, waveIn.WaveFormat);

private void OnDataAvailable(object sender, WaveInEventArgs e)
            {
                if (waveWriter == null) return;
                waveWriter.Write(e.Buffer, 0, e.BytesRecorded);
                waveWriter.Flush();
            }

I think that routing will be done in OnDataAvailable event, by checking sender object? Am I true, or is there an another way to do that?

Coordinator
Nov 28, 2012 at 1:22 PM

yes, your samples will come in interleaved. (one sample for channel 1, one sample for channel 2, one sample for channel 3) etc

Nov 28, 2012 at 1:24 PM

Thanks a lot Mark. I will try.

Coordinator
Nov 28, 2012 at 1:25 PM
Edited Nov 28, 2012 at 1:25 PM

so you could write code like this if you had an array of waveFileWriters one for each channel:

 

private void OnDataAvailable(object sender, WaveInEventArgs e)
{
    int bytesPerSample = 2; //(for 16 bit, set to 4 for float)
    int offset = 0;
    while (offset < e.BytesRecorded)
    {
        for (int n = 0; n < channels; n++) 
        {
            waveFileWriter[n].Write(e.Buffer,offset,bytesPerSample);
            offset += bytesPerSample;
        }
    }
}