scope_buffer.h
The scope's buffer, with no user interface anywhere near it.
#include <sonore/scope_buffer.h>- 1type
- Guides: Getting started, MIDI and MPE
On this page
Design notes
Why this is not part of the widget
The producer is the AUDIO THREAD and the consumer is a component. Keeping both inside one Widget would mean the wrapper -- which has to feed it from process() -- depending on the whole UI stack: fonts, look and feel, the rasteriser. It would also mean the buffer only existing while an editor is open, so a scope would start blank every time somebody opened the window instead of showing the last second of audio.
So the buffer lives here, owned by whatever owns the audio, and the widget points at one. Exactly the split WaveformView and AudioThumbnail already have, and the same one MeterState has had since before there was a native UI.
The real-time constraint
push() allocates nothing, takes no lock and does not block. The buffer is fixed-size and written with relaxed atomics; the UI reads whatever is there. A torn read shows one wrong column for one frame at thirty frames a second, which is invisible. A lock on the audio thread is a dropout, which is not.
Types 1
A ring of min/max columns.
Each column is the minimum and maximum of however many samples fell into it, not one sample picked out of the group. A scope that plotted every Nth sample would alias badly -- a 10 kHz tone at 48 kHz is under five samples a cycle, and sampling that at pixel intervals draws a slow wobble that is not in the audio. Min and max draws the envelope, which is what an analogue scope shows.