Skip to content

Releases: JonasGrunau/open_audio_analyzer

Open Audio Analyzer v0.11.0

Choose a tag to compare

@github-actions github-actions released this 24 Aug 19:02

📐 Measurement

  • Audio missed while the capture source was stopped is now counted as lost
    audio, so the frame count includes it and the warning appears. It previously
    counted nothing at all: integrated loudness and LRA average every block since
    the reset, so a device that stopped for a minute produced a reading of the
    programme minus that minute and presented it exactly like a clean one. A
    stall's share of the count is derived from the analysis clock rather than from
    the ring, so it is accurate to about a quarter of a second rather than to the
    frame — enough to prove audio was lost, which is what the figure is for.
    Re-measure any session where the warning appeared.
  • The System Output tap no longer measures an output device that has changed its
    own sample rate. A macOS output device can move rate without ceasing to be the
    default output — AirPods drop from 48 kHz to 24 kHz the moment anything opens
    their microphone — and the tap went on delivering while the K-weighting
    filters, the true-peak oversampler, the spectrum's frequency axis and the
    elapsed clock all stayed built for the rate the engine opened at. Every
    reading was then wrong by the ratio between the two rates: at half the rate
    the spectrum sat an octave low and the elapsed clock ran at half real time,
    with the meters moving convincingly throughout. The source is now reported as
    stopped and reopened at the device's new rate. Re-measure anything metered
    through System Output on a Bluetooth output device.

✨ Added

  • A File menu, and presets that are documents. Open… picks a preset
    through the platform's own dialog, starting in the presets folder and reaching
    anywhere else you point it — a preset somebody sent you now opens where it was
    downloaded to, instead of having to be moved into the configuration directory
    first. Save writes back to the file it came from without asking, Save as…
    places a copy anywhere and names the preset after the file, and the open
    preset's name sits at the left of the status bar with a dot beside it when it
    differs from what is on disk. On macOS the menu is in the system menu bar,
    after the application menu; on Windows and Linux it is the FILE button in the
    status bar. Opening a preset over unsaved changes asks whether to save first.
  • A privacy policy, at
    open-audio-analyzer.com/privacy.
    It states what the microphone, the camera, the local network and the disk are
    used for, that nothing is collected or transmitted, and — the part worth
    reading — that the remote display link has neither encryption nor
    authentication, so publishing on a network you do not trust means anybody on
    it can read your meters. App Store Connect requires the URL; the page is
    written for a person rather than for that field.

⚡ Changed

  • The website serves its three typefaces itself instead of loading them from
    Google Fonts. Reading a page no longer makes a request to Google, which
    previously saw the IP address of everybody who opened one — the privacy policy
    said so and now says the opposite. It is also the reason the site's text used
    to move a moment after the page appeared: the fallback face is a different
    width, so the first paragraph re-wrapped once the real one arrived.
  • The faintest text on the website — the footer, the small readouts above each
    section, every table heading and the documentation contents list — is light
    enough to read. It was the application's own textFaint, which is 2.97:1
    against the page and under what WCAG asks even of large text; in the
    application it labels a meter you are already looking at, and on a phone in
    daylight it was text you could not. The application's own interface still has
    this and is not changed here.
  • ⌘O now opens a preset, and analysing an audio file has moved to ⌘I. The
    layout is this application's document — the thing that is opened, saved and
    sent to somebody — so it takes the chord every desktop user tries first, and
    analysing a file is an import, which is what ⌘I means elsewhere. Save on ⌘S
    and Save as… on ⇧⌘S are both new. Ctrl on Windows and Linux, as always.
  • The preset browser is gone, and ⌘P with it. Saving is Save and Save as…;
    the list of saved layouts is the presets folder in a file manager, which is
    also where the delete button that used to be in that panel now lives.
    Settings → Session still prints that folder and lets you select the path.
  • Whether a preset carries the delivery target and the skin is a property of the
    preset now, rather than two switches beside a Save button: two rows in the File
    menu, each asking whether the preset should carry one and ticked when it
    does. They cannot go in the platform's save dialog — macOS would need a save
    panel of our own, Windows a plugin of its own, and Linux cannot do it at all
    — and as properties of the document they survive a save, which the
    switches did not.
  • The plugin's window is drawn in the application's own palette and the
    application's own two typefaces, both compiled into the VST3, the Audio Unit
    and the Standalone rather than asked of the platform — so the panel looks the
    same in Logic on a Mac as it does in Reaper on Windows, and looks like the
    tool whose meters it is feeding. What it shows changed with it: a diagram of
    the three places the path can break, with each run lit only while something is
    travelling down it, and the socket's dashes moving while frames are actually
    being sent, so a link that came up and quietly stopped no longer looks
    identical to one that is working. The middle of that chain is the app icon
    itself, drawn as line art in the shape macOS masks an icon with, so the thing
    you picked out of the DAW's plugin browser and the thing in the diagram are
    recognisably the same object. It also names the format it is loaded in and
    the host it is loaded into, which are the first two facts on every bug report
    and were the two nobody wrote down.
  • A dropped-frame warning in the plugin's window no longer erases the readings
    it is a warning about. The count, the missing playhead and the loudness
    reading shared one line, so the worst news arrived by deleting the evidence;
    the readings now have a row of their own and the warning sits directly above
    the Reset button that answers it.
  • The plugin's window says where the meters are when everything is working. A
    metering plugin that draws nothing is a confusing object the first time
    somebody inserts one — it loads, it reports itself healthy, and nothing
    happens — and the line that was blank in exactly that case is the calmest,
    most readable moment in the window.
  • The Super Meter's target tick is a plain mark again rather than one cut into
    the arcs. 0.10.0 widened the slot beneath it to stand 1.5 px out either side,
    which put a notch through all three rings at the target; the slot is back to
    the tick's own width, so the rings run unbroken and only the tick crosses
    them. 0.10.0's note describing the wider slot stands as written and is
    superseded by this one.
  • Every menu in the application marks the value it holds with a check and a
    band across the whole row. The band used to be the darkest colour in the skin,
    which in Precision Instrument put a near-black hole in a menu that is itself
    nearly black, and it stopped short of the menu's edges so the current value
    read as a chip sitting in the list rather than as one of its rows. It is a
    wash of the colour the rest of the interface already uses for selection now,
    it reaches both sides, and the check says which row it is without anybody
    having to compare two greys. Menus of actions — duplicate, rename, delete —
    hold no value and are unchanged.
  • The iPad build no longer offers itself to iPhones. Its Xcode target had been
    universal since the project was created, so a phone could install a
    twenty-four-column canvas drawn for a tablet, and App Store Connect asked for
    a set of iPhone screenshots of it. It is iPad-only now, which is what every
    document already said it was.

