Skip to content

FeedbackDelay and MultiTapDelay: lifecycle gaps found by reading the nodes against their tests #177

Description

@bdbarnett

A state-by-event read of audioecho.FeedbackDelay and audiodelays.MultiTapDelay at v0.6.3rc3, against every test that exercises them. Items marked measured were run on the CPython twin. The rest come from reading the code and are not reproduced. Nothing was run on a native build.

Could hang

  • MultiTapDelay: a source that reports more data and hands back 0 bytes spins the pull loop with no exit (MultiTapDelay.c:345-364; the twin's _Effect does the same, audiofilters.py:76-101). No test.

Audio lost or repeated

  • FeedbackDelay: reset_buffer drops the source frames the node holds. With 512-frame source buffers, 256 frames are lost (measured: the frame before the reset was 255, the first after was 512); a RawSample restarts from its top (FeedbackDelay.c:254-255). clear() keeps them.
  • FeedbackDelay: a source that runs dry part-way through a block hands a SHORT block downstream (measured: 256, 44, 256 frames). The comment at FeedbackDelay.c:235 says silence rather than a short block, which holds only when nothing was produced.
  • FeedbackDelay ignores GET_BUFFER_DONE, so a source that is done but still hands data is replayed for ever (measured: a 300-frame RawSample came out non-zero in 4 of 4 blocks). The node's own RawSample test fixtures depend on this.

A control taken to its stop leaves state behind

  • FeedbackDelay wow_hz to 0 freezes the oscillator mid-swing: the read head stays displaced (measured: a 20 ms echo at frame 148, not 160).
  • FeedbackDelay loop_semitones off and on resumes from a stale phase, with a half-window step.
  • Not tested at all: feedback 0 and back, delay_slew 0 mid-glide, Mix back from 0, two or three set() calls before one pull.

The C node and the CPython twin disagree

  • MultiTapDelay delay_ms: C zeroes the tail past the new length on every write (MultiTapDelay.c:134); the twin does not (audiodelays.py:188-195). Shorten then lengthen reads stale audio on CPython and silence on the boards.
  • MultiTapDelay after deinit(): C still reports its source from sources(); the twin clears it.
  • MultiTapDelay with a stereo source that hands an odd number of samples swaps the lanes (audiodsp_multitap.c:17).

Unlocked writes

The pattern

MultiTapDelay has no node-level lifecycle test at all: everything is three-interpreter identity against a golden, which pins what the node does and asserts nothing about whether it is right. FeedbackDelay is tested where a class audit found a defect and nowhere else.

Wanted: one fixed matrix of lifecycle events, run against every node, that asserts properties (no frame lost, no frame repeated, silence in gives silence out, a control back from its stop plays what a fresh node plays).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions