A Level Meter That Tells the Truth, and a Log Worth Reading
A Level Meter That Tells the Truth, and a Log Worth Reading

Two features in a recorder do nothing for the recording itself and decide whether people trust the application: the meter that shows the sound going in, and the log that explains what happened when something went wrong.
Both are easy to build badly in a way that looks finished. A meter that moves convincingly and reports the wrong thing, and a log full of data nobody can read, are worse than not having either — because both create confidence that is not warranted.
Peak and RMS answer different questions

Peak is the highest sample value in the buffer. It answers exactly one question — did anything clip — and it answers it instantly. A peak meter alone flickers constantly, spikes on a single sample and tells a person almost nothing about whether their level is right.
RMS is the average energy over a window, and it corresponds to what a listener would call loudness. It moves smoothly, it sits where the ear expects it, and it will happily read a comfortable level through a passage that is clipping on every transient.
A useful meter shows both: RMS as the moving bar that tells you where your level is, and peak as a separate mark that warns when a transient hit the ceiling. Neither one alone is a meter, and shipping only RMS — which is the prettier of the two — means your application never warns anybody about distortion.
Peak hold, because nobody is watching
A clip that happens while the user is looking at their notes has not been reported. A peak hold indicator that latches at the highest value and decays over a second or two catches those, and it is about six lines of code.
Decay matters: too fast and it is no better than the instantaneous peak, too slow and a single early spike leaves the warning on for the rest of the session. Around a second and a half feels right, which is roughly how long somebody takes to look up.
Decibels, not linear
Buffer values are linear and human hearing is not. A meter drawn directly from linear amplitude spends most of its travel in the top few decibels and shows almost no movement across the entire range where speech actually lives.
Convert to decibels and draw a range that matches the job — roughly minus sixty to zero for voice. The meter then moves where the sound is, which is the only reason to have one.
The muted microphone

The single most damaging failure in a recorder is not a crash. It is a recording that runs its full length and contains nothing, because the wrong input was selected, or a hardware mute switch was on, or another application had exclusive access.
A crash is obvious and recoverable — the user tries again. An empty recording is discovered when the person sits down to edit, by which time the meeting is over and the take cannot be repeated. People do not send support mail about this. They conclude the application does not work and stop using it.
Detecting it is trivial: sustained level below roughly minus sixty decibels for a few continuous seconds while recording. What matters is the response.
- Say it on screen, immediately. Not in a log, not at the end. While there is still time to fix it.
- Name the likely causes. Hardware mute, wrong input device, another app holding the microphone. Three specific things a person can check.
- Never stop the recording. A quiet passage is legitimate. Warn; do not act on the user’s behalf.
- Clear the warning the moment sound returns. A warning that persists after the problem is fixed trains people to ignore warnings.
This is the highest-value few hours of work in the entire application. It converts the worst possible outcome into a five-second interruption.
What belongs in a diagnostic log

A recorder that fails on somebody else’s machine is very difficult to debug from a description, so a log is not optional. What goes in it is a design decision, and the instinct — log everything — produces a file nobody will ever read.
The rule that made ours useful is to log decisions, not data. Every point where the code chose a path, one line. Nothing about the contents of the recording, ever.
- Permission states at launch, all of them, by name.
- Which input and output devices were selected, with identifiers.
- Every device change, with what it changed to.
- Which fallback path ran, if any, and why the previous one failed.
- Pause and resume, with the offset applied.
- Frames dropped, as a count at the end rather than one line each.
- How the recording ended: user stopped, permission revoked, device lost, error.
That is roughly thirty lines for a normal session and two hundred for a session that went wrong, which is exactly the shape you want. A support mail arrives, you read the log top to bottom in a minute, and the answer is usually in it.
A log is personal data

