Skip to content

Edit: Fixed toBitSet() ignoring its argument and returning every track in the Edit - #403

Merged
drowaudio merged 1 commit into
developfrom
bugfix/399-tobitset
Sep 2, 2026
Merged

Edit: Fixed toBitSet() ignoring its argument and returning every track in the Edit#403
drowaudio merged 1 commit into
developfrom
bugfix/399-tobitset

Conversation

@drowaudio

Copy link
Copy Markdown
Contributor

Fixes #399

Problem

toBitSet (const juce::Array<Track*>&) (modules/tracktion_engine/model/edit/tracktion_EditUtilities.cpp:250) used its argument only to reach the Edit, then looped over getAllTracks() instead of tracks:

for (auto t : allTracks)          // <-- should be `tracks`
    if (int index = allTracks.indexOf (t); index >= 0)
        bitset.setBit (index);

The result therefore never depended on what was asked for - every track in the Edit got a bit. The mask is live: Renderer::Parameters::tracksToDo becomes CreateNodeParams::allowedTracks (Renderer.cpp:38), so a caller asking for a subset silently rendered or measured the whole Edit.

It stayed hidden in-engine because Renderer::renderToFile() passes getAllTracks (edit) (for which "every track" is the right answer), and the one in-engine call passing a subset (tracktion_NodeRendering.test.cpp:203) is on an Edit with a single audio track. The engine's own tests had already worked around it: tracktion_EditNodeBuilder.test.cpp and tracktion_Plugins.test.cpp each carried a private getTracksMask() built from Track::getIndexInEditTrackList() rather than calling the shared helper.

Plan

  1. Fix the loop - iterate tracks rather than allTracks in toBitSet(). allTracks.indexOf() still supplies the index, so the bit numbering is unchanged and tracks from another Edit are skipped.
  2. Tighten the doc comment on tracktion_EditUtilities.h to state what the bits mean, where the Edit comes from, and that foreign tracks are ignored - the vague wording is part of why the bug survived.
  3. Add tracktion_EditUtilities.test.cpp (new ENGINE_UNIT_TESTS_EDIT_UTILITIES flag in tracktion_TestConfig.h, included from tracktion_engine_model_1.cpp) covering: a single track, an arbitrary subset, all tracks, an empty array, tracks belonging to another Edit, agreement between the bit index and Track::getIndexInEditTrackList(), and a toTrackArray() round-trip.
  4. Delete the two getTracksMask() copies in tracktion_EditNodeBuilder.test.cpp and tracktion_Plugins.test.cpp and call toBitSet() instead - those helpers exist only to route around this bug, and keeping them would leave the fix untested by the suites that actually render subsets.
  5. Record the behaviour change in BREAKING-CHANGES.md: host code that passed a subset now gets a subset, which changes what renders.

Verification

  • The new test fails against the old loop (15 failing assertions) and passes with the fix, so it is not vacuous.
  • TestRunner Debug builds clean, and the suites touching the changed helpers pass: tracktion_EditUtilities.test.cpp, tracktion_EditNodeBuilder.test.cpp, tracktion_Plugins.test.cpp and tracktion_NodeRendering.test.cpp - 12 test cases, 543 assertions, 0 failures.
  • Nothing else in-engine feeds toBitSet() into a bitset: TransportControl.cpp:969, AudioTrack.cpp:1094 and RenderOptions::getTrackIndexes() all build their masks directly, and Renderer::renderToFile() passes every track, so its result is unchanged.

Note on behaviour

test_utilities::expectPeak() in tracktion_TestUtilities.h has no in-engine callers but is part of the public test utilities - host tests using it against a subset of tracks will now measure that subset, which is the documented intent but may shift existing expected values.

…k in the Edit

toBitSet() used its argument only to reach the Edit and then looped over
getAllTracks(), so the returned bitset never depended on what was asked
for. Callers passing a subset - Renderer::Parameters::tracksToDo and
Renderer::measureStatistics() via test_utilities::expectPeak - silently
addressed the whole Edit.

Iterating `tracks` instead makes the result match the documented
behaviour, so the private getTracksMask() copies in
tracktion_EditNodeBuilder.test.cpp and tracktion_Plugins.test.cpp can go
back to calling the shared helper.

Added tracktion_EditUtilities.test.cpp covering subsets, the empty array,
tracks from another Edit, agreement with Track::getIndexInEditTrackList()
and the toTrackArray() round-trip.

Fixes #399
@drowaudio drowaudio linked an issue Sep 1, 2026 that may be closed by this pull request
1 task
@drowaudio
drowaudio merged commit 0e02f70 into develop Sep 2, 2026
39 checks passed
@drowaudio
drowaudio deleted the bugfix/399-tobitset branch September 2, 2026 09:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: toBitSet() ignores its argument and returns a bitset of every track

1 participant