🐛 Fixed

  • The live analyzer's own document no longer offers itself to search engines as
    oaa_analyzer_demo, described as "A new Flutter project.". It is the page the
    front page loads into an iframe, and it had shipped as the Flutter scaffold
    wrote it — no language, no viewport, and a title and description that
    described the project worse than nothing would have. It now says what it is
    and asks not to be indexed.
  • The website's 404 page no longer asks to be indexed, and no longer tells
    crawlers that every address without a page is really /404.
  • "Linux dependencies" in the building document is a second-level heading, so
    the page no longer skips from its title straight to a third level.
  • Re-saving a preset no longer silently drops the delivery target or the skin it
    was carrying. The two switches in the preset browser reset to off every time
    the panel opened and were never read back from the preset being saved, so
    opening a layout that carried EBU R 128, moving one module and saving wrote a
    preset that carried nothing — and nothing in the interface said so. They are
    rows in the File menu now, and they are ticked from the preset itself.
  • The meters no longer freeze until you switch to another source. A capture
    source that stopped delivering left the engine publishing an empty ring at the
    same forty-seven frames a second for the rest of the session: every meter held
    its last reading, the window and the menus stayed perfectly responsive around
    it, RESET moved the readings to their floors and they held there, and
    nothing anywhere said why. The engine now notices within a quarter of a
    second, puts the source back itself when the format allows it, and says so on
    screen; when only a new engine can follow the device, the application opens
    one and the notice says the measure...
Read more

v0.10.1

Choose a tag to compare

@github-actions github-actions released this 23 Aug 01:02

⚡ Changed

  • The name under the application's icon is Audio Analyzer on iPadOS and
    Android, where it was OAA. A home screen gives a label about eleven
    characters before it starts dropping the spaces out of one, so the full name
    has never fit there and the initials went in instead — which read as an
    acronym nobody outside this repository knows. Nothing else is renamed: the
    bundle identifier, the window title, the installers and the desktop builds
    are untouched, so no permission grant moves with it.

🐛 Fixed

  • The documentation site's sitemap names the eight documentation pages as well
    as the front page. It had named the front page alone since before the manual
    was part of the site, so nothing but the home page was being offered to a
    search engine that asked.
  • The version on the site's download button is read from pubspec.yaml at
    build time. src/lib/app.mjs was written to do exactly that and then had no
    importer at all — both pages still carried the number as text, so the button
    was correct only for as long as nobody tagged anything.

🚧 Internal

  • The site's demos replay what the engine measured instead of playing a mock.
    website/tools/oaa_record/ is a Dart CLI that links the real engine by FFI,
    pushes forty-five seconds of a real track through it and writes down the
    readings; website/tools/oaa_replay/ holds that format and ReplaySource,
    a fourth MeterSource beside native memory, the socket a tablet reads and
    the mock this replaces. Both Flutter targets play the same recording, so the
    fourteen stills and the live canvas can no longer disagree about what the
    material did — and no reading on the site is invented any more. The track is
    CC BY 3.0 and is not in this repository: npm run record refuses to run
    without the attribution file tool/fetch_test_audio.dart writes, because the
    licence asks for the credit wherever the audio is published, and the front
    page carries it under the canvas.
  • npm run check in website/ opens every page at 360, 390 and 768 px with
    the viewport actually overridden and fails if the document scrolls sideways,
    naming the widest element rather than the overflow. It is the one responsive
    defect that is invisible in a screenshot and obvious on a phone, and a
    browser window cannot be dragged narrow enough to show it. Not part of
    npm run build, because it needs Chrome.
  • The front page's hero is one column and a measure wide rather than two, and
    the section rail in the manual tracks at 0.08em so that the longest heading
    fits on one line in the 215 px it has.
  • Claude Code's .claude/ is ignored. Its settings.json named a hook by an
    absolute path inside one developer's home directory, which would have failed
    silently on any other machine.
  • The website's tab icon survives a run of the icon generator.
    packaging/icon/make_icons.dart wrote the app icon's tile over
    website/public/favicon.svg, which is a different drawing on purpose — the
    wave cropped out of the tile and stroked in the signal colour, because a tab
    shows it at 16 px where the tile is mostly ramp. The hand-drawn version
    therefore lasted until the next run of the generator and was reverted with no
    error and no diff anybody read. The generator no longer writes that one file,
    and says why where the line was.
  • website/public/oaa.svg is back. It is the app icon's tile, written by the
    generator, and scripts/og.html references it rather than holding a copy of
    the mark; it was deleted in the change that redrew the logo while that
    reference stayed, so the Open Graph card had been pointing at a missing file.
  • website/AGENTS.md describes the directory as it is: the documentation pages
    and the two lists that decide what they are, the live analyzer and the mock
    the two Flutter targets share, and why tools/ is outside the repository's
    analyze gate. Its file table had been an inventory of a website that no longer
    existed — three files it named were gone and eighteen it did not name were
    there.
  • CLAUDE.md, assets/AGENTS.md and tool/AGENTS.md no longer say that
    tool/docs.dart renders the documentation site. It renders one redirect per
    page now, and the manifest it used to carry lives in
    website/src/lib/docs.mjs.

v0.10.0

Choose a tag to compare

@github-actions github-actions released this 22 Aug 22:14

