Using CamillaDsp with a Motu-M4 as a Crossover

Mark Zachmann
Home Wireless
Published in
10 min readMay 10, 2023

--

Traditionally, loudspeakers have internal passive crossovers to funnel highs to tweeters and lows to woofers. This article is about using a Motu-M4 as an electronic crossover to drive multiple power amplifier signals into each individual speaker driver.

Motu-M4

TLDR;

This was a difficult project to get working completely right. The goal is an unattended {Motu-M4 + Computer} that acts like an active crossover. After trying Raspberry Pi and Windows PC, I ended up with a Mac M1 Mini as the ONLY good working M4 solution.

POSTSCRIPT: Now that Raspberry Pi 4’s are available to purchase again I bought one and tried it with CamillaDsp using Ubuntu 23.04 and it seems to be working perfectly — after a day of trying it out. The summary of how to get it working in AudioScienceReview is excellent.

Background

I started this project 12 years ago and the loudspeakers have been sitting waiting for technology to catch up.

Two good historical examples of inexpensive (<$500) packaged solutions are the MiniDsp 2x4 (2015) and the Dayton Audio DSP-408 (2018). These are programmable active crossovers, but even as the best quality of their time barely listenable.

A passive crossover contains high voltage/power resistors, inductors, and capacitors and funnels the high-power audio signals to loudspeaker drivers. Unfortunately the parts are so large and so expensive that crossovers are generally so-so.

In my current loudspeaker I use a simple 2nd order passive crossover for the tweeter and midranges (the one in the diagram below, actually) and then use an active crossover to funnel to the ‘speaker’ or the woofers. Just one inductor for a mediocre woofer crossover would cost about $50 (the lower the frequency the greater the cost).

Two ways to drive one two-way loudspeaker

By using the M4 instead of a simple passive crossover, we can room-correct and time-align the drivers and … and end up with almost a flat frequency response curve. This is a difficult task and it takes very good A/D and D/A converters and a fast DSP/CPU to get high quality audio.

It’s only been the last year or so (I write this in 2023) where you can buy off-the-shelf equipment to produce transparent sound.

Other Choices

Parts Express has an entire line of amplifiers (from Dayon-Audio/Sure Electronics) that include an on-board 2x4 DSP subsystem (A/D -> DSP -> D/A). Example is the Dayton Audio KABD-250 2 x 50W.

Dayton Audio KABD-250

The newer MiniDsp units are very high quality and expensive. The Dayton Audio stuff is likely to be mediocre. The original Minidsp2x4, the DSP408 , and the KABD boards all use an ADAU1701 chip — which is pretty much 16bit x 48 or 44.1KHz with very mediocre A/D and D/A. Rather moderate fidelity.

The Loudspeakers

The testing speakers are a traditional MTM with woofer using mainly Parts-Express drivers.

A stereo and TV

Speaker detail

Speaker detail with mid/tweeter crossover

The speakers have one tweeter, two mid-woofers, and one very large woofer. The mids/tweeter use the passive crossover on the speaker top. It would produce better audio to use a Motu M6 with 3 amplifier stages per loudspeaker (removing the passive crossover) but this much-less-expensive design does nearly as well with 2 amplifier stages per loudspeaker and it’s a great test of the approach.

Which OS to Use

CamillaDSP is a very nice application from Henrik Enquist that is perfect for using the M4 as a crossover. It’s cross-platform (PC/Mac/Pi) and supports very complex crossovers and automatic room-correction.

Pi

Almost everyone I saw online supported using a Raspberry PI with CamillaDSP to do a crossover. I tried and tried with a PI3 B+ and just like most of my complex PI projects it failed.

First, the Raspbian PI OS itself is unstable. I had sporadic crashes and in one case the software started an infinite loop screaming into the loudspeakers — not something my wife (or I) want. Also, no matter what I did, it sounded like garbage — the PI is noisy, too slow, and the end result sounded just awful — clicks, pops, dropouts, and breathing.

After this horror show and waiting a year for availability, I was able to buy and try a Pi 4B with Ubuntu 23.04 and wonder of wonders it worked like a champ. It’s using about 16% of the CPU so there’s plenty of excess capacity. Note that the Pi4 will overheat in a standard closed or even open box without a fan. Running Ubuntu server rather than desktop saves about 10 degrees but it still overheats slowly without a fan.

Windows PC

After the PI I tried using a MAC and had enough issues that I then tried a Windows PC — an Intel NUC. The NUC is a wonderful computer but the M4 windows (WASAPI) drivers are just bad. Motu provide an ASIO driver that is 4-channel, but not WASAPI. Instead they publish two stereo devices — so I had to run two instances of CamillaDSP that caused all sorts of maintenance and synchronization issues and again it sounded just awful and fuzzy. If CamillaDSP supported ASIO this might have been an ok solution.

Mac Mini

I returned to my Mac M1 Mini as the best-sounding after PI and PC failures. The Mac driver is solid (both the default Mac USB driver and the MOTU specific M4 driver) and the M1 is incredibly fast so no performance issues.

The biggest issue with the M1 was getting the software to run at startup. None of the documentation is accurate about using MacOS — anywhere — so it took three days to write a simple reliable PLIST script.

Mac Mini connected up with the M4

Finally : using the Mac Mini or Raspberry Pi 4B

So, it finally works reliably. There are two ways to use this.

  1. Use a good Bluetooth receiver and send output to the analog inputs to the M4 and split them into 4 outputs (as shown above). The M4 A/D converters are very good and the quality doing it this way is excellent.
  2. Stream via Wifi to the Mac/Pi. The signal flow is then Mac->USB->M4 outputs with no A/D conversion required and no analog noise input.

Bluetooth is really too slow for great audio quality and the better LDAC/Aptx-HD decoders aren’t available open-source. Using a retail Bluetooth receiver adds AptX-HD and Sony LDAC support — which are good quality.

The problem with WiFi streaming is that the only supported quality way to send music to a Mac is via AirPlay so my iPad could stream well to the Mac and nothing else in the house (Windows PC, Android Phones) could talk to it at all (except via just awful-sounding SBC). Thanks Apple.

Streaming the Raspberry Pi via WiFi has no Airplay 2 support and no Chromecast support, so it’s pretty much a non-starter.

I ended up with, for now, using the M4 analog inputs with a Bluetooth receiver, so fundamentally it acts like a very high quality, very smart Minidsp 2x4 box.

There are just two important files: the CamillaDSP configuration for the crossover and the startup file for CamillaDSP that runs it at bootup.

The crossover

This crossover uses low pass filters for the woofers and high pass filters for the mid/tweeter speaker along with a small boost in the midrange for the mid/tweeter. I run everything at 96Khz so filtering is smooth. This is a pretty simple crossover for test purposes.

The capture device is the M4 inputs (analog lines 1,2 here) and the output is all 4 outputs of the M4. The M4 is driven by a nice Bluetooth receiver line output — adding solid LDAC and AptX support.

devices:
adjust_period: 3
capture:
change_format: false
channels: 4
device: M4
format: S32LE
type: CoreAudio
capture_samplerate: 96000
chunksize: 1024
enable_rate_adjust: true
enable_resampling: false
playback:
change_format: false
channels: 4
device: M4
exclusive: true
format: S32LE
type: CoreAudio
queuelimit: 4
rate_measure_interval: 1
resampler_type: Synchronous
samplerate: 96000
silence_threshold: -85
silence_timeout: 10
stop_on_rate_change: false
target_level: 0
filters:
HiP:
parameters:
freq: 80
q: 0.7
type: Highpass
type: Biquad
LoP:
parameters:
freq: 100
q: 0.7
type: Lowpass
type: Biquad
Peak:
parameters:
freq: 300
gain: 3
q: 0.4
type: Peaking
type: Biquad
mixers:
copy:
channels:
in: 4
out: 4
mapping:
- dest: 2
mute: false
sources:
- channel: 1
gain: -12
inverted: false
mute: false
- dest: 3
mute: false
sources:
- channel: 1
gain: -12
inverted: false
mute: false
- dest: 0
mute: false
sources:
- channel: 0
gain: -12
inverted: false
mute: false
- dest: 1
mute: false
sources:
- channel: 0
gain: -12
inverted: false
mute: false
pipeline:
- name: copy
type: Mixer
- channel: 0
names:
- HiP
type: Filter
- channel: 2
names:
- HiP
type: Filter
- channel: 1
names:
- LoP
type: Filter
- channel: 3
names:
- LoP
type: Filter
- channel: 0
names:
- Peak
type: Filter
- channel: 2
names:
- Peak
type: Filter
View of the crossover

