How to properly close and reopen an audio input device (OSX)


#1

Hi,

I’m having some problems with the audio input device on OSX. I’m aware that osx only allows 1 input device to be opened, what I’m trying to do is to close the existing device and open a new one.

before I open the device I try to disconnect the nodes and reset the pointers:

if ( mMonitorNode )         { mMonitorNode->disconnectAll(); mMonitorNode->disable(); }
if ( mInputDeviceNode )     { mInputDeviceNode->disconnectAll(); mInputDeviceNode->disable(); }
mInputDeviceNode    = nullptr;
mMonitorNode        = nullptr;

is this correct or am I missing something?


#2

I just ran into the exact same problem. I also tried doing

ctx->disable();
ctx->disconnectAllNodes();

but it didn’t help.


#3

Both of those should do it. Just make sure that the InputDeviceNode's uninitialize() method is getting called (ex. put a breakpoint or log in it).

If you’re still stuck switching between input devices at runtime, please post a more complete example and list what’s going wrong. It does (or did last I checked, I’m not on OS X much these days) work with the test/_audio/DeviceTest app in the repo.

cheers,
Rich


#4

Hi,

Im having problems switching the audio input device on OSX too. Its probably something really silly, but i don’t see it (i only program for about 3 years now and haven’t yet learned everything about c++/ cinder yet).

So first of all some code:

// from the class declaration:
    audio::InputDeviceNodeRef inDev;
    audio::GainNodeRef inGain;

void LoopStationApp::setInputDevice( const audio::DeviceRef &device, int numChannels)
{
   if(inDev) {
        inDev->disconnectAll();
        inDev->disable();
        inDev = nullptr;
    }
    
    auto format = audio::Node::Format();
    format.channels( numChannels );
    
    inDev = audio::master()->createInputDeviceNode( device, format );
    
    inDev >> inGain; // Trying to reconnect, here is where i get an exception. Also tried inDev->connect(inGain), what should mean the same, i think
    inDev->enable();
}

The Error i am getting is a Bad Access Exception, thrown by the AudioObjectRemovePropertyListenerBlock (a Core Audio Function). I checked, that inGain is still there, it is not connected to any input anymore. I also compared my code to the code of the DeviceTestApp, but the code of the app is not working in my environment (i don’t know why, but i had the same problem with switching the outputDevice - that is working right now; although: The DeviceApp is running correctly). I also checked that i pass a device and that the reference is not empty.
Also strange is that when i setup everything, it all works fine. I can record anything - but when i try to change the device it does not work.
And one last thing: I don’t think the uninitilialize() method is called. But i did not find out how to make sure that happens too.

If there is anybody who has an idea what might be wrong or where to look, i would be really grateful! I am working on this problem for really a long time now.


#5

Try calling audio::master()->disable() before doing anything else. Your code above should work in theory, but there is some tricky multi-threaded stuff going on still - even after you’ve disconnected and nulled your input device there is still an audio graph running on a background thread.


#6

Thanks! Its working right away.


#7

Hey there - again!

Actually it seems the problem is still there, and even worse - i have the same problem with the device-Test too. I did not realise it until now because of a mistake: It seemed, the switching was working after adding the line rich.e was suggesting me, but actually i disabled the switching of Input Devices to avoid bugs in this area and i forgot to enable it again.

The Problem occurs every time, audio is first pulled from an input device and afterwards the audio device should be switched. An abortion is raised, without a specified exception.

Probably someone who has OS X should confirm this, then i should open an issue on GitHub.