✨ Added

  • A skin editor. Settings → Appearance → Edit skin opens all thirteen colour
    roles with a picker on each, and the canvas behind the panel repaints as you
    drag — as does a tablet mirroring the session. Every role prints its contrast
    ratio against the surface it is read on, and the ones below the floor that
    role is held to are marked with the reason; a low-contrast palette still
    saves, because refusing to save what is already on screen is worse than a
    warning. Skins remain plain JSON files and hand-editing them is unchanged.
  • Skins can be deleted from the editor, which previously meant finding the file.
  • Reset, beside Edit on Settings → Meters → Delivery target, deletes every
    target you have saved and puts the built-in six back. It asks first, in a
    dialog naming what goes, and afterwards says how many files it removed.
    Targets you wrote by hand are gone from the disk, so this is also how a
    correction to a built-in is undone without going looking for its JSON file.
  • The VU Meter marks where the needle reached. A mark rides the scale at the
    loudest point of the last second and a half and then falls back to the
    needle, because a 300 ms movement is slow by design and the loudest moment of
    a phrase is over before the needle has finished describing it. It is the same
    quantity the needle draws, held rather than measured a second time.
  • The VU Meter prints its reading and its reference along the bottom of the
    face: the deflection in VU on the left, and which dBFS level reads as 0 VU on
    the right. The second one is the genuinely confusing thing about a VU meter
    and the face now says it out loud. A module too small for either drops it and
    keeps the dial.
  • The Spectrogram and the Oscilloscope can be drawn in full colour.
    Colour: Full RGB in either module's menu replaces the skin's one-hue ramp,
    and what it paints is the quantity that module's axes leave uncoloured. On the
    Spectrogram that is the level: the spectrogram rainbow, indigo through
    green and yellow to red and white, which separates far more steps of level than
    one hue can. On the Oscilloscope it is the band balance, because a waveform
    has no frequency axis at all: red, green and blue are its bass, its mids and
    its highs, split at 200 Hz and 2 kHz, so a kick is red, a hat is blue and a
    full-spectrum hit is white, the way DJ software has coloured audio for twenty
    years. That balance is taken in decibels against the loudest of the three bands
    rather than in power — bass carries an order of magnitude more power than air
    does, and a power mix draws every piece of music red — and it is recorded with
    the column, so the picture holds its colours instead of being repainted by
    whatever is playing now. A column whose source published no spectrum keeps the
    accent rather than being handed a colour that would claim a balance nobody
    measured. Off by default in both, because a rainbow reads as more precise
    than the measurement behind it, it collapses for the eight percent of men who
    cannot separate red from green, and on the Spectrogram it brings its own dark
    ground into a light skin. Nothing measured changes at either setting: no
    reading, no report and no byte on the wire moves.

⚡ Changed

  • A menu marks the value it holds by recessing that row, not by brightening
    it.
    Every dropdown in the application — the delivery target, the signal
    source, and a module's dozen settings — used to print its current value as the
    lightest row in the menu, which put the emphasis on the one choice pressing
    cannot change and left the options you can still take looking greyed out. The
    chosen row now sits in a darker well and the alternatives sit on the menu's
    own surface, which is how selection reads everywhere else in the interface.
    Nothing about what the menus contain or choose changed.
  • The signal source in the status bar is a bordered chip, the same shape the
    delivery target beside it has always had. It is the menu people open most and
    it was drawn as a dot and a bare word in a row of bordered controls, which
    reads as a caption rather than as something you can click. The dot stays,
    inside the chip: bright while something is being metered, dim on Silence.
  • The OAA wordmark is gone from the status bar. The window carries the
    application's name; the bar carries what changes while you work, and three
    capitals that never change were the one item in it saying nothing about the
    signal. Every width at which the bar drops an item moved with it — the
    controls at the narrow end now leave 25 to 40 px earlier than they did,
    because a bordered chip cannot give back the width a bare word could. All of
    them still have keyboard shortcuts except the three remote controls, which is
    unchanged.
  • The sample rate no longer prints flush against the DAW's playhead. The gap
    between the source group and the readings is a fixed one now rather than
    whatever the window had left over, so it is there at every width instead of
    only on a wide one.
  • The VU Meter has a face. The scale is a band along the rim rather than a
    hairline arc, red above 0 VU over a tinted ring, and the needle is a taper
    under a machined hub — so how far up the scale the programme is can be read
    from the rim before the needle is read at all. Nothing about the movement,
    the ballistics or the reading changed.
  • The Loudness Distribution fits its loudness axis to the programme instead of
    always drawing −60 to 0 LUFS. A mastered programme's gated distribution
    occupies eight to fifteen of those sixty decibels, so the picture the LRA
    reading is taken from was squeezed into a fifth of the module with the rest
    left blank; the axis now holds every occupied bin, the gated range and the
    delivery target, rounds outwards to whole ticks, and stays where it is until
    the distribution grows past it. No reading changes — the same bins are drawn
    against a shorter stretch of the same scale. Scale: Full range in the
    module's menu restores the published axis, which is the one to pick when two
    distributions are being compared side by side.
  • Open Audio Analyzer has a new logo, and every icon it ships follows it. A
    white waveform on a teal ramp, replacing the four teal bars on graphite. The
    app icon, the installers' icons, the Android launcher icon, the layered icon
    macOS and iOS render, the favicon, the documentation site's header, the
    README and the social card all change together. The tile is also a rounder
    shape than it was, because the one macOS 26 and iOS 26 draw is rounder than
    the one every version before them drew. Nothing about what the application
    measures or displays is affected.
  • The icon reads less well at 16 px than the one it replaces, and that is a
    real cost rather than an oversight. Four bars at four heights survived being
    two pixels wide; a waveform with nine excursions across twelve pixels does
    not, and no stroke weight rescues it. The line is held at one device pixel so
    that it stays white instead of smearing to grey, and the sizes the icon is
    now designed around are 32 px and up. Where this shows is the Windows
    Explorer list view and a Linux panel at its smallest setting.
  • Precision Instrument and Daylight can no longer be replaced. A skin file
    naming one of their two ids used to shadow the built-in; it is now ignored,
    and the skin editor offers Save as new rather than an in-place save. The two
    shipped skins are what proves the thirteen colour roles are semantic rather
    than aliases for particular colours, and a reference point a file on disk can
    quietly redefine is not one. If you had such a file it is inert now
    rename its id and it comes back as a skin of its own. Delivery targets are
    unaffected and still shadow their built-ins, because a target is a claim about
    somebody else's published specification and has to be correctable without a
    release.

🐛 Fixed

  • The VU Meter no longer draws a needle for a reading nobody measured. The
    per-channel arrays are NaN while a remote display's link to the host is
    quiet, and the dial rested at the bottom of its scale with exactly the
    confidence it reads a quiet passage with; the face now shows no needle and
    the reading is an em dash. Only a tablet display could reach this.
  • The VU Meter's scale numbers no longer overprint each other on a small
    module: −5 and −3 sit close together on a face that crowds towards the bottom
    in voltage, and at the narrowest widths they collided into one smear. The
    face now sheds the numbers it has no room for, keeping 0 and both ends.
  • A panel that scrolls draws one scrollbar rather than two. Settings, and
    every other panel tall enough to scroll, carried the skin's own thumb on its
    right edge and a second, wider grey one immediately inside it, which faded in
    whenever the panel was scrolled. The second was supplied by Flutter, which
    decorates a scrolling region on macOS, Windows and Linux without being asked;
    the panel now declines it. Tablets never showed it.
  • The Super Meter's target tick sits in its slot again. The slot is a
    surround laid down under the tick so that its contrast is identical on all
    three rings, whatever each ring is currently drawing; it was being stroked at
    exactly the tick's own width, so the tick covered it completely and was read
    against the arc after all. It stands 1.5 px out either side now, which is what
    the constant describing it always said. The tick itself is unchanged.