Here channels 0,2 are the primary speaker and 1,3 are the woofers. It makes more sense to have 0,1 be the primary speaker and then the front panel volume control controls the ‘speakers’ (it only adjusts channels 1&2) but this was done to match the Windows setup for testing.

The startup file

Nowhere did I see this documented, but it turns out that to have an app autostart the simplest approach is to just copy the PLIST script to /Library/LaunchAgents. They call it a script but it’s really an XML config file to run an app with multiple arguments.

That’s it. The PLIST file is below. It just invokes a shell script (see below).

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN
http://www.apple.com/DTDs/PropertyList-1.0.dtd >
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.camilladsp</string>
<key>ProgramArguments</key>
<array>
<string>/bin/zsh</string>
<string>/Users/me/camilladsp/runbkgd.sh</string>
</array>
<key>WorkingDirectory</key>
<string>/Users/me/camilladsp</string>
<key>StandardOutPath</key>
<string>/Users/me/camilladsp/camilladsp.log</string>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>

Note the RunAtLoad key (without which nothing actually runs) and the StandardOutPath to set stdout the ‘right’ way. Also, the use of WorkingDirectory to make the shell scripts relocatable.

The shell script in ~/camilladsp that gets called by the PLIST startup ‘script’.

sleep 10
date >>runme.txt
echo running camilladsp >>runme.txt
while TRUE
do
./camilladsp ./configs/Crossover.yml -p 1234 --logfile ./camilladsp.log
done

The script waits 10 seconds at boot for the audio subsystem to load and then it runs camilladsp with the crossover yaml file. Since this crashes every now and then it does a KeepAlive by rerunning on crash. It’s possible to set the working directory and not need the long paths.

The CamillaDsp GUI

The CamillaDSP user interface is slick and it runs via a web browser so portable and doesn’t require you to login to the Mac. I won’t duplicate the excellent installation instructions (see the camillagui-backend).

The CamillaDSP Gui

Bitperfect Listening

Bitperfect listening is when the receiver produces digital results equal to the original binary data. This is starting to be available but the first offerings are SPDIF (Wiim Pro/Plus). In order to support this I’ve written a short Python application that sets the CamillaDsp file based on the incoming capture rate. The SPDIF to USB converter has no way to read the format so this works instead.

See here on Github

Results

Here is the original (no woofer, no correction) frequency response curve. The low end is not accurate because of room modes and I did not do a nearfield test. Still, this music sounded like this picture — it has a serious midrange suckout and not much low-end.

Mid/Tweeter response curve

Second Speaker Build

It turned out that the way I did dual woofers just didn’t work well above. The passive crossover for the primary drivers (woofer/tweeter) had the usual passive crossover problems (impedance matches, low-order, …). I also hate the dispersion issues with D’Appolito designs when not in a TV room so I decided to build a pair of 2-ways with better drivers. This way it would have no passive crossover.

This design uses the Parts-Express SIG-180 and RST-28A drivers.

They are a little light on the very deep bass but otherwise excellent.

A 2-way design

The CamillaDsp crossover looks like this:

The 2-way crossover

Here:

  • LoP = lowpass 2nd order (so two==4th order) at 1400
  • HiP = highpass 2nd order at 1400
  • TimeAlign = short delay for the tweeter to align to woofer
  • Shelf — 2dB adjustment for baffle effect starting at 350Hz
  • Bassplus — test code for bass adjustments (ignore)

I did a crude SPL test with the speakers a couple of feet from any wall. I think floor bounce causes a slight issue at about 850Hz. I design a little high frequency droop…

Quick SPL Test in-room

--

--

Mark Zachmann
Home Wireless

Entrepreneur, software architect, electrical engineer. Ex-academic.