The machine your measurement hardware is plugged into does not have to be the machine you sit at. Run Phonalyser server on the one that is wired to the converters and it becomes a bench: it owns the sound cards and the QA40x analyzer and serves them over the network to Phonalyser.web clients elsewhere. It has no window and needs no desktop - a Raspberry Pi or any headless box will do.
This chapter is the server half: getting one running and keeping it running. The client half - finding a bench, connecting to it and measuring through it - lives in Preferences ▸ Measuring through a Phonalyser server, and what happens on the wire is in Theory ▸ A bench across the network.
The server ships as its own download, one ZIP per platform - Windows x64 and x86, Linux x86_64 and aarch64, macOS Intel and Apple Silicon - beside the desktop application's installers. Unpack it anywhere and run it; there is no installer and nothing is written outside the folder until the server starts.
Inside each ZIP is one fat JAR plus the launchers for that platform. What you must provide is a Java 17 or newer runtime on the PATH - and nothing else: no JRE is bundled.
| Platform | What comes with it |
|---|---|
| Windows | phonalyser-server-x64.exe (double-click launcher),
phonalyser-server.cmd (the same in a console you can
read), install-service.cmd /
uninstall-service.cmd, and a natives\
folder carrying PortAudio (the WDM-KS path), libusb (the QA40x) and
csjsound (the WASAPI-exclusive JavaSound mixers). Keep
natives\ next to the launcher - it is the only place
searched. Without csjsound the server still runs but offers
shared-mode mixers only, so the EXCL: devices and the
high sample rates that depend on them disappear from the list. |
| Linux | phonalyser-server.sh,
phonalyser-server-service.sh and the QA40x udev rule
70-qa40x.rules. There is deliberately no
natives/: ALSA is reached through the Java runtime, and
libusb - needed only for a QA40x - comes from your distribution.
The JAR is architecture-neutral - the x86_64 and aarch64 ZIPs differ
in name only. |
| macOS | phonalyser-server.sh,
phonalyser-server-service.sh and
natives/ with libportaudio.dylib (CoreAudio)
and libusb-1.0.dylib. The Intel and Apple Silicon ZIPs
carry different dylibs - take the one that matches your Mac. A QA40x
needs no kernel driver here. |
-x64 / -x86 suffix
names what the bundle targets - which JRE the launcher looks for
and which architecture the DLLs in natives\ are - not the
launcher's own bitness. The 32-bit bundle insists on a 32-bit JVM, because
a 64-bit one would quietly find none of its DLLs, and it caps the heap at
1200 MB, as much as a 32-bit process can reliably reserve. A QA40x must
already be bound to the WinUSB driver, which happens once QuantAsylum's own
software has been run on that machine. phonalyser-server-x64.exe
phonalyser-server.cmd --name bench1 --port 8377
./phonalyser-server.sh
./phonalyser-server.sh --name bench1 --port 8377
Every launcher takes the same four arguments:
| Flag | Meaning |
|---|---|
--name <text> |
The name clients see in their server list and in the in use by note beside a device someone else holds. Defaults to the machine's host name. |
--port <port> |
One port carries everything - the control channel, the audio stream, the informational endpoints, the file upload and the web bundle. Default 8377. |
--bind <address> |
Listen on one interface only. Default: all of them. This is the one knob that limits who can reach the bench - see no authentication below. |
-d, --daemon |
Accepted, and every service definition passes it - but it changes nothing today: the server writes no console output in any mode, and the log file is written the same way with or without it. |
Ctrl-C stops it cleanly. The shutdown hook closes the audio lines and parks a QA40x analyzer at a safe attenuator setting - the same protection the desktop application performs on the way out. That is why a server is stopped rather than killed: an End Task leaves the analyzer at whatever sensitive input range the last measurement selected.
Clients find a server by UDP multicast on 239.255.83.77, port 8377/udp - the same number the server listens on, because UDP and TCP are separate port spaces. The announcement is link-local: routers do not pass it, so a bench on another subnet is never discovered and is added by its address in the client instead.
Allow that one port through the firewall, udp and tcp, or skip discovery altogether and type the address into the client by hand.
From an elevated command prompt:
install-service.cmd run as LocalSystem
install-service.cmd /user BENCH\alex run as a real account
install-service.cmd /user BENCH\alex --name bench1
Extra arguments are baked into the service. It is named PhonalyserServer and points at that folder, so the folder must not be moved or deleted afterwards. It is a genuine Service Control Manager service, hosted by WinSW: stopping it is a request, not a kill - WinSW sends a Ctrl+C and waits up to 20 seconds, so the shutdown hook runs and the analyzer is parked, which a scheduled task or an End Task would not do.
start : sc start PhonalyserServer
stop : sc stop PhonalyserServer
remove : uninstall-service.cmd
settings: services.msc, entry "Phonalyser server"
/user <account> so the service
loads that user's profile and sees the same devices that user does. Windows
needs the account's password before such a service can start and the script
deliberately does not handle passwords: after installing, open
services.msc ▸ Phonalyser server ▸ Properties ▸ Log On
▸ This account, type it, then Start. If even that does not show the card you
expect, do not fight the service - put a shortcut to the launcher in
shell:startup and it starts at logon inside your own desktop
session, where the audio stack is unambiguous. sudo ./phonalyser-server-service.sh install
sudo ./phonalyser-server-service.sh activate
sudo ./phonalyser-server-service.sh install --name bench1 --bind 192.168.1.20
install writes
/etc/systemd/system/phonalyser-server.service pointing at that
folder, creates the system user phonalyser, creates
/var/lib/phonalyser and /var/log/phonalyser, and
installs the QA40x udev rule; activate enables the unit and starts
it. Extra arguments given to install are baked into the unit, and the
folder must not be moved afterwards - the unit points straight at it.
status : systemctl status phonalyser-server
stop : sudo systemctl stop phonalyser-server
remove : sudo ./phonalyser-server-service.sh uninstall
The service user is given the audio and plugdev
groups by the unit itself, so nothing in /etc/group is edited.
systemctl stop sends SIGTERM, so the shutdown hook
runs and the analyzer is parked. uninstall leaves
/var/lib/phonalyser, /var/log/phonalyser and the
account alone: your calibration is data, not packaging.
./phonalyser-server-service.sh install
./phonalyser-server-service.sh activate
Do not use sudo. install writes a LaunchAgent at
~/Library/LaunchAgents/org.edgo.phonalyser.server.plist
pointing at that folder; activate loads it, and from then on it starts at
every login.
status : launchctl print gui/$(id -u)/org.edgo.phonalyser.server
stop : launchctl bootout gui/$(id -u)/org.edgo.phonalyser.server
remove : ./phonalyser-server-service.sh uninstall
bootout terminates normally, so the shutdown hook runs and the
analyzer is parked.| Platform | Log, cards and identity |
|---|---|
| Windows | One place, however it was started - console, LocalSystem service or
/user service alike:
%ProgramData%\Phonalyser\logs\phonalyser-server.log,
%ProgramData%\Phonalyser\devices.yaml,
%ProgramData%\Phonalyser\server-id. WinSW keeps its own
record of service starts and stops in the same
logs folder, beside the application's log rather than
instead of it. |
| Linux | From a terminal:
~/.config/Phonalyser/logs/phonalyser-server.log (or
/var/log/phonalyser when that is writable). As the
service: /var/log/phonalyser/phonalyser-server.log and
/var/lib/phonalyser for
devices.yaml and server-id - the
phonalyser account has no home directory of its own, so
the unit names those paths. |
| macOS | Both ways of starting it use one directory:
~/Library/Application Support/Phonalyser/ -
logs/phonalyser-server.log, devices.yaml,
server-id. |
On Windows that single machine-wide home is deliberate: a server is a
machine installation. The per-user %APPDATA%\Phonalyser
belongs to the desktop GUI, and a server sharing it would edit the desktop's
own card store - while the two service forms would each get a
different %APPDATA% and disagree with the console
run.
devices.yaml across. On Linux the same
applies between a terminal run and the systemd service, which have separate
data directories.A Phonalyser server does not ask for a password, and nothing on the wire is encrypted. That is a decision, not an omission: a bench instrument belongs on a network you trust - the room your measurement equipment is in - and adding credentials to a LAN instrument protocol would buy nothing the network does not already provide. Anyone who can reach the port can list the devices and take one.
So do not expose the port to the open internet. If the machine has more
than one interface, --bind the server to the one your bench
lives on and leave the rest unreachable.
With a server running, the whole client side is three steps and it is all in Preferences ▸ Audio:
<server> -> <backend>. Browsing only previews;
OK commits.The details - what is staged and what takes effect at once, the in use by note on a device another client holds, the granted-rate rule, the file upload, the five-second reconnect and the reasons a session can end - are all in Preferences ▸ Measuring through a Phonalyser server.
You do not have to install anything on the machine you measure from.
A running server hands out its own copy of Phonalyser.web: open the bench's
address in a Chromium browser - http://<bench>:8377/ - and
you get a workbench that is already connected to it, with that bench's
backends offered and no setup at all. This is the address to give a
colleague.
Such a page has no local backends - it arrives over plain
http://, which is not a secure context, so the browser's own
audio capture and WebUSB do not exist on it. That is also the answer to a
trap on the other route: an application loaded over https://
cannot open a session to a bench on the LAN at all. Both are explained in
Phonalyser in a browser ▸ the page
a bench serves.
web sits next to the JAR, the server also
serves it on the same HTTP port.