🚧 Internal

  • The skin editor's suite waits for the effect of a save rather than for the
    file. Its helper stopped as soon as the skin's file existed, which is one
    event-loop turn before the editor is told the write finished — so the four
    ...
Read more

v0.9.0

Choose a tag to compare

@github-actions github-actions released this 22 Aug 16:47

📐 Measurement

  • 7.1 material reads 0.35 LU quieter, and correctly. The +1.5 dB surround
    weight was applied to every channel past the LFE, so a 7.1 stream had it on
    the rear pair as well as the side pair. BS.1770 gives it to the surround pair
    only — Report ITU-R BS.2217's channel table states 7.1 as
    1.00 / 1.00 / 1.00 / N/A / 1.41 / 1.41 / 1.00 / 1.00 — and the ITU's own
    two 7.1 compliance files read 0.35 LU high against a ±0.1 tolerance until this
    was fixed; they now read −23.000 and −24.000 exactly. Only 7.1 and wider is
    affected
    : mono, stereo, quad, 5.0 and 5.1 never reached the arm that was
    wrong, and every reading from them is unchanged. Anything measured from a 7.1
    master — its LUFS-I, LUFS-M, LUFS-S, LRA and the delivery verdict
    drawn from them — was 0.35 LU too loud and is worth re-measuring.
  • Max M and Max S are found on a 10 ms grid, where momentary and
    short-term loudness previously advanced only every 100 ms.
    The official EBU
    test vectors caught this: Tech 3341 tests 13 and 14 slide a 400 ms tone —
    exactly one momentary window long — through twenty files in 20 ms steps and
    require Max M within ±0.1 LU of −23.0 every time. On a 100 ms grid a tone
    offset by anything else never lies inside one window whole, so sixteen of the
    twenty read low, by up to 0.45 LU, and test 14 by 0.70. Every Max M and
    Max S therefore rises rather than falls: on the EBU's two authentic
    programme segments Max M rises by 0.16 and 0.11 LU and Max S by 0.02 and
    0.01, and a transient that fell between the old grid points can rise by up to
    0.7 LU. LUFS-I, LRA and its percentiles, TP Max and Peak Max are
    unchanged
    — identical to three decimals across all 70 files of the test set
    — because both gating windows are still filed every 100 ms, which is the 75%
    overlap BS.1770 asks for. Re-read a delivery decision that turned on Max M
    or Max S against a ceiling; one that turned on the integrated numbers stands.
  • The spectrum analyser draws its bands tilted, at 4.5 dB per octave by
    default.
    The curve is rotated about 1 kHz, so 20 Hz is drawn 25.4 dB lower
    than it measures and 20 kHz 19.4 dB higher — 44.8 dB between the ends of the
    range, where previously the drawn level was the measured level at every
    frequency. It is a view: the offset is added per band at the moment of
    drawing, and Spectrum and Spectrum peak are published and sent over the
    wire exactly as the engine measured them, so nothing needs re-measuring. What
    changes is that a level read off the analyser's own dB scale is only true at
    1 kHz now, which is why the module prints the tilt it is drawing at and why
    Tilt: 0 dB/oct — where the scale is true everywhere — prints nothing.
  • The analyser's peak-hold line holds the drawn curve rather than the raw
    bands.
    It is the highest the curve has been, held for a second and a half
    and then let down at 12 dB a second, which is the schedule the engine's own
    per-band hold already followed. Two consequences: the line moves with the
    curve instead of jumping to a peak the curve is still easing towards, and on
    Response: Slow it reads lower than it used to — by as much as the pole
    smoothed the transient away — because the curve it is holding never went
    there. Response: Fast holds every published frame and is the setting to
    find a click with. Spectrum peak itself is unchanged.
  • The histogram draws both of its bands averaged over a second, where it
    previously drew every 100 ms column exactly as measured.
    Smoothing in its
    menu chooses Off — the old picture, byte for byte — Light at 0.5 s, Normal at
    1.0 s or Broad at 2.0 s, and Normal is the default. The window is centred
    rather than trailing, so nothing moves along the time axis; what it costs is
    height on a short event. A transient the momentary band reached for a single
    column now reads lower by roughly the distance between that column and its
    neighbours — a 6 LU spike over a steady body reads about 1 LU above it on
    Normal — and the newest column at the right edge lags the live meters by up to
    half the window, settling as it ages. Nothing measured changes: the ring holds
    the columns as they arrived, the smoothing is applied on the way out every
    frame, and reports, the wire protocol and every other loudness module are
    untouched. Choose Off to find the loudest 100 ms in a programme.
  • The loudness distribution's fill no longer double-draws itself. Each of
    the 120 published bins was stroked half a pixel wider than its own spacing to
    keep butt caps from leaving seams, so every overlap was composited twice
    through the translucent gradient — a brighter line at all 119 bin boundaries,
    and on a default-sized module nearly a fifth of the fill drawn at double
    alpha. The bins are unchanged and none of them moves; what changes is that the
    drawn area is now a shape rather than a row of overlapping lines, and a column
    covering more than one bin takes the loudest of them rather than blending
    them, the way the engine already maps transform bins into spectrum bands.