A diagnostic log from a recording application contains the shape of somebody’s working day, and it must be treated accordingly.
Never log the contents of a recording, in any form. Not audio, not sample statistics detailed enough to reconstruct anything, not the text of anything on screen. Never log full file paths — the last path component is enough to identify a recording and does not disclose a home directory or a client name in a folder.
And never upload automatically. A diagnostic that leaves the machine without the user asking is telemetry, whatever the setting is called. Write it to a file the person can open, give them one button that reveals it in the Finder, and let them decide what to attach to their message.
The practical benefit of this discipline is that you can tell a customer exactly what is in the log before they send it, which is frequently the difference between receiving one and not.
Making the log survive a crash
The log is most valuable in the session that ended badly, which is precisely the session where a buffered log has not been written.
Write it line by line, unbuffered, to a file that is opened for append. It is a tiny amount of I/O at a rate of a few lines a minute, and it means a crash leaves a log that ends at the last thing that happened rather than at the last flush.
Rotate it by session rather than by size, keeping the last handful. A user reporting an intermittent problem can then send the log for the session that failed rather than one enormous file containing three weeks of everything.
Where the meter reads from
A level meter has to reflect the signal being recorded, and there are several places in an audio graph where you could read it. Only one of them is right.
Read from the same tap that feeds the writer, after any processing that will be applied to the file, and before anything that only affects monitoring. A meter that reads before a gain stage tells the user their level is fine while the file clips. A meter that reads from the monitoring path shows the effect of a monitoring volume control that has nothing to do with what is being written.
This sounds obvious stated plainly and it is one of the most common bugs in recording software, because the monitoring path is the convenient place to attach a meter and the difference only appears once somebody adds a gain control.
Metering costs nothing if you do it right
Computing peak and RMS over a buffer is a single pass over data you already have in cache. It is genuinely free.
What is not free is what people do next: allocating, taking a lock, or dispatching to the main thread from the audio callback to update a view. Any of those on the audio thread will eventually cause a dropout, and a dropout is a hole in the recording.
Compute in the callback, store into a plain atomic value, and let the interface read that value on a timer at whatever rate the display refreshes. The audio thread never allocates, never locks and never talks to the interface.
What the meter should look like
Three details that decide whether people can actually use it.
- Mark the target zone. A meter with no indication of where a good level sits is a decoration. A shaded region around minus eighteen to minus twelve turns it into an instrument.
- Colour only at the top. A bar that is green then amber then red across its whole length reads as a warning at any level. Colour the last few decibels; leave the rest neutral.
- Show it before recording starts. The meter is most valuable while somebody sets their level, which is before they press record, not after.
The third is the one most recorders miss. A meter that only appears during a recording cannot be used to set a level, which is the entire reason to look at one.
Reading a log that came from a stranger
The test of a diagnostic log is not what it contains, it is how long it takes somebody who did not write the code to find the answer.
Two conventions did most of the work for us. Every line carries a timestamp and a short category, so a reader can skim for the category they care about. And every failure line names both what failed and what happened next — “input node connect failed, rebuilding engine” rather than an error code — so the recovery is visible in the same line as the problem.
The second convention is what makes a log readable by somebody in a hurry. An error on its own raises a question. An error with its consequence attached answers it.
And put the session summary at the end: duration, frames dropped, how it ended, which fallbacks ran. Most support cases are answered by those four numbers without reading anything above them.
What to do when the input device disappears
Somebody unplugs a headset mid-recording. The input device your engine was reading from no longer exists.
What must not happen is silent continuation on a different device. The system will frequently switch to the built-in microphone, the recording carries on, and the second half of the file is a completely different sound — different level, different room, different quality. Nobody notices until editing.
The correct behaviour is to notice the device change, log it, warn on screen, and keep recording. Not to stop: a person who unplugs headphones by accident during a take would rather have a file with a discontinuity than no file. But the discontinuity has to be announced, at the moment it happens and again in the summary at the end.
This is the same principle as the silence warning. The application knows something the user does not, and the entire value is in saying so while it can still be acted on.
Testing the meter without a studio
A level meter is hard to verify by looking at it, because a plausible-looking meter and a correct one are indistinguishable at a glance.
- Feed it silence. The meter should sit at the bottom, not float at ten per cent because of a scaling error.
- Feed it a full-scale tone. Peak should read zero and stay there. If it reads slightly under, your conversion is wrong.
- Feed it a quiet tone and a loud one an octave apart. RMS should differ by the amount the amplitudes differ, in decibels, not in some other proportion.
- Clap once. Peak spikes and holds; RMS barely moves. If RMS jumps, the averaging window is too short.
Four checks, five minutes, and they catch every scaling mistake anybody makes in this code. All of them can be done with a generated file rather than hardware.
The summary that ends a session
The last thing written to the log for a recording should be a short block that answers, without scrolling, what happened.
Duration, file size, how it ended, frames dropped, any fallback that ran, any warning shown to the user, the input and output devices in use at the end. Seven lines.
In practice this block resolves most support cases on its own, because most reports are of the form “the recording was wrong” and the summary says which of the handful of possible wrongnesses it was. Reading upward from there is only necessary when the summary is unremarkable, which is the rarer case.
What we would tell anyone building this
- Show RMS and peak. Either alone is not a meter.
- Work in decibels, over a range that matches voice.
- Add peak hold with a slow decay. Six lines, catches every clip.
- Detect sustained silence and say so on screen, immediately, with three specific causes.
- Never stop a recording on the user’s behalf.
- Log decisions, not data. Thirty lines for a good session.
- Redact paths, never log content, never upload automatically.
- Write unbuffered and rotate per session, so the crashed session leaves a usable log.
Neither of these features appears in a comparison table and neither sells a copy. They are the two that decide whether somebody who hits a problem stays a user, which over a couple of years is worth considerably more than a feature that does.

