One of the most exciting things about Cantabile 3 is its new audio engine. Just about every aspect has been re-engineered to best suit Cantabile’s requirements going forward.
Improved Audio and MIDI Routing
One of the main things I wanted to fix in this version of Cantabile is audio and MIDI routing. Cantabile 2’s system of using a master bus and manually connecting plugin channels to that bus, works and is reasonably flexible, but can be tedius to setup.
In Cantabile 3, the master bus is replaced with the concept of “ports”. Objects are connected together by creating routes from an output port on one object to an input port on another. The same concept is used for both audio signals and MIDI data. All ports can accept multiple connections.
Audio routes have a gain setting (ie: partial sends) while MIDI routes support the same filtering and matching options as Cantabile 2’s MIDI routing table. MIDI routing has been improved with better tracking of held notes and the ability to automatically release held notes when routes are disconnected.
To properly support sub-session switching the routing mechanisms have been designed to handle multiple simultaneous changes. Combined with Cantabile Performer’s improved sub-session control of routes you can now configure two sub-sessions to have completely different route settings and Cantabile will smoothly transition between them.
All this means simpler, but more flexible configuration of your sessions.
Physical Hardware Abstraction
Physical hardware — both audio and MIDI — is now abstracted behind a set of virtual ports. This means you can completely reconfigure your hardware and so long as you keep the same port configurations your sessions will continue to work.
For example, instead of connecting your session to a physical device like “Roland PCR-M50”, you create a virtual MIDI port (in settings) called say “Main Keyboard” and map it to the hardware device. In your session you refer to the device as “Main Keyboard”. Now suppose your PCR keyboard dies, just go into settings, remap “Main Keyboard” to your new device and away you go!
One of the main things that the audio engine has to deal with is thread concurrency — when two parts of the program want to work on the same piece of data at the same time.
(If you don’t know what a thread is, think of it as a piece of software doing some particular task — it could be the audio driver asking for the next block of audio, or it could be the code that handles the user clicking a button to suspend a plugin. What should happen if the plugin is suspended right in the middle of processing an audio cycle?)
The easiest approach to these issues is to use a lock. While one thread is working on something, set a lock that blocks the other thread until it’s finished. This approach works well, except in the case where the audio driver gets locked out for too long. The result: audio drop outs. Not good.
In Cantabile 3, the audio engine is completely lock free so no matter what the user-interface or other parts of the program are doing the audio processing will continue on — no matter what.
Well almost. There are still some cases where Windows can interrupt a high-priority thread when ideally it wouldn’t. Look up Deferred Procedure Calls, or DPC’s for more on this.
Parallelism is the ability for a multi-core machine to process two or more things at once ie: in parallel.
Cantabile 2 supports multi-core processing by processing non-connected racks in parallel. This provides a good boost in performance but an entire rack can be a fairly big chunk of work which in itself can’t be spread across multiple processor cores.
Cantabile 3 improves on this by breaking down those big tasks into much smaller pieces of work — going right down to mixing individual audio channels in parallel. The result is better use of the available processing capabilities of your machine.
Optimized Audio Mixing
Cantabile 3 uses the same highly optimized audio mixing routines as Cantabile 2, but their use has been streamlined.
Applying mix levels on the audio signal path is now delayed for as long as possible. If it can be delayed until the actual point it’s mixed with another signal, applying the mix level and mixing the two audio signals can be done in one operation.
The benefit of this is that multiple audio mixers can be chained together with negligible performance overhead. This is important for supporting other features of the engine in a simple manner.
Audio Driver Support
Cantabile 3 drops support for DirectSound (it never worked well anyway), but gains support for WASAPI drivers.
Also, it will (hopefully) support multiple audio drivers at the same time — even if they’re on different physical clocks and/or running at different sample rates.
For devices running on a different physical clock, it does micro-resampling to keep everything in sync — so even after hours of use, all your signals will stay perfectly synchronized (and no glitches while re-syncing).
I’ve got a proof of concept of this working and it seems to work well.
Potential for Multiple Simultaneous Sessions
There’s nothing in the new audio engine core that precludes loading more than one session at a time.
In practice I’m not really sure how this would work, but I’ve been thinking about the idea of allowing a main session to load other sessions as linked in racks. I need to think on this more but the goal would be to improve re-usability of sessions and racks.
Smaller, Lighter, Better
A lot of code and responsibility has been moved out of the core audio engine making all its components smaller, lighter and faster. This also means it’s less likely to contain bugs and easier to maintain.
Cantabile 2’s audio engine is about 60,000+ lines of C++ code. For Cantabile 3 it’s still C++, but I’ve trimmed it down to about 25,000 lines (plus supporting C# code).
Aside from these major changes, there have been dozens of other minor improvements which I won’t go into (mostly technical details).
As you can probably tell, I’m pretty excited about this and would love to hear your thoughts either in the comments, or you can contact me here.