✨ Added

  • The oscilloscope locks to the DAW. Sync: Tempo makes the width a
    musical division — 4 bars down to 1/32, straight, triplet or dotted — and
    puts every sample in the column its position in the bar falls in, so each
    pass overwrites the last in place and a kick is drawn in the same spot every
    bar. The graticule divides into beats rather than tenths while it is locked,
    and the corner says which division is on screen. It uses the host's own
    playhead, tempo and time signature, which the plugin already forwards: MIDI
    clock carries neither a bar position nor the accuracy, and is not involved.
    A source with no playhead — a sound card, or a DAW that reports none — draws
    the free window and labels it as the free window, because a display that
    said 1 bar over something else would be worse than one that is not synced.
  • The spectrum analyser has a tilt, Tilt in its menu: 0, 1.5, 3, 4.5 or
    6 dB per octave, rotated about 1 kHz. Programme material falls with frequency
    at something like 3 to 4.5 dB an octave, so an untilted analyser draws every
    mix ever made as the same ramp — bottom octaves against the ceiling, top
    octaves crushed into the floor — and spends most of its height on the one
    part of the picture that carries no information. Tilted, a mix is roughly
    horizontal and what is left is the deviation. The analyser prints the tilt it
    is drawing at, because a dB scale quietly rotated across its width is worse
    than no scale at all.
  • The oscilloscope draws a stereo signal either as two lanes or with both
    channels around one centre line, from Stereo in its menu. Overlaid, the
    two are told apart by weight rather than by colour, and the trace gets the
    whole height of the module — which is the arrangement that shows what the
    channels are doing differently.
  • The oscilloscope can be triggered by a transient. Trigger: Transient
    makes the display wait, armed, until the signal rises through a level you set,
    draw forward across the whole width once from that sample, and hold what it
    caught until the next crossing. It works at every time base — the roll above
    200 ms is replaced by the sweep rather than left in place — so the attack of
    one kick can be looked at instead of a picture that lands somewhere different
    every pass. Trigger: Auto, which is the default and what the module did
    before, is unchanged: a rising zero crossing below 200 ms, a rolling display
    above it, and always something on screen. A threshold nothing reaches leaves
    the last capture where it is, which is the mode working rather than failing.
    Trigger stays in the module's menu under Sync: Tempo, greyed rather than
    dropped: a bar-locked window is placed by the bar line and has no use for it,
    and a row that vanishes is a row somebody hunts for.
  • The oscilloscope's height and trigger threshold are sliders on the
    module
    , HEIGHT and THRESHOLD in a strip along the bottom of the plot,
    and the threshold is drawn across the lane at the height it is set to. Both
    are numbers over a wide range that are chosen by watching the waveform while
    they move, and a menu that closes over the waveform on every step cannot be
    used for that. The height goes from 1x to 32x, continuously rather than in
    named steps — a reverb tail thirty decibels under full scale is a flat line at
    1x, and the setting that fits the material is rarely a round multiple. The
    strip is dropped on a module too short to spare the room, like the graticule
    and the lane letters, and is not drawn on a remote display, which has no
    layout to write to. Nothing measured changes: a sample is still marked as
    clipped only if it reached full scale, and a trace that runs off its lane is a
    trace that is zoomed.
  • AUTO beside the threshold takes it from the loudest transient. It
    follows the largest positive excursion of the mid signal over the last two to
    four seconds — the quantity the trigger itself compares against — and sets the
    threshold six decibels under it, which is half the amplitude and so still
    inside the attack: the sweep starts before the transient rather than on top of
    it, which is what a threshold set exactly at the peak would do. The slider
    shows where the level has got to and stops answering while the box is checked;
    unchecking it keeps the number Auto found rather than snapping back to
    whatever was dragged before. Silence moves nothing — a passage nobody played
    is not a measurement, and a threshold dropped to the floor would arm the
    trigger on the noise underneath it.
  • The histogram has a Smoothing setting — Off, Light, Normal or Broad....
Read more

v0.8.0

Choose a tag to compare

@github-actions github-actions released this 22 Aug 10:34

✨ Added

  • An Oscilloscope module: the waveform itself, in a lane per channel. Its
    one control is a time base, from 5 ms to 5 s, and it sets both how much time
    the width holds and how the window is found — below 200 ms the display is
    triggered on a rising zero crossing, so a periodic signal stands still and
    can be read, and above it the display rolls right to left the way a DAW
    draws a waveform. Anything that reached full scale is drawn in the over
    colour, so a clipped passage is a red band rather than a flat top somebody
    has to notice. It measures nothing the previous thirteen modules did not:
    the samples were already published, and it works on a tablet unchanged.
  • The oscilloscope leaves a gap where audio was measured and never published —
    a file pushed through faster than real time, or a device that overran. The
    alternative is drawing the samples that happen to be at hand across the
    whole stretch, which is a picture of a programme that never played, at the
    right amplitude and in the right place.

⚡ Changed

  • The default layout's Spectrum tab carries the oscilloscope across its full
    width. The analyser and the three displays below it are a row shorter each
    to make room. A layout you have already arranged is untouched — the canvas
    as you left it is what reopens.

🚧 Internal

  • The meter clock now acquires the engine's snapshot on every tick and throttles
    only the repaint. The frame-rate setting still does what it says — at 30 fps
    the meters rasterise thirty times a second — but a measurement is no longer
    lost between two of them. The engine's snapshot has one slot, so anything a
    reader does not take before the next publish is gone; that cost the old
    arrangement one measurement in three at 30 fps against a 47 Hz publish rate.
    The oscilloscope is the first module for which that is a hole rather than a
    coarser picture, and it reads the new unthrottled channel.

v0.7.0

Choose a tag to compare

@github-actions github-actions released this 22 Aug 09:07

✨ Added

  • Pairing a display by camera. The sending machine shows a QR code under
    the code button beside PUBLISH in its status bar, and a tablet reads it
    under Scan a QR code on the screen it opens with. It carries the address and
    the port and nothing else, so a display that scans one can still only watch.
    This is the route that works where discovery does not — a venue or a guest
    network that blocks multicast previously left somebody reading four numbers
    off a laptop across the room and typing them into a tablet.
  • The pairing code names which network interface it is for, on a machine with
    more than one. A laptop on Wi-Fi with a dock has two addresses and only one
    of them may be reachable from the tablet, which is not knowable from the
    sending side.
  • Scanning is offered on Android, iPadOS and macOS. Windows and Linux have no
    camera implementation, so the row is absent there rather than present and
    refusing; the typed address is offered on every platform, as before.
  • The macOS, Windows and Linux downloads now install the plug-in for you, with
    a checkbox that starts ticked. macOS offers the VST3 and the Audio Unit as
    separate rows, Windows and Linux the VST3; unticking leaves the application
    on its own. Previously the plug-in was a bare archive and the instructions
    for placing it by hand ran to a screenful, most of which existed because a
    bundle in the wrong folder and a bundle that failed to load look identical
    from inside a DAW.
  • A plug-in installed by the macOS package needs no xattr step. Files placed
    by an installer are not quarantined, so the Gatekeeper refusal that has no
    override — the one a DAW reports as "could not verify … is free of malware" —
    does not arise.
  • The Windows installer registers an uninstaller under Settings → Apps, which
    removes the plug-in as well as the application.
  • A third Linux download, a tarball, beside the AppImage and the flatpak. It
    is the only one of the three that carries the VST3: unpack it and run
    ./install.sh, which needs no root and writes under your home directory
    unless you ask it for --system.
  • The Linux tarball's install.sh is its uninstaller too, and takes --vst3,
    --no-vst3, --system and --uninstall for use without a prompt.

