Cinder-PortAudio: PortAudio as an alternative audio backend


#1

Hi all,

I’d like to announce that we have made public cinderblock and new audio backend for ci::audio that wraps PortAudio:

The main motivation for adding PortAudio as a possible backend is to gain support for Windows / Steinberg ASIO drivers, which have a long a much longer history with audio interface vendors over the native Windows WASAPI drivers. Moreover, we have an upcoming project that uses Dante equipment, which only supports ASIO on Windows. As such, we’ve only tested this so far on Windows, but PortAudio supports many other OSes and backends and enabling those would mostly be a matter of setting up the project configuration.

Using Cinder-PortAudio is straightforward: once the cinderblock is setup in your project, you make one call before any other audio calls:


audio::ContextPortAudio::setAsMaster();

There is also a basic sample and TinderBox template included in the repo.

Why isn’t Cinder-PortAudio included in core? The main reason is that when originally writing ci::audio, we chose to use platform specific APIs directly to minimize thirdparty code and remove the extra layers between the user’s application and whatever OS specific audio backend exists. That said, portaudio supports almost all popular OSes and backends out there, so it can be a nice solution if cinder core doesn’t yet provide support for one of those, for example if you need JACK support in linux or ASIO on windows.

Furthermore, while enabling ASIO is straightforward, you still need to personally agree to Steinberg’s licensing agreement and install the sdk into the right location, so we can’t use ASIO as an audio backend by default. For more directions on how to set up ASIO, please see this section of the readme.

Lastly, I also want to send a big thanks to Rare Volume, who helped to fund this development with the aim of providing it to the larger Cinder community.

cheers,
Rich Eakin


Audio Device selection using Dante Virtual Soundcard
Audio Device Selection with WMFVideo using Dante/ASIO
#2

Thanks again for this work Rich - ASIO support in particular is really key for Cinder, and has come up in project work for us quite a bit lately in the context of compatibility with Dante networks in particular.

Looking forward to using this.


#3

Where were you 2 years ago? :wink:

Thanks for the hard work, PortAudio seems to cover a lot of bases, which is especially helpful for those of us who suck at audio programming, namely myself.

Cheers,

A.


#4

@lithium.snepo hey I mentioned then that if it were my project then I would take the portaudio route and that’s what I did. :smile:

@petros recently added support for CMake, so now this should be usable on all Posix systems. Thanks Petros! If anyone can test and report back issues or success we’d be grateful.

cheers,
Rich


#5

This is great! Cinder audio wasonly recognizing 2 channels instead of 4 on my multichannel device. It was also running an odd amount of 480 framesPerBlock. Port Audio fixed multichannel functionality on my device and is now only 128 framesPerBlock, lowering my latency. Thanks!
I had to enable in and out in the findDevicebyName function. Does this have something to do with duplexIO?

//DEVICE
//console() << audio::Device::printDevicesToString() << endl;
auto EIEDev = audio::ContextPortAudio::master()->deviceManager()->findDeviceByName("Akai EIE Pro ASIO Driver", true, true);//audio::ContextPortAudio::master()->deviceManager()->getDefaultOutput();
//INPUT
auto inNode = audio::ContextPortAudio::master()->createInputDeviceNode(EIEDev, ci::audio::Node::Format().channels(EIEDev->getNumInputChannels()));
//Output
ctx->setOutput(ctx->createOutputDeviceNode(EIEDev, audio::Node::Format().channels(EIEDev->getNumOutputChannels())));

#6

@Malfunkn Glad to hear it’s working for you. A Couple comments:

‘odd amount of 480 framesPerBlock’ - a little while ago I lifted the restriction of requiring power of two block sizes, as there wasn’t really any reason for it other than tradition. Windows WASAPI drivers ask for a default buffer of 10 milliseconds in whatever samplerate you have set, which is where the 480 comes from (if your samplerate is 48K).

About your code - it’s a bit of an odd design and I’d like to change it in the future when time permits, but you don’t actually need to use the audio::DeviceManager directly. You can instead use:

auto EIEDev == audio::Device::findDeviceByName( "Akai EIE Pro ASIO Driver" );

Or if you need separate input / output devices, you can use Device::findInputByName() and audio::Device::findOutputByName() instead. Does that answer your question?

Cheers,
Rich