Chirp
Real-Time Audio Monitoring, Visualization & Triggered Recording
v3.9.1Overview
Chirp is a desktop application built with Python, PyQt5, and pyqtgraph for real-time audio monitoring, spectral visualization, and threshold-triggered recording. It was designed for bioacoustics research but is suitable for any scenario requiring continuous audio surveillance with automatic capture of events of interest.
Key Capabilities
- Live spectrogram, waveform, and amplitude visualization
- Threshold-triggered recording with configurable pre- and post-trigger buffers
- Spectral entropy trigger for tonal sound detection
- Multi-stream support — monitor several audio devices simultaneously
- Stereo channel analysis with per-channel trigger logic
- Optional bandpass filtering for frequency-specific triggering
- Configurable display: FFT size, window function, frequency scale, view modes
- Dark-themed UI using the Catppuccin Mocha color palette
- Save and load full session configurations as JSON
The application ships as the chirp Python package (run with
python -m chirp) and is also distributed as a standalone
Chirp.exe built with PyInstaller.
Installation
Requirements
- Python 3.11 or later
sounddevice— audio I/O via PortAudionumpy— numerical computationscipy— signal processing (FFT, bandpass filter)soundfile— streaming WAV output (libsndfile)PyQt5— GUI frameworkpyqtgraph+PyOpenGL— GPU-accelerated real-time plottingmatplotlib— colormap source (+ a small legacy helper layer)
Quick Start
# Create and activate a conda environment (recommended)
conda create -n chirp python=3.11 -y
conda activate chirp
# Install dependencies
pip install sounddevice numpy scipy soundfile PyQt5 pyqtgraph PyOpenGL matplotlib
# Launch
python chirp.py
Interface Layout
The main window is divided into five functional areas: the sidebar, the central canvas, the transport bar, and two configuration panels at the bottom (trigger and display), plus a settings panel.
Sidebar (Left)
The sidebar lists all configured recording streams. Each entry displays:
- Status indicators — colored dots showing stream state: ACQ (acquiring, green), REC (recording, green), TRIG (triggered, red)
- Sticky health badges — S latches when this stream has saturated (clipped) at any point during the session; D latches when the audio capture has dropped any callback chunks (with the total count in its tooltip); ! latches on pipeline problems — device open failures, DSP errors, WAV-write failures, timestamp divergence, and inserted silence in the captured audio. All stay lit until you click the badge to clear, so a brief clip or a single dropped callback can't slip by unnoticed; hover any badge for the details behind it.
- Transient drop flash — a short per-tick indicator that blinks when a drop occurs in the current UI tick, alongside the sticky D badge.
- Mini amplitude preview — a small real-time level meter
- Recognition color — each stream carries a color shown as a bar along the item's left edge, so you can tell at a glance which bird/cage/stream a row belongs to. The same color frames the stream's config panel and its View-mode tile. New streams are auto-assigned a distinct color; change it from the Config view (see the Color picker in the Status area). The color is persisted in the config file.
- Reorder buttons — move streams up or down in the list
- Delete button — remove a stream
- On/Off switch — per-stream enable. A disabled stream (greyed-out, struck-through name) keeps its full configuration but is skipped by Start All Acq and Start All Rec — useful for keeping a stream defined without it participating in bulk operations. Disabling also stops the stream immediately if it was running; its own per-stream Start buttons still work for deliberate one-off use, and Stop All always stops every stream. The switch is persisted in the config file and also editable in the All-Streams Table ("Enabled" row).
- Lock switch (🔒) — per-stream parameter lock. Locking freezes the stream's configuration (trigger parameters, band filter, spectral trigger, output folder/prefix/suffix, reference date, input device, recognition color, Reset, and inline rename) so it can't be changed by accident. Display parameters, the audio monitor, and Start/Stop still work while locked — the lock protects settings, not operation. The same state is shown by a lock button in the Config Status area. Unlocking asks for confirmation and names the stream, so in a shared setup one person can't unlock another's stream by mistake. The sidebar also has Lock All / Unlock All buttons (Unlock All confirms once and lists the affected streams). In the All-Streams Table a locked stream's protected cells are greyed read-only. The lock is persisted in the config file.
Click Add Recording at the bottom of the sidebar to create a new stream. Right-click the sidebar background for Start All and Stop All context actions.
Adjustable layout: the border between the sidebar and the main pane, and the border between the display plots and the configuration panels, are draggable splitters — drag either to give more room to the sidebar, the plots, or the config controls.
Canvas (Center)
The central area hosts the pyqtgraph/OpenGL plots showing the spectrogram, waveform, and amplitude plots for the currently selected stream. A vertical cursor line indicates the current write position in the circular buffer.
A thin detect / record events strip sits directly beneath the amplitude plot with two rows: a yellow bar lights up for every sample the trigger condition is met (detect), and a green bar lights up for every sample the writer is actually capturing (record). The detect row is driven by the same per-sample trigger mask the recording state machine consumes — there is no second computation, so what you see is exactly what the trigger did, including any bandpass filtering and spectral-entropy gating. If an event is later dropped by the Min Total Cross filter (its accumulated above-threshold duration fell short of the minimum, so no WAV is written), that event’s record bar turns red instead of green — so a discarded event is visible at a glance, not just in the terminal log.
Transport Bar
| Button | Action |
|---|---|
| Start Acq | Begin audio acquisition (fills buffer, enables display) |
| Stop Acq | Stop acquisition and clear the buffer |
| Start Rec | Arm threshold-triggered recording |
| Stop Rec | Disarm recording (finishes any in-progress file) |
| Reset Params | Restore all parameters to defaults |
| Save / Save As | Save current configuration to JSON |
| Load | Load a previously saved configuration |
| Startup | Choose what configuration Chirp loads on launch (empty / last used / a specific file) |
| View Mode | Switch to multi-stream grid view |
Status indicators in the transport bar show the global state: ACQ, REC, and TRIG.
The Status area also holds a Color swatch button — click it to choose the recognition color for the selected stream. The chosen color frames the config plot panel (a colored rectangle around the spectrogram / amplitude / events plots), outlines the stream's View-mode tile, and tints its sidebar left edge, making a specific bird/cage/stream easy to pick out.
Trigger Panel (Bottom Left)
Controls that govern when and how recordings are triggered:
| Control | Description |
|---|---|
| Threshold | Amplitude level that triggers recording. Also draggable on the plot. |
| Min Cross | Minimum duration the signal must stay above threshold to confirm a trigger. |
| Min Total Cross | Minimum accumulated above-threshold duration over the whole event — files whose total crossing time is shorter are discarded instead of saved (0 = keep everything). |
| Hold | Duration to keep recording after the signal drops below threshold. |
| Post-Trigger | Additional time appended after the last threshold crossing. |
| Max Rec | Maximum duration of a single recording segment (auto-splits if exceeded). |
| Pre-Trigger | Duration of audio captured before the threshold crossing via ring buffer. |
| Band Lo / Hi Hz | Bandpass filter frequency range for trigger analysis. |
| Detect Mode | Trigger detection strategy (see Spectral Entropy). |
| Entropy Threshold | Spectral entropy level below which a tonal trigger fires. |
| Auto Calibrate | Automatically set threshold from ambient noise measurement. |
Display Panel (Bottom Right)
| Control | Description |
|---|---|
| Gain | Amplification applied to the input signal for display. |
| dB Floor / Ceil | Dynamic range limits for the spectrogram colormap. |
| FFT Size | Number of FFT points (256, 512, 1024, 2048, or 4096). |
| Window | FFT window function: Hann, Hamming, Blackman, Bartlett, or Flattop. |
| Freq Scale | Frequency axis mapping: Linear, Logarithmic, or Mel. |
| Display Lo / Hi | Visible frequency range on the spectrogram. |
| Buffer Duration | Length of the circular display buffer (5 to 60 seconds). |
| View | Visualization mode: Spectrogram, Waveform, or Both. |
| Sync | Synchronize display parameters across all streams. |
Settings Panel (Bottom)
| Control | Description |
|---|---|
| Output Folder | Directory where WAV recordings are saved. |
| Prefix / Suffix | Custom text prepended/appended to recording filenames. |
| Input Device | Audio input device selector with refresh button. |
| Channel Mode | Mono, Left, Right, or Stereo. |
| Trigger Mode | Channel logic for stereo triggering (Average, Any, Both, Left, Right). |
| Sample Rate | Audio sample rate from 8,000 Hz to 96,000 Hz. |
| Reference Date | Base date for day-count subfolder naming (e.g., days post hatch). |
Visualization Modes
The View combo box in the Display panel selects which plots are shown on the canvas. All modes include an amplitude envelope subplot at the bottom.
Spectrogram
The default mode. The upper plot shows a scrolling spectrogram rendered by a pyqtgraph
ImageItem using the inferno colormap (colormap mapping on the CPU, blitted
through the OpenGL-composited viewport). The lower plot
shows the amplitude envelope (absolute sample values) as a blue line. A dashed threshold line is
drawn when
recording is armed.
Waveform
The upper subplot displays the raw signed waveform as a teal line. The lower subplot shows the amplitude envelope, identical to spectrogram mode. This view is useful for inspecting transient shape and polarity.
Both
Three subplots stacked vertically: spectrogram on top, waveform in the middle, and amplitude envelope at the bottom. This provides the most complete picture at the cost of vertical space.
Stereo Display
When the channel mode is set to Stereo, an additional subplot is added for the right channel spectrogram or waveform. The amplitude plot combines both channels: left in blue, right in pink.
Visual Indicators
- Cursor line (green) — marks the current write position in the circular buffer.
- Saturation warning — the waveform and amplitude lines turn red when the signal reaches 99% of full scale or higher. The transient red tint clears as soon as a clean chunk arrives; the sticky S badge on the sidebar entry latches until you click it, so a brief clip is never missed. Hover the badge to see the last saved recording that contained clipped samples — its filename, folder and peak level — so you can open that file directly instead of searching chirp_errors.log for it. If clipping was seen but no recording has captured it (acquisition running without recording armed, or a clipped stretch that never triggered), the tooltip says so rather than naming an older file.
- Drop warning — raw audio lands in a preallocated per-stream ring buffer straight from the realtime callback, so capture cannot be stalled by DSP or the display. The sticky D badge on the sidebar entry latches only if that ring ever overruns (the DSP consumer fell seconds behind — it should never happen in normal use), with a running session total in its tooltip. Click to clear.
Amplitude Y-Axis Scale
The amplitude envelope plot has two Y-axis scales:
- Log (dB) — the default. Y axis runs
-80 dBto0 dBfull scale. Best for surfacing quiet signals that compress against zero on the linear scale (faint vocalisations, distant calls). Mouse-wheel Y zoom works here too, so you can zoom into the noise floor to place the threshold line precisely. - Linear — raw envelope, scrollable Y zoom. Best when you care about the absolute peak level and want to see the shape of high-amplitude transients.
The threshold value is kept at fine resolution across the whole dB range — even deep near
the -80 dB floor the line moves smoothly, so quiet thresholds are no longer forced
to snap to coarse steps.
Right-click on the amplitude plot (in either Config or View mode) to pick
Linear or Log (dB) for that stream. The choice is per-stream and is saved to the JSON
settings file along with the rest of the configuration. The threshold line and its label
track the chosen scale automatically — in dB mode the label reads e.g.
thr = -26.0 dB; in linear mode it reads thr = 0.050.
Threshold-Triggered Recording
Chirp continuously monitors the amplitude envelope and automatically records audio segments when the signal exceeds a configurable threshold. This enables unattended data collection over extended periods. The envelope is a smooth measure of instantaneous loudness rather than the raw sample values — see Amplitude envelope for how it is computed and the two estimators you can choose between.
State Machine
Recording progresses through three states:
- IDLE — Acquisition is running but recording is not armed, or the signal is below threshold.
- PENDING — The signal has crossed the threshold but the Min Cross duration has not yet elapsed. If the signal drops back below threshold before this duration, the trigger is cancelled (false-trigger rejection).
- RECORDING — A confirmed trigger. Audio is being written to a WAV file. Recording continues until the signal has been below threshold for the Hold duration, plus any Post-Trigger extension, or until Max Rec is reached.
Parameter Reference
Threshold
The amplitude level that initiates the trigger sequence. This can be set numerically or by dragging the yellow dashed line directly on the amplitude plot. Values are in linear amplitude (0.0 to 1.0 of full scale).
Min Cross
The minimum continuous duration (in seconds) the signal must remain above the threshold before a trigger is confirmed. This prevents brief transient spikes (e.g., a click or bump) from creating recordings. Typical values range from 0.01 s to 0.5 s.
Min Total Cross
The minimum accumulated above-threshold duration (in seconds) an event must reach for its file to be kept. Unlike Min Cross (which gates the start of an event on one continuous run), Min Total Cross sums every above-threshold sample across the whole event — separate bursts bridged by Hold all count. The check runs just before the file is finalized: an event that never accumulates enough crossing time is discarded (its in-progress temporary file is deleted) instead of being saved. Set to 0 to disable the filter and keep every triggered file. Files force-split by Max Rec are judged on the whole event's running total, so a long split recording never loses its parts to a quiet tail. Continuous-mode and Force Trigger recordings always pass (their entire duration counts as crossing time).
Pre-Trigger Buffer
Duration of audio (in seconds) captured before the threshold crossing. A ring buffer continuously stores recent audio so that the onset of a vocalization is not lost. The pre-trigger audio is prepended to each recording file.
Hold
How long (in seconds) recording continues after the signal drops below the threshold. This bridges short pauses within a single vocalization to avoid splitting it into many small files.
Post-Trigger
An additional duration (in seconds) appended after the last threshold crossing. Unlike Hold, Post-Trigger always adds this full duration once the hold period has expired, capturing any trailing reverberation or echo.
Max Rec
The maximum allowed duration (in seconds) of a single recording segment. If a continuous sound exceeds this limit, the current file is closed and a new one is started immediately — sample-accurately, with no gap. Split files share the same name format as every other recording; each carries its own capture-time timestamp (the second file's time = the first file's time + its duration), so a long event appears as a series of consecutively-timestamped WAVs. This prevents runaway recordings from filling disk space.
Recording Modes & Force Trigger
The Rec Mode selector at the top of the Trigger panel picks how recording is driven, per stream:
- Triggered (default) — the threshold state machine described above.
- Continuous — while REC is on, everything is recorded: a file opens on the first sample after Start Rec and a new file starts every Max Rec seconds with no gap between them. Every file shares the same name format; each one's timestamp is its own capture time, so consecutive files of one take differ by exactly Max Rec. All other trigger parameters are ignored and greyed out. Memory stays flat regardless of duration — audio streams to disk as it arrives.
In Triggered mode, the ● Force Trigger button (enabled while REC is on) manually opens a recording segment right now — including the configured pre-trigger lookback — and pressing it again closes the segment immediately, with no hold or post-trigger tail. Max Rec splitting applies to forced segments too.
Output Files
Recordings are saved as uncompressed WAV files (PCM 16-bit) with the following naming pattern:
<prefix>_<epochMs>_YYYYMMDD_HHMMSS_mmm_<suffix>.wav
Where epochMs is the Unix epoch in milliseconds, and the timestamp reflects local
time down to the millisecond. Both fields encode the same instant — the onset of the
recorded event (including the pre-trigger lookback). Files are written in a background thread
to avoid blocking the audio processing pipeline.
The prefix and suffix are yours to use freely, but they are
sanitized so they can never produce an unusable path. Letters, digits and
- _ . + are kept as typed;
anything else — spaces, slashes, colons, accented or non-Latin characters — becomes
an underscore. So a suffix like stim+ or day3+ctrl reaches the filename
intact.
Timestamp Reliability
Filename timestamps come from a disciplined capture clock: a sample-accurate clock driven by the audio stream itself, continuously steered onto the system wall clock. This gives the best of both worlds for long recording campaigns:
- Local precision — adjacent, overlapping, and Max-Rec–split files tile at sample accuracy (part 2's timestamp = part 1's onset + part 1's duration, exactly), because timestamps derive from the sample counter, not from when the file happened to be written.
- Long-run accuracy — sound-card crystals drift by seconds per day (minutes over a multi-week experiment). The clock measures its offset against the system wall clock on every audio buffer and corrects it smoothly (≤ 1 ms per second of audio), so the drift never accumulates. Timestamps are computed in UTC internally and rendered to local time only in the filename, so a daylight-saving transition mid-run does not skew the readable timestamp.
- Capture holes — if the device stalls or samples are dropped, the
clock detects the hole and jumps forward across it between recordings (never inside
a file), logging a
clock_stepentry tochirp_errors.log.
Two independent safety nets watch the timestamps:
- Publish-time watchdog — every finalized WAV's
onset + duration is checked against the wall clock; a divergence beyond
10 seconds lights the sidebar
! badge and logs a
timestamp_divergenceentry with the exact delta and file path. - Clock audit log — once per minute, each acquiring stream appends a
row to
chirp_clock_log.csvin its output folder pairing the capture sample index with the derived capture time and the raw system clock (utc_iso, stream, ring_sample_index, derived_epoch, derived_source, wall_epoch). After a long run, comparingderived_epochandwall_epochbounds the clock error at any point in the session — and lets you verify (or correct) any filename's timestamp offline. The file is capped at 64 MB (≈10 MB per stream over 90 days in practice).
Spectral Entropy Trigger
The spectral entropy trigger provides a frequency-domain criterion for identifying sounds of interest. It computes the normalized Shannon entropy of the FFT magnitude spectrum, producing a value between 0 and 1:
- 0 — pure tone (all energy at a single frequency)
- 1 — white noise (energy uniformly spread across all frequencies)
Tonal vocalizations (birdsong, bat calls, whale sounds) produce low entropy values. The trigger fires when entropy falls below the configured threshold, meaning a structured tonal signal has been detected.
Detect Modes
The Detect Mode dropdown in the Trigger panel selects how amplitude and spectral entropy criteria are combined:
| Mode | Trigger Condition |
|---|---|
| Amplitude Only | Legacy behavior. Only amplitude threshold is checked. |
| Spectral Only | Only entropy is checked. Amplitude threshold is ignored. |
| Amp AND Spectral | Both conditions must be met simultaneously. |
| Amp OR Spectral | Either condition alone is sufficient to trigger. |
Entropy Min Duration
The Entropy Min Dur parameter debounces the spectral gate: entropy must stay
below the threshold continuously for at least this long (evaluated per FFT chunk,
≈23 ms at 44.1 kHz) before the spectral condition turns ON. It turns OFF again
on the first chunk back above the threshold. This filters out momentary tonal blips without
touching the amplitude Min Cross, which still applies to the combined detection mask.
Set to 0 for instantaneous behavior.
Entropy Trace Plot
When any spectral mode is active, an additional subplot appears below the amplitude plot showing the real-time entropy trace:
- Mauve line — current entropy value over time
- Peach dashed line — entropy threshold (draggable, like the amplitude threshold)
- Scroll-wheel zoom — adjusts Y-axis range, centered on the mouse cursor position
A numeric entropy display label in the status area shows the current instantaneous value. For stereo streams, per-channel entropy values are combined using the same logic as the channel trigger mode setting (Average, Any, Both, Left, or Right).
Auto-Calibrate
The Auto Calibrate button in the Trigger panel measures the ambient noise floor and automatically sets the amplitude threshold above it.
How It Works
- Acquisition must already be running.
- Click Auto Calibrate. The system records ambient levels for a configurable duration (1 to 10 seconds).
- The threshold is set to the 95th percentile of measured amplitude, multiplied by a safety margin.
Bandpass Filter
Each stream can optionally apply a 4th-order Butterworth bandpass filter. When enabled, the amplitude measurement used for threshold triggering is computed from the filtered signal, focusing detection on a specific frequency band.
- Set the Lo Hz and Hi Hz fields in the Trigger panel to define the passband.
- The spectrogram always displays the unfiltered signal so you retain full spectral context.
- The filter is particularly useful when the target vocalization occupies a narrow frequency band but the environment contains broadband noise.
Channel Modes
Input Channel Selection
| Mode | Behavior |
|---|---|
| Mono | Uses a single-channel input. |
| Left | Extracts the left channel from a stereo device. |
| Right | Extracts the right channel from a stereo device. |
| Stereo | Uses both channels. Dual spectrograms are displayed (left in blue, right in pink). |
Because the two share one device, the device is only released when the last of them stops acquiring — relevant if you ever need to reset a misbehaving audio device (see Inserted Silence).
Stereo Trigger Modes
When operating in stereo, the Trigger Mode control determines how per-channel amplitude values are combined for threshold comparison:
| Trigger Mode | Logic |
|---|---|
| Average | Mean of left and right amplitudes must exceed threshold. |
| Any Channel | Either channel exceeding threshold is sufficient. |
| Both Channels | Both channels must independently exceed threshold. |
| Left Channel | Only the left channel is evaluated. |
| Right Channel | Only the right channel is evaluated. |
View Mode
Click View Mode in the transport bar to switch from the single-stream configuration view to a multi-stream monitoring grid.
- All active streams are displayed simultaneously in a configurable grid. Use the Columns control in the view toolbar to set the number of columns (e.g. 2 columns × 4 rows for 8 streams).
- Order: choose how tiles fill the grid. Column (default) fills down the first column before the next, so 8 streams in 2 columns land as streams 1–4 in the left column and 5–8 in the right; Row fills across the top row first. The setting is saved with the configuration.
- Each cell shows a compact spectrogram or waveform, amplitude plot, threshold line, detect / record events strip, and status text, framed by a rectangle in the stream's recognition color.
- The sidebar and configuration panels are hidden to maximize display area.
- Per-tile header: each tile shows the stream name, acq / rec / trig status dots (blue / green / red — same vocabulary as the sidebar), and the sticky health badges S (saturation), D (dropped chunks) and ! (pipeline errors) — hover for details, click a lit badge to clear it right from the grid. A 🎧 marker shows which stream feeds the audio monitor.
- Each tile also includes the detect / record events strip (yellow = trigger condition met, green = written to WAV, red = event dropped by the Min Total Cross filter), so trigger activity is visible while monitoring.
- Active only: a toolbar checkbox that hides streams whose acquisition is stopped. The setting is saved with the configuration.
- Per-tile Height is adjustable, or click Fit to screen to size every tile so all streams are visible at once without scrolling (based on the current column count).
- Rendering uses pyqtgraph with an OpenGL-composited viewport: off-screen tiles are skipped and the frame rate adapts under load, so audio capture is never starved by the display.
- Click Config Mode to return to the single-stream editing view.
Settings Management
All configuration parameters can be saved to and loaded from JSON files using the Save, Save As, and Load buttons in the transport bar.
What Is Saved
- Audio device names and sample rates
- All trigger parameters (threshold, timings, band filter, detect mode, entropy settings)
- Display options (FFT size, window, frequency scale, view mode, gain, dB range)
- Channel and trigger mode selections
- Output folder, prefix, suffix, and reference date
- Per-stream recognition color
- View-mode grid settings — number of columns, tile height, fill order (column / row), "Active only" filter, and OpenGL rendering
- Audio-monitor settings — output device (by name), gain, mute state, Follow toggle, and which stream is routed to the monitor
- ⚙ Advanced settings — the capture engine (input buffer, block size, exclusive mode), both auto-recovery switches, and the amplitude-envelope estimator and cutoff
Unsaved Changes
A small dot after the file name in the window title marks unsaved changes, and the Save button is enabled only while there are unsaved changes — a greyed-out Save means Chirp believes the file on disk already matches what is in memory. Every change that gets written to the configuration file marks the config as unsaved, including structural ones like the input device, channel mode and sample rate.
If you close Chirp with unsaved changes, a prompt asks whether to Save, Discard, or Cancel. Choosing Save writes to the current configuration file (or asks where to save if the config is new); Discard quits without saving; Cancel returns to the app without closing. If acquisition or recording is still running, that warning appears first, then this save prompt.
Startup Configuration
The Startup button chooses what Chirp loads each time it launches:
- Empty configuration — start with a single fresh recording (the default).
- Last used configuration — automatically reload whichever config file you most recently saved or loaded.
- A specific configuration file — always load a fixed file you pick, regardless of what you worked on last.
The choice is stored per-user (independent of any config file), so it persists across sessions. If the chosen file is missing or fails to load, Chirp falls back to an empty configuration so the app always comes up usable.
Device Resolution
When loading a configuration, Chirp resolves audio devices by name. If an exact match is not found, it attempts a partial string match. This allows configurations to be portable across systems where devices may have slightly different names.
All-Streams Table
The All Streams Table… button opens a side-by-side table of every parameter of every stream — rows are parameters, columns are streams. Double-click a cell to edit; the change applies to that stream immediately, exactly as if you had edited it in the per-stream panel. Choice-valued rows list their allowed values in the tooltip; invalid input reverts. Structural parameters (device, sample rate, channel mode, input source) are shown read-only — change those from the Settings panel. A locked stream's protected cells are also greyed read-only (its display params and Enabled switch stay editable). This replaces the live-sync checkboxes from earlier versions.
Audio Monitor Controls
The monitor bar gained a 🔊 enable/disable toggle — muting closes the output stream but keeps both the source and output device selections, so re-enabling restores the exact same routing. The Follow checkbox makes the monitor track your selection: selecting a stream in the sidebar (Config mode) or clicking a tile (View mode) routes that stream to the speakers. A Gain slider (0–200%, default 100% = unity) scales the loopback playback volume — recordings are never affected; output boosted past full scale is clipped, not wrapped.
All of the monitor bar's state — output device (saved by name and re-resolved on load), gain, mute, Follow, and the selected source stream — is saved in the configuration file and restored when it is loaded. A configuration saved while muted restores its routing silently (the output stays closed until you un-mute).
Reference Date & Subfolder Naming
The Reference Date field enables automatic subfolder naming based on the number
of days elapsed since a reference event. For example, in bird vocalization studies, you can set
the hatch date. Recordings are then saved into subfolders named by the day count, simplifying
longitudinal data organization. The subfolder is <prefix>_<days> —
the Folder Prefix you set plus an automatically inserted underscore and the day
number (e.g. a prefix of day gives day_0/, day_1/, …). A
trailing underscore in the prefix is not doubled, and an empty prefix yields just the day number.
Error Logging
Every pipeline failure surfaced by the sidebar
S /
D /
! indicators is also appended to a
plain-text log file named chirp_errors.log, written to the folder Chirp is launched
from. The file is created on first event, opened in append mode (so it survives across runs),
and never deleted automatically — manage rotation manually if it grows.
Line Format
Each event is a single tab-separated line:
<ISO timestamp> <category> stream=<name> [file=<path>] <message>
Example:
2026-04-27T14:32:18.412 saturation stream=Mic A file=D:\recordings\day_042\Mic_A_..._.wav recording contains clipped samples (peak=1.0000)
Categories
| Category | What it means | File path |
|---|---|---|
ring_overrun |
The capture ring buffer overran — the DSP consumer fell more than the ring's capacity behind and unread audio was overwritten (the sidebar D badge). Throttled to one line per stream per second; the cumulative count is stamped on each line so you can see how many were suppressed between two log entries. | — |
os_drop |
PortAudio reported input_overflow — the driver / OS lost samples
upstream of our ring (the OS tag on the ! badge).
Same throttling as ring_overrun. |
— |
underflow |
PortAudio reported input_underflow — zero samples were
inserted into the captured audio to cover data the device failed to
deliver. Unlike os_drop (samples lost) this corrupts the audio
content: the silence reaches the spectrogram, the monitor and the WAVs.
Lights the ! badge. Same
throttling as os_drop. See Inserted Silence. |
— |
zero_run |
Chirp found runs of exact digital zeros (≥ 1 ms) in the captured signal — inserted silence that raised no PortAudio flag at all. The line carries how many runs were seen and the longest one. Lights the ! badge. Throttled. See Inserted Silence. | — |
ingest |
An exception was raised inside the per-entity ingest loop (DSP / FFT / trigger). The thread is preserved; a 3-frame traceback is included in the message. Every event is logged. | — |
open |
The audio capture (AudioCapture) or WAV-replay capture
(WavFileCapture) failed to open. Every event is logged. |
WAV-replay path on a WAV-open failure. |
wav_writer |
The writer pool failed to write a triggered WAV (disk full, bad path, permission,
scipy crash). Every event is logged. A worker that dies entirely is also logged with a
worker died: ... message before the supervisor respawns it. |
Output folder of the failed write. |
saturation |
A successfully-written WAV contained at least one sample at |x| ≥ 0.99
of full scale. Logged once per file (not per sample) so you can locate
and review every recording that clipped without flooding the log. |
Full path of the WAV that clipped. |
clock_step |
The disciplined timestamp clock detected a capture hole (device stall / drop burst) and stepped forward across it, between recording events. The message carries the size of the jump. See Timestamp Reliability. | — |
timestamp_divergence |
A published WAV's onset + duration disagrees with the wall clock by more than 10 seconds — the filename timestamps may be wrong. Logged once per affected file with the exact delta; also lights the sidebar ! badge. | Full path of the affected WAV. |
Throttling
ring_overrun, os_drop, underflow and
zero_run can fire on every audio chunk
(50+/second at the default sample rate / chunk size). To keep the log bounded and useful,
those categories are limited to one entry per (stream, category) per second. The first
event in any burst always logs immediately; subsequent events within the window are
suppressed. Because each line carries a cumulative count, the difference between two adjacent
lines tells you how many events were suppressed in between.
All other categories — ingest, open, wav_writer,
saturation, clock_step, timestamp_divergence —
are not throttled; every event produces a line.
Reliability
The logger is wrapped in a try/except — any I/O failure (path locked, disk full, permission error) is swallowed silently. Losing log lines is strictly preferable to crashing the audio pipeline.
chirp_errors.log and search for the stream name. The timestamp on the first
matching line is when the failure actually occurred — the badge only tells you it
happened, the log tells you when, where, and (for writer / saturation events) which file.
Capture Engine (⚙ Advanced)
The ⚙ Advanced button opens settings that belong to the machine and its
audio hardware rather than to any one stream: how capture streams are opened, and what Chirp
does when a capture session goes bad. They are stored in the configuration file's
audio section. All capture-engine settings take effect the next time a
stream opens — Stop Acq → Start Acq, or a config load.
Input buffer and block size
| Setting | What it does |
|---|---|
| Input buffer (latency) | How late the machine may be before captured audio is lost — the setting that actually protects against dropouts. Device default can be as little as 10 ms on WASAPI (measured on a Focusrite Scarlett), far too thin a margin for a shared desktop; an explicit 0.25–0.5 s is much safer. Chirp logs the latency the driver actually granted when it opens the stream. |
| Callback block size | How often Chirp is handed audio. Larger means fewer wake-ups (less chance of being late) at the cost of monitor and display delay. It does not affect the recorded audio — the capture ring absorbs any buffer size. |
WASAPI exclusive mode
In shared mode every capture passes through the Windows audio engine, which owns the endpoint buffer and is free to zero-fill a period it could not service — the inserted-silence fault. Exclusive mode hands the endpoint to Chirp alone, so audio comes straight from the driver and the engine's mixing and buffering path is out of the picture entirely.
- While it is on, no other application can use that input, and the hardware must accept the stream's format natively (there is no engine resampler to absorb a mismatch).
- Only WASAPI devices have an exclusive mode. On MME, DirectSound and WDM-KS entries the request is logged and ignored — WDM-KS already bypasses the engine on its own.
- If an exclusive open is refused (another application holds the endpoint, or the format is not natively supported), Chirp opens the device in shared mode and logs it loudly rather than leaving an unattended rig with no capture at all.
open line in
chirp_errors.log names the device, its host API and the mode it opened in, for
example device 17 "Analogue 1 + 2 (Focusrite USB)" [Windows WASAPI], blocksize=8192
(186 ms), requested latency=0.5, granted latency=685.8 ms, 2 ch @ 44100 Hz,
mode=EXCLUSIVE. A bare device index is not evidence: indices shift as endpoints come
and go, one interface publishes several near-identically-named endpoints, and the same
endpoint appears once per host API.
Inserted-silence auto-recovery
A capture session that has latched into zero-filling is cleared only by stopping acquisition on
every stream that holds the device and starting again. This watchdog does it for you.
When a stream's digital-zero duty cycle stays above Trigger above for
Sustained for, Chirp stops acquisition on every stream sharing that input
device, waits for the operating system to tear the session down, then restarts them and
restores their recording state. Wait between attempts keeps a persistent fault
from turning into a restart loop. Every intervention is logged as
zero_run_recovery.
Defaults: on, above 5% digital zeros sustained for 15 s, at most one attempt per 120 s per device. Turn it off if you are trying to observe the fault rather than survive it.
Lost-device auto-reconnect
Separately from the zero-filling fault, a capture stream can stop delivering audio altogether
— classically because a remote-desktop connect or disconnect made Windows tear down or
re-route the audio endpoint. When no new frames arrive for five seconds, Chirp marks the stream
stalled, lights the ! badge, and logs
capture_dead. With Reopen a stream automatically when its device stops
delivering audio ticked (the default) it then closes the dead stream and reopens the
device by name, preserving the recording state.
That reconnect is not free: the teardown and reopen themselves cost audio. If your device tends to come back on its own — notably with a WDM-KS input, whose kernel-streaming pin sits below the per-session endpoint layer that RDP churns — the reconnect can do more harm than the stall it is reacting to. Untick the box to keep the detection and drop the automatic repair; the badge and the log line still tell you what happened, and you reconnect with Stop Acq → Start Acq when it suits you.
Amplitude envelope (trigger)
The trigger's question is "how loud is it right now?", asked of the band-filtered signal, sample by sample. That instantaneous loudness is the envelope, and Chirp can compute it two ways. This is an app-wide choice, and unlike the capture settings it applies to every running stream on the next block — no restart.
| Estimator | Behaviour |
|---|---|
| Hilbert (analytic signal) default |
Mathematically exact for a tone and has no delay at all, but is recomputed from scratch for each block of audio, which leaves a brief artifact (tens of samples) at every block boundary. |
| Rectify + low-pass | The classic envelope follower: take the absolute value, then smooth it. The smoothing
filter carries its state across blocks, so there is no boundary artifact at all — in
exchange the envelope lags the signal by roughly 1 / cutoff (about 20 ms
at the default 50 Hz). |
Low-pass cutoff applies to the rectify method only. It has to sit below your signal band, so the tone itself is smoothed away, and above the rate at which your calls turn on and off, so real onsets are not blurred. Lower it for a smoother, slower envelope; raise it to track fast onsets more tightly.
Inserted Silence (Zero Samples)
Audio drivers and the Windows audio engine sometimes fill gaps with digital silence instead of reporting them. When that happens, runs of exact zeros appear inside the captured signal: you can see them as gaps in the spectrogram, hear them as dropouts in the monitor, and they are written into the WAV files verbatim. Nothing in the recording chain above the driver can tell the difference between "the microphone was silent" and "the driver made this up" — except statistically, which is what Chirp does.
How Chirp detects it
- PortAudio flag — when the audio layer admits to inserting
zeros it raises
input_underflow, which Chirp counts and logs asunderflow. - Signal-level scan — the flag is often not raised, so Chirp
additionally scans the raw capture for runs of exact zeros lasting
1 ms or more and logs them as
zero_run. A live analog input never produces those: even in a silent room, the noise floor of the analog-to-digital converter guarantees the lowest bits keep flickering. An exact-zero millisecond is therefore inserted silence by definition, not quiet audio.
Either detector lights the sticky ! badge; hover it to see how many runs were found and how long the longest one was. The first second after Start Acq is deliberately ignored — a freshly-started capture legitimately delivers silence while the device primes.
What an episode looks like. Field logs from a 21-hour, 5-stream run: the fault arrives abruptly (0 to about 20% of samples zeroed within three seconds), affects one input endpoint at a time (both streams of a split stereo input show identical zero runs while other endpoints of the same interface stay clean), ramps upwards over the following hour or two, then clears on its own after 30–190 minutes. Severity is driven by how often the zero-fill happens, not how long each one lasts: the events stay 5–8 ms (one driver period) while their rate climbs from about 6/s to 37/s. Mean duty cycle across that run was 16% of all captured samples, peaking at 34%. Do not wait for it to clear itself — reset the device, or let the watchdog do it, as soon as the badge lights.
Reducing the odds
- Match the device's sample rate. If the endpoint's default format in Sound Control Panel → Recording → Properties → Advanced differs from the rate Chirp is running at, Windows silently resamples the capture — which can hide driver glitches. Chirp warns about this in the log when it opens the stream.
- Keep the interface on its own USB controller where possible, on a rear port, and not behind a hub shared with busy devices.
- Keep the driver and firmware current for your audio interface.
- Check the recordings, not just the badge — the log records exactly when the runs started, so you can tell which files are affected.
- Get out of the shared audio engine. Field measurement showed that raising
the buffer and the latency does not help: across a 21-hour run PortAudio never
raised
input_underflow, Chirp never fell behind, and no ring overrun was recorded — the zeros were already in the buffer handed to the application, below anything the app can reach. The layer below is the next thing to try: either WASAPI exclusive mode or the device's WDM-KS entry.
Recording over Remote Desktop (RDP)
Connecting to (or disconnecting from) the recording machine via Windows Remote Desktop can interrupt an ongoing recording: a session change tears down or re-routes the host's audio endpoints, which silently kills the open capture streams. Chirp defends against this with an auto-reconnect watchdog — but the best fix is to pick an input device that the session change cannot touch, and to prevent RDP's audio redirection in the first place.
Choose the WDM-KS input device (recommended)
The same physical device usually appears several times in the Input Device list, once per
Windows audio API — e.g. Microphone (MyCard) [MME],
[Windows DirectSound], [Windows WASAPI], and
[Windows WDM-KS]. These are different doorways into the same hardware: MME and
DirectSound are legacy shims layered on top of WASAPI, and WASAPI endpoints belong to the
per-session Windows audio engine — exactly the layer an RDP session switch
tears down and renames. WDM-KS (kernel streaming) binds the driver directly,
below the endpoint layer: its device name is stable across session changes and an
open capture stream survives an RDP connect/disconnect untouched. For a machine you reach
over RDP, always select the [Windows WDM-KS] entry.
As a bonus, WDM-KS bypasses the audio engine's mixer/resampler, so capture is bit-exact at the card's native rate with the lowest overhead of the four APIs. Two caveats: access is exclusive (one Chirp stream per WDM-KS device — on multichannel interfaces each stereo pair is a separate device, so use one stream per pair — and other applications cannot use the device while Chirp holds it), and the stream's sample rate must be natively supported by the card — there is no hidden resampler to absorb a mismatch, an unsupported rate simply fails to open.
Prevention: disable RDP audio redirection
On the machine you connect from, in the Remote Desktop client (mstsc):
- Open Show Options → Local Resources → Remote audio → Settings…
- Set Remote audio playback to “Play on remote computer”.
- Set Remote audio recording to “Do not record”.
Alternatively (and more robustly, since it works regardless of the client's settings), disable
audio redirection on the recording host via Group Policy (gpedit.msc):
Computer Configuration → Administrative Templates → Windows Components →
Remote Desktop Services → Remote Desktop Session Host → Device and Resource
Redirection — set “Allow audio recording redirection” to
Disabled (registry equivalent: fDisableAudioCapture=1 under
HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services). Consider also
disabling “Allow audio and video playback redirection” if you don't need remote
playback.
Auto-reconnect watchdog (built in)
Even with redirection disabled, Windows may briefly bounce audio endpoints on a session
switch. Chirp watches every live-device stream: if a capture stops delivering frames for
~5 seconds while acquisition is running, it is declared dead — in-flight trigger
events are flushed to disk first, then Chirp re-resolves the device by name and
reopens it, retrying with increasing backoff until the device returns. Recording re-arms
automatically. If frames resume on their own before the reconnect starts (a transient churn,
common when AnyDesk or RDP attaches), the recovery is cancelled and the healthy stream is left
untouched. All recovery work runs on a background thread, so the UI stays responsive even if
the audio driver blocks. The stream's ! badge latches and
chirp_errors.log gets capture_dead entries for both the outage and
the reconnect, so the gap is always visible after the fact.
The reconnect itself costs audio, so it can be a poor trade when the device recovers on its own — which is typical of a WDM-KS input, whose kernel-streaming pin sits below the endpoint layer RDP churns. Untick ⚙ Advanced → Lost-device auto-reconnect to keep the detection (badge and log line) while handling the reconnect yourself with Stop Acq → Start Acq.
Display rendering in remote sessions (built in)
Windows Remote Desktop replaces the display driver for the duration of the session, which breaks live OpenGL rendering (the historical cause of Chirp appearing frozen when viewed over RDP). Chirp handles this automatically: when it starts inside a remote session — or when an RDP session attaches mid-run — every plot switches to software (raster) rendering, and OpenGL is restored when the console session comes back. Screen-mirroring tools such as AnyDesk or TeamViewer mirror the console session and are unaffected. No configuration is required.
Mouse & Keyboard Interactions
| Action | Target | Effect |
|---|---|---|
| Click & drag | Amplitude threshold line | Adjust amplitude trigger threshold |
| Click & drag | Entropy threshold line | Adjust spectral entropy threshold |
| Scroll wheel | Amplitude plot | Zoom Y-axis (anchored at zero) |
| Scroll wheel | Waveform plot | Zoom Y-axis (symmetric around zero) |
| Scroll wheel | Entropy plot | Zoom Y-axis (centered on mouse cursor) |
| Scroll wheel | Spectrogram | No effect (use Display panel frequency controls) |
| Right-click | Amplitude plot | Context menu: switch Y axis between Linear and Log (dB) |
| Right-click | Sidebar background | Context menu: Start All / Stop All |
Tips & Best Practices
Setting the Threshold
Use Auto-Calibrate to quickly set a threshold above the ambient noise floor. Fine-tune by dragging the yellow threshold line on the amplitude plot while monitoring a live signal.
Capturing Complete Vocalizations
Set a generous Pre-Trigger buffer (0.5–2 s) to ensure you capture the onset of each vocalization. Use Hold to bridge short pauses within a phrase, and Post-Trigger to capture trailing echoes or reverberation.
Reducing False Triggers
Increase Min Cross to reject brief transients. Enable the bandpass filter to ignore out-of-band noise. In environments with broadband noise, switch to Amp AND Spectral detect mode so that only tonal sounds trigger recording.
Frequency Scale Selection
Use Mel frequency scale for bioacoustics work. Mel spacing approximates perceptual frequency resolution and provides better visual separation of harmonics in birdsong and other animal vocalizations. Use Log for general-purpose analysis and Linear when precise frequency measurements are needed.
Multi-Stream Monitoring
Configure all your streams in Config Mode, arm recording on each, then switch to View Mode for a clean monitoring display. Use the Sync checkbox to keep display parameters consistent across streams.
Long Recording Sessions
Always save your configuration before starting a long session. Set Max Rec to a reasonable limit (e.g., 300 s) to prevent individual files from growing too large. Monitor available disk space—uncompressed WAV files consume approximately 176 KB/s per channel at 44,100 Hz.
Reference Date for Experiments
If you are tracking development over time (e.g., days post hatch in bird research), set the Reference Date to the start event. Recordings will be automatically organized into day-count subfolders, making longitudinal analysis straightforward.
FFT Settings
Larger FFT sizes (2048, 4096) provide finer frequency resolution but coarser time resolution. Smaller sizes (256, 512) give better time resolution at the expense of frequency detail. For birdsong, 1024 is usually a good compromise at 44,100 Hz sample rate. The Flattop window is best for accurate amplitude measurement of pure tones; Hann is the best general-purpose choice.