⚡ Changed

  • The remote display is reached from the status bar in one press, from
    either end.
    REMOTE and the panel behind it are gone. In their place the
    bar carries a PUBLISH switch, a button beside it showing the pairing
    code, and ATTACH, which opens Show another machine directly. Publishing
    no longer takes three presses and a question about which end of the link this
    machine is — a question anybody pressing the button had already answered.
  • The remote display's name, port, update rate and pairing code are now in
    Settings under Publish, with the rest of what the application remembers,
    instead of in a modal of their own. The section also states whether it is
    publishing and how many displays are attached, which the switch has no room
    to print.
  • The name and port commit when the edit ends — on Enter or on leaving the
    field — rather than from an Apply button. Nothing else in the settings panel
    has one.
  • The pairing code's button is disabled, rather than absent, while publishing
    is off. A code nothing is listening at is a display that scans, connects and
    times out, which reads as a broken feature rather than as a switch that is
    not on.
  • The pairing-code mark is redrawn on Material's qr_code geometry: three
    finders and a scatter of data cells. The previous mark was five filled cells
    in a 3x3 grid, which reads as a dice face.
  • A module's title bar and its corner resize grip now accept a finger from a
    larger area than they draw: 40 px down from the top edge instead of the
    24 px bar, and a 32 px corner square instead of a 16 px one. Both were well
    under the 44 pt and 48 dp the platforms ask for, which made a module fiddly
    to move and harder still to resize on a tablet. Nothing on screen changed
    size, and neither did anything for a mouse, a trackpad or a stylus-free
    pointer — the larger targets are admitted to touch and stylus only.
  • A tap on a module's resize grip selects the module. It previously did
    nothing: the grip is opaque, so it took the tap from the module underneath
    it and had nothing of its own to do with it.
  • A typed address that is not an address now says so, instead of the Connect
    button appearing to do nothing. A mistyped port — 192.168.1.20:70000 — was
    previously read as a host name with a colon in it and dialled, which failed
    several seconds later as a name lookup, and an unbracketed IPv6 literal was
    split at its last colon into a host and a port that could never connect.
  • The macOS download is an installer package rather than a disk image, and the
    Windows download is an installer executable rather than an msix. Neither
    original format can install a plug-in: a disk image has no install step at
    all, and an msix's virtualised filesystem cannot write the shared VST3
    directory.
  • The Windows installer is not yet signed, so Windows shows "Windows protected
    your PC" and the user clicks More info → Run anyway. The msix it replaces was
    refused outright when unsigned, so this is a state a user can get past rather
    than one they cannot.

🐛 Fixed

  • Publishing to a tablet no longer stops following the desk when the window
    is narrowed.
    The status bar drops whole items rather than squeezing them,
    and everything that fed the display host ran inside the item it dropped — so
    past that width the socket went on streaming measurements while layout, skin
    and delivery-target changes stopped arriving, and a changed name, port or
    rate was never adopted. Nothing said so, and the tablet looked healthy
    throughout.
  • The status bar no longer overflows its own row while publishing at narrow
    window widths. The remote button's label grew from REMOTE to REMOTE · ON
    when it was switched on — 27 px the width gate below it had never been
    measured against, because the sweep that proves the bar fits never published.
    The switch that replaced it is the same width in both states.
  • A warning that no display will find this machine no longer flashes on screen
    for a second every time publishing is switched on. The first announcement of
    a session is often refused before the multicast join settles and succeeds on
    the next one a second later; the notice now waits for the responder's opening
    burst to finish before it says anything, and clears immediately.
  • Publishing that could not start — the usual cause is a second copy of Open
    Audio Analyzer already running — now says so on screen. The switch flicked on
    and back off under the pointer with the reason recorded nowhere anybody was
    looking.
  • A desktop that cannot announce itself on the network now says so, on the
    Remote row and in the panel behind it, instead of reading Publishing while
    no tablet ever lists it. The advertisement had no error reporting at all: its
    bind error, its send error and its socket's error stream were all discarded,
    and the last of those is the one a refused local-network permission arrives
    on. Nothing about the machine looked wrong either, because the permission
    blocks the announcement and not the port — a display given the address by hand
    connected and worked perfectly throughout.
  • macOS users upgrading from 0.5.0 or earlier have to allow local network
    access again.
    0.6.0 changed the bundle identifier from
    dev.openaudioanalyzer.oaa to com.openaudioanalyzer.oaa, and macOS keys the
    permission to the identifier — so the entry granted to the old application no
    longer applies to this one and tablets stop finding the desk. Allow Open Audio
    Analyzer under System Settings → Privacy & Security → Local Network. Presets,
    skins and paired hosts are unaffected; they are keyed by name, not by
    identifier.
  • A panel now moves clear of a tablet's software keyboard. Every panel stayed
    centred on the whole screen while the keyboard covered the bottom third of it,
    so the address field in Show another machine — the last row above the footer —
    was behind the keyboard together with the caret and everything typed into it.
    Panels make room for the keyboard now, and the field being typed into is
    scrolled in front of whoever is typing.
  • The DAW's playhead no longer floats loose in the middle of the status bar. Its
    box reserves the width of a timecode, so a host that counts bars and beats
    instead — 1|1.0 — filled a third of it and left the rest as a hole on the
    right, while on the left the sample rate and channel count printed flush
    against the reading at every window between about 1160 px and 1310 px. The
    playhead now sits one gap from the elapsed clock it is read beside, and a
    group's width away from the format readout at every window size.
  • A tablet's page tabs now sit beside the name of the machine they belong to.
    The playhead was in front of them, and it reserves room for a timecode, a
    tempo and a time signature whether or not the host at the other end keeps all
    three — so on a host counting bars the tabs stood 88 px clear of the reading
    with nothing between the two, and on one reporting a clock and no tempo 190 px,
    reading as a control floating in the middle of the bar. The tabs come first
    now, and nothing that appears, vanishes or reserves unused room can move them.
  • The Linux VST3 now loads on the same distributions as the Linux application.
    It was built against a newer glibc than everything shipped beside it, so on an
    older distribution it was simply absent from the DAW's plug-in browser with
    nothing logged — indistinguishable from having installed it in the wrong
    place. Aff...
Read more

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 22 Aug 05:14

