Contributions welcome

Nobody is standing at your desk

FOHanalyzer is a small project. There is no roadmap committee, no CLA to sign, and no backlog you have to earn your way into. If something about this tool is wrong for the way you work a show, you are already qualified to fix it — and if you would rather just say so in an issue, that helps too.

Start here

The most valuable thing you can send costs you ten minutes

Not code. A report from a rig the maintainer does not own.

Audio device enumeration is where every analyser goes wrong, and it goes wrong differently on every interface. FOHanalyzer lists devices once at launch, maps their channels, and has to guess sensibly when a saved 18-in interface reopens on a 2-in one. There is no way to test that except on real hardware.

If you have five minutes and an interface, this is the highest-leverage thing you can do:

  • Open Preferences and check every device in the list is one you recognise.
  • Point a source at a multi-channel interface and step through the channels.
  • Unplug it, relaunch, and confirm the app falls back to the simulator instead of failing.
  • Tell us what you saw — including "all fine", which is genuinely useful data.

A good report has three lines

The interface and how it is connected, what you expected, and what happened instead. macOS version and the version chip from the app header if you have them. Screenshots of the plot are welcome — the trace usually says more than a paragraph.

Getting started

Clone, run, change something

You need JDK 25+ and Maven 3.9+. You do not need a measurement mic, an interface, or a venue — every source runs from a simulated preset.

  1. Get it running

    Two commands. The window that opens is the one in the screenshots, driven by simulated sources.

    $ git clone https://github.com/d135-1r43/fohanalyzer
    $ cd fohanalyzer
    $ mvn javafx:run

    mvn test and mvn package work even if JAVA_HOME points at an older JDK — the POM picks an installed 25+ toolchain. Running and packaging are not covered by that, so put JAVA_HOME on 25 yourself:

    $ export JAVA_HOME=$(/usr/libexec/java_home -v 25)   # macOS
  2. Find your way around

    Five packages, no framework, no dependency injection container, no code generation. engine and dsp are pure functions with full test coverage — start there if you want a change that is easy to prove correct.

    The README is unusually detailed on purpose: it explains not just what the code does but why it is shaped that way, down to why the Blackman window is the symmetric definition and why the broadband RMS is hand-rolled. Read the section covering the area you are touching before you change it — it will usually already answer your first question.

  3. Use the dev aids

    CSS hot reload re-applies theme.css to the running window on save, so padding and colour work does not need a restart. The render probe boots the app, snapshots the window and exits — handy for a visual check without a display.

    $ FOH_DEV=true mvn javafx:run   # CSS hot reload
    $ PROBE=true mvn javafx:run     # snapshot to target/probe-full.png, then exit
  4. Match the house style

    The style is the Eclipse formatter profile in formatter/java.xml: tabs at width 4, braces on their own line, comments wrapped at 80 columns. It is enforced, not suggested — the formatter's validate goal runs in the validate phase, so any build fails on an unformatted file, including mvn test.

    $ mvn formatter:format   # apply it, then commit

    One quirk that will bite you

    The profile sets join_line_comments=false, so the formatter splits an over-long // line but never rejoins the remainder. Keep // lines inside 80 columns yourself — counting the tab indent — and put a long comment on its own line above the statement rather than trailing it.

  5. Test what you can test

    EngineTest, SignalStateTest, AudioDspTest and SettingsTest cover the band maths, note naming, formatting, simulation, averaging, smoothing, peak hold, the spectral logic and the settings store. If your change touches any of that, it needs a test.

    The JavaFX controls have no unit tests and that is deliberate — they are trivial and the harness would cost more than it caught. Nobody will ask you to add one.

    $ mvn test
  6. Open the pull request

    One change per PR, and say what a reviewer should look at. If it is visible, attach a screenshot — PROBE=true mvn javafx:run will take one for you. CI runs the tests, the format check and a full package on every push, so you will know within a few minutes whether it holds.

    Draft PRs are welcome, and so is asking first. An issue that says "I am thinking of doing X, is that wanted?" saves everyone an afternoon.

What needs doing

Pick something that suits you

Roughly ordered by how self-contained they are. None of these are assigned to anyone, and the issue tracker is short enough to read in a minute — open an issue saying which one you are taking, so two people do not build the same thing.

Windows and Linux packaging

The application code is plain JavaFX and Java Sound — nothing in it is macOS-specific. What is macOS-specific is scripts/package-mac.sh: the microphone usage description in Info.plist, the ad-hoc re-signing, and the .dmg.

An equivalent jpackage invocation producing an .msi or an AppImage, plus a CI job to run it, would put the app on two more platforms. The module list is already worked out and documented — including the two easy to miss, java.desktop for audio capture and java.prefs for settings.

Clear finish line · no DSP knowledge needed · high impact

Sharper measurement

A- and C-weighting for the SPL readout. Coherence, so you know when to believe the transfer function. Phase. A proper dual-FFT transfer function with delay finding. Impulse response and RT60.

All of it lands in dsp and engine, which are pure functions with no JavaFX anywhere near them — you can write the test first and never open the UI.

Testable in isolation · pick one, not all five

Interface and workflow

The control rail is ordered by how often a hand reaches for something mid-show, and everything decided once at patch time lives in a separate Preferences window so it is not competing for the column you read during a show.

That ordering is a judgement call made by one set of hands. If it is wrong for how you work — or if something you need mid-show is two clicks deep — say so. Keyboard shortcuts, a full-screen plot mode and a dark-stage brightness mode are all open.

No Java required to file this · experience is the qualification

Hardware coverage

Devices are enumerated once at launch; there is no hot-plug notification, so plugging an interface in after the app is running does not show it. Fixing that properly means watching for device changes on each platform.

Smaller and just as welcome: channel-count edge cases, sample-rate mismatches, and interfaces whose names come through mangled.

Needs hardware · needs patience

Documentation and translation

A short practical guide — ringing out a wedge, setting an SPL calibration against a hand-held meter, reading a transfer function — would help more working engineers than most features would.

The interface is English-only. It is a small string set, and the app is used by people who do not work in English.

Good first contribution · no build needed for prose

Signing and notarisation

The bundle is ad-hoc signed, not notarised, so Gatekeeper refuses the first launch on another Mac and users have to right-click → Open. A Developer ID signature and a notarisation step in CI would remove that, for everyone, permanently.

This one needs an Apple Developer account as much as it needs code, so it is as much a question of who can help as how.

Blocked on access, not difficulty

Ground rules

What to expect

Your work stays yours, and stays free

Contributions are accepted under GPL-3.0-or-later, the project's own licence. There is no copyright assignment and no CLA. Nobody can take what you write here and close it.

Reviews are about the code

Expect direct feedback on the change and nothing else. Be the same way in return. Anyone who cannot manage that will be shown out — a small project has no room for it.

Not everything gets merged

This is a focused tool, and a feature that is right for a different application is still wrong for this one. Asking in an issue before building something large is the way to find out cheaply.

It may take a few days

This is a spare-time project. A quiet week is a quiet week, not a verdict on your patch — nudge the thread if it goes silent.

Still reading?

Then you are exactly the person this page is for. Take the smallest thing on it — a typo, a device report, a question — and start there.