✨ Added

  • macOS releases can be notarised, which is what lets a downloaded plugin or dmg
    be opened with no further steps. A Developer ID signature now also carries the
    hardened runtime and a secure timestamp, both of which Apple requires before it
    will notarise anything and neither of which was being requested.
  • Tagging a release now builds the iPadOS display and uploads it to TestFlight,
    so a tablet no longer has to be built from source to be updated. The upload
    runs after the release is published rather than before it, which means a
    TestFlight build always corresponds to a release that exists. The IPA itself
    is deliberately not attached to the release: an App Store build provisions no
    devices, so a downloaded copy could not be installed by anyone.
  • The iPadOS build declares that it uses no encryption. Without that declaration
    every TestFlight build waits in "Missing Compliance" until somebody answers
    the export question by hand, which is the one step an automatic upload cannot
    take.

⚡ Changed

  • The application identifier is now com.openaudioanalyzer.oaa, and the
    plugin's is com.openaudioanalyzer.oaa.plugin. Both were under dev., which
    reversed a domain nobody held; these reverse open-audio-analyzer.com. The
    hyphens do not survive the trip, and cannot: an Android applicationId and a
    Kotlin package are Java identifiers and reject -, while Apple's
    CFBundleIdentifier accepts only letters, digits, - and . and so rejects
    the _ that Android would want in its place. Stripping them is the one form
    that is legal on all six platforms. The Linux application id, the AppStream
    and flatpak ids, the msix identity and the hicolor icon filenames all move
    with it.

🐛 Fixed

  • The macOS plugin bundles are built for Apple silicon and Intel, and load on
    macOS 11 and later. Every release up to 0.5.0 shipped a bundle built for
    whichever machine the release ran on — Apple silicon only, and requiring that
    machine's own macOS version or newer — which a DAW reports in exactly the way
    it reports a plugin that was never installed.
  • The instructions for a downloaded macOS plugin now describe what macOS 15 and
    later actually do when the quarantine flag is still on it: a modal saying the
    plugin cannot be verified free of malware, or that it will damage your
    computer, with nothing in System Settings to override it — the "Open
    Anyway" button there is only offered for a blocked launch, and loading a plugin
    into a DAW is a library load. The fix has not changed and is still
    xattr -dr com.apple.quarantine; what was wrong was the description of the
    symptom, which called the failure silent and sent people looking for a
    different problem.
  • The README no longer claims the macOS build is distributed "signed with a
    Developer ID and notarised". It has never been either.

🚧 Internal

  • CI imports a signing certificate before anything signs. OAA_SIGNING_IDENTITY
    was being handed to codesign on runners whose keychain was empty, and
    OAA_NOTARY_PROFILE named a credential that only exists on a developer's own
    machine, so neither secret could have worked on a runner — and neither failed a
    job, because they had never been set and the scripts took their no-credential
    branches instead.
  • packaging/ios/make_ipa.sh and packaging/ios/testflight.sh, and the ipa
    and testflight jobs in ci.yml. Manual signing is injected through
    ios/Flutter/Release.xcconfig so the Xcode project stays on automatic signing
    for local development; the script reads the signing authority back off the
    archive, because flutter build ipa exits 0 on an export that silently fell
    back to automatic signing.

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 22 Aug 01:40

✨ Added

  • Double-clicking the status bar on macOS zooms the window again, as
    double-clicking a title bar does everywhere else on the Mac — the status bar
    is this window's title bar, and it had answered nothing since 0.3.0. It obeys
    the system's "double-click a window's title bar to" setting, so a Mac set to
    minimise minimises and one set to do nothing does nothing, and it waits the
    double-click interval that Mac was configured with. No control in the row
    answers any later for it: what Flutter recognises there is still a single
    click, and the pair is counted in the runner.

⚡ Changed

  • The iOS and Android home screen label is OAA, the wordmark the status bar
    already draws. It was Open Audio Analyzer, which no tablet ever actually
    showed: iOS fits an icon label to the width of one icon by tightening the
    tracking before it truncates, and tracking is spent on the spaces between
    words first — a 19-character name arrived on the home screen as
    OpenAudioAnal…, run together and cut short anyway. Apple's guidance is
    twelve characters. The product's name is unchanged everywhere it fits: the
    macOS, Windows and Linux applications, both permission prompts, and every
    configuration directory — nothing a tablet has saved moves.

🐛 Fixed

  • The canvas no longer gets slower the longer a spectrogram is on screen. The
    spectrogram redrew its whole history as run-length marks on every published
    frame, and its cost was budgeted against smooth columns — real material
    jitters a brightness step between most adjacent rows, so a large display was
    re-recording and re-rasterising 150,000–230,000 marks about 47 times a
    second, a cost that ramped for the half-minute the history took to fill after
    a mount and then stayed. Every meter repaints from the same clock, so it
    dragged the whole canvas — most visibly the analyser — and the remote display
    paid the same price on weaker hardware, more of it at the 60 fps link rate.
    The history is now kept as pixels and drawn as one image, a quarter of a
    millisecond per published frame whatever the signal does; the numbers are in
    tool/bench_spectrogram.dart.
  • On a remote display, the tab control now sits beside the name of the machine
    being watched instead of stranded in the middle of the link bar. The bar kept
    room for the host's playhead whether or not the host had one, so on every host
    with no DAW behind it — a desktop metering a device or a file, which is most
    of them — 248 px of nothing stood between the name and the tabs. The slot
    appears with the playhead and does not move again while the link lasts, so a
    reading that goes stale does not shift the tabs out from under your finger.

🚧 Internal

  • tool/bench_spectrogram.dart is formatted the way the test job's
    dart format --set-exit-if-changed step demands. It was not, so that job
    failed on every push after the benchmark landed while the analyzer, the
    suites and the benchmark itself all stayed green. That step is now listed
    with the other gates in README.md and CLAUDE.md, which is why it was
    never run by hand.

v0.4.1

Choose a tag to compare

@github-actions github-actions released this 21 Aug 23:51

🐛 Fixed

  • The macOS plugin bundles now carry a valid code signature. All three — the
    VST3, the Audio Unit and the Standalone — shipped with an invalid one in every
    release up to 0.4.0: the VST3's resource seal was computed before JUCE wrote
    moduleinfo.json into the bundle, and the other two were never bundle-signed
    at all. On Apple Silicon that is enough for a DAW to leave the plugin out of
    its browser without logging anything, and for auval to refuse the Audio
    Unit. Each bundle is now signed after everything that writes into it and
    verified on the spot, so the build fails rather than producing a bundle it
    cannot verify. auval -v aufx OaaM OaaA passes. If the plugin never
    appeared in your DAW, this is why
    — and on macOS also strip
    com.apple.quarantine from a copy you downloaded, which no build can do for
    you.

✨ Added

  • The documentation site's Install
    page now has an In a DAW section: which folder the VST3 and the Audio Unit
    have to be copied into on each platform, the xattr line that a downloaded
    copy needs on macOS, and the Ableton Live preference that has to be on before
    Live looks in the folder at all. The page had linked to that section since the
    site was first published, and the section did not exist.

🚧 Internal

  • OAA_CODESIGN_IDENTITY signs the macOS plugin bundles with a Developer ID
    instead of ad-hoc. Releases stay ad-hoc.
  • Signing runs from a target that depends on the format target rather than from
    POST_BUILD, which is not last: a MACOSX_PACKAGE_LOCATION resource is
    copied by a sibling rule that make may run after the link, and on a
    from-scratch build it does. Only visible with the bundle deleted first.

v0.4.0

Choose a tag to compare

@github-actions github-actions released this 21 Aug 21:13

✨ Added

  • An Android tablet now finds hosts on the network by itself, like every other
    platform. It held a multicast socket that never received an answer, because
    Android's Wi-Fi driver discards multicast for an app that is not holding a
    WifiManager.MulticastLock — silently, with the search still saying it was
    looking. The lock is held while a search is running and given back when it
    stops, so it costs nothing once a display is attached.
  • An Android tablet now remembers its layout, its skin and the host it was last
    attached to. Nothing in an Android process names a directory it may write to,
    so the configuration directory is asked for over a platform channel and lives
    in the app's own files directory; every launch before this one started from
    the defaults.
  • Metering your Mac's own output no longer needs a loopback driver. On macOS
    14.2 and later, System Output is the first entry in the source menu, named
    after the output device it is metering. It is a Core Audio process tap, so
    there is nothing to install, nothing to reroute and no password prompt — the
    audio still reaches your speakers while it is being measured. macOS may ask
    for permission to record system audio the first time. Below 14.2 the entry is
    absent and BlackHole or Loopback is still the answer; Windows and Linux are
    unaffected, since WASAPI loopback and a PipeWire monitor source already appear
    in the list.

⚡ Changed

  • The wire protocol is at version 3, and a receiver now accepts any version it
    knows rather than only its own. A plugin built against 0.3.0 keeps working
    with a newer app, which under the old equality check it would not have: a
    plugin lives in the DAW's plugin folder and stays there across app upgrades,
    so the mismatch was the ordinary case, and what it looked like from the plugin
    was a port that accepts and hangs up forever — indistinguishable from the
    defect where the port was never bound at all. The rule is one-way on purpose:
    a peer newer than this build is still refused, because a later version may
    have moved a table and misreading a measurement table is how a meter draws a
    confident wrong number. A tablet still running 0.3.0 or earlier will refuse
    a newer desktop
    and say so, rather than drawing anything; update both ends.
    Version 3 adds a frame type and moves no byte of any existing table — held by
    a test that decodes the frozen version-2 golden and diffs it against the
    version-3 one, where exactly four bytes differ and all four are version
    fields.
  • A host search that is running but cannot receive says so instead of
    "Looking for hosts on this network…", which is the face a search that is about
    to succeed wears.

🐛 Fixed

  • The plugin's status panel no longer claims a playhead from a host that is not
    giving one. The line was drawn from whether a transport had ever been
    published, and the plugin publishes one for every audio block — the empty one
    that means "this host said nothing" included — so it read as a playhead the
    moment audio started flowing, on precisely the host it exists to warn about.
    It now follows what the host is reporting now, and says "no playhead from
    host" again if a host stops.

🚧 Internal

  • Groundwork for the Elapsed and Timecode LUFS modes, which are not yet
    offered by any module
    — this is the protocol and the engine underneath them,
    and the modules and their menu are the change after this one. docs/WIRE.md
    gains 0x0020 SET_LUFS_MODE, the first frame that travels from consumer to
    producer, permitted on the ingest port only because that one binds loopback
    where whatever connects is already running as this user; the display port
    binds every interface and stays read-only until somebody designs
    authentication for it. Three implementations moved together, as that file
    requires.
  • The engine can reset itself when the signal returns after a silence
    (oaa_engine_set_silence_reset, ABI 5), which is what the System mode is made
    of. It lives in engine/ rather than above it because silence is a property
    of audio and not of a host — one implementation serves a plugin and a sound
    card, where two would eventually disagree about when a track began. The gate
    runs before the block it judges, so a track whose loudest sample is in its
    first block keeps that peak rather than having it cleared by its own reset.
    Off by default, and off for file analysis, which must measure a file whole.
    The two transport-driven modes need no engine API at all: they are the
    producer declining to push, so engine/ still does not learn what a DAW is.
  • The plugin's answer to a host that supplies no transport is now held by a
    test. plugin/test/transport_capture_test.cpp hosts the AudioProcessor
    directly, which is the only way to reach either of the two branches behind it:
    no VST3 or Audio Unit host can express "no playhead" or "no position", so
    neither a DAW nor the fake DAW can ask for them. It runs in the gated plugin
    job's ctest, and both it and the transport box's own test were verified by
    breaking the code under them and watching them fail.
  • Five documents caught up with protocol version 3's two goldens. docs/WIRE.md
    still gave the SNAPSHOT payload size "at protocol version 2" in the one
    document whose header declares version 3; packages/oaa_wire/AGENTS.md named
    wire_v2.bin as the golden its codec test decodes, when the test reads both
    and wire_v3.bin is the one tracking the current serialiser; and two comments
    in ci.yml credited the C++ producing side with writing wire_v2.bin, which
    it no longer does. The one that could have cost something: the regeneration
    command in plugin/test/wire_fixture.cpp still wrote to wire_v2.bin — the
    frozen file whose whole purpose is to hold bytes produced before version 3
    promised to move no table. Following it would have destroyed the evidence and
    left every test green.
  • Two claims about that branch are corrected here rather than in the 0.3.0
    notes, which are released. It is not reached by the Standalone build —
    JUCE 8's AudioProcessorPlayer installs a counting playhead whenever the
    processor it is given has none — and it is unreachable through an Audio Unit
    as well, not only through VST3. The plugin's own handling was correct
    throughout; only the note about what exercised it was wrong. README.md no
    longer lists it under Known gaps, because it now has a test instead of a
    paragraph.