Skip to content

Source and tests: the engine in plain C++, Tuning, the suite's host test - #7

Merged
MaymiPR merged 5 commits into
mainfrom
chore/standard-deviations
Nov 11, 2026
Merged

MaymiPR merged 5 commits into
mainfrom
chore/standard-deviations

Conversation

@MaymiPR

@MaymiPR MaymiPR commented Nov 11, 2026 •

Copy link
Copy Markdown
Owner

What and why

Removes Chan Sampler's remaining structural differences from the suite standard (STANDARDS.md, "Tree" and "Naming";
the engine in plain C++).

Change Detail
Source/dsp/ plain C++ without JUCE, namespace cs::dsp: the engine renders into channel pointers from a list of MIDI events (dsp::MidiEvent), the samples use the DSP's own Buffer, Detect tempo has its own FFT with JUCE's order of operations, the stretcher's FFT its own four-lane vector (SSE2, NEON or plain C++); the comparison and rounding helpers keep JUCE's operation order
One file per block Dsp.h/.cpp became Numeric.h, Modes.h, KnobLaws.h/.cpp, Envelope.h, Lfo.h, Filter.h/.cpp; new Buffer.h, Fft.h/.cpp
JUCE side Source/SampleFile.h: the loaded file (RawSample over dsp::SampleSource), JUCE views of the DSP's buffers (a file decodes straight into them), the tempo text; the processor turns its MIDI into engine events
Params.h Params.cpp folded in; every parameter ID an inline constexpr const char* in cs::id (the 82 envelope and LFO IDs spelled out), allIds (161, checked against the layout by ChanSamplerTests), presetIds, createLayout
dsp/Tuning.h every measured, fitted and design constant of the DSP (envelopes, LFOs, knob laws, filters, voices, echo, declick curves, trim model, precomputed effects, transients, time stretching, Detect tempo), each group naming its MEASUREMENTS.md section; forEach () lists them by name, so CsRender's tune:key=value and tuning=<file> reach every one (an array entry by name and index)
Host test tools/HostTest.cpp is the suite's generic host test with two generic additions: --property name=value (a root property of the plug-in's own state in every instance: Chan Sampler's test sine as its sample) and JUCE's MIDI CC parameters left out of the save and reload checks like the program list. The sampler's own host checks moved to tests/ChanSamplerPlayTests.cpp (ctest)
Fixture tests/data/state-1.2.0.txt: the two readings that changed on purpose since 1.2.0 (OUT's conversion from a dB trim, FL's time percent) hold today's texts; the .bin is unchanged
Shared namespace chan (the suite name's first word, as the standard names it), was chansampler

How it was checked

  • Byte-identical renders on a clean build against main's: the 21 render-regression outputs (sha256 of each
    .f32) and 1126 further renders through CsRender (sha256 each): the 592 null-test cases of every
    nulltest/cases_*.py with their signals in the single-render form, 173 jobs at each of 44.1, 48 and 96 kHz (every
    stretch mode on two samples, two stretch factors, pitch, loops and a long loop; every filter type static and
    modulated; every declicking mode; every LFO shape on every target; every arpeggio direction, chords and slide;
    echo ping-pong and fat mode; each precomputed effect alone and all together, reverb A and B, crossfades, reversed and
    shortest trims; envelopes, tracking, levels, pitch bend range, polyphony, slice map), Detect tempo and loadcheck
    output, and stretchtest in every mode: 0 differ.

  • tune: reaches the constants: an unknown key is refused, tune:boostGain=8 changes a render, the defaults give
    the same bytes.

  • Frozen identity against main's build: VST3 class IDs ABCDEF019182FAEB4368736D43736D31 and
    ABCDEF011234ABCD4368736D43736D31, names, vendor Chan Sampler, categories and factory info identical
    (moduleinfo.json); the 161 parameter IDs in a saved state identical and in the same order, state tag unchanged;
    CMakeLists.txt, packaging/, .github/, cmake/ and the identity lines of plugin.cmake (codes Chsm /
    Csm1, bundle ID com.ChanSampler.ChanSampler, CLAP ID com.chansampler.chansampler) untouched.

  • scripts\check.ps1 -KeepFl on a fresh build folder:
    CHECK | 63812a6 | repo ok | lint skipped | build ok | warnings 0 | vst3 ok | ctest ok | regress ok (5 of 5
    ctest; the 1.2.0 project loads with its 135 parameters reading as its fixture records them).

  • CI on three systems green (the last commit renames a constructor argument that GCC and Clang reported as shadowing; it changes no code generated).

  • FocusCheck on the built VST3: PASS (the space bar reaches the host after clicks at four points).

  • scripts/check_repo.py: 0 findings; the suite consistency check over the tree and the history: 0 FAIL.

  • ctest passes and the render regression is green (CI runs both)

  • A user-facing change has a line in CHANGELOG.md under ## Unreleased

  • A sound change has its measurement in the plug-in's MEASUREMENTS.md and its numbers in NULLTESTS.md (no sound change: the renders are byte-identical)

🤖 Generated with Claude Code

MaymiPR and others added 5 commits November 10, 2026 23:04
Source/dsp/ includes no JUCE header and lives in cs::dsp: the engine
renders into channel pointers from a list of MIDI events, the samples
use the DSP's own Buffer, Detect tempo has its own FFT with JUCE's
order of operations, the stretcher's FFT its own four-lane vector, and
the knob laws, the enums and the comparison helpers moved into
dsp/Dsp.h with JUCE's operation order. The loaded file (RawSample),
JUCE views of the DSP's buffers and the tempo text sit in
Source/SampleFile.h. Params.h holds every parameter id as an inline
constexpr const char* in cs::id, allIds, presetIds and createLayout.
The shared code's namespace is chan, the suite name's first word.
Every render-regression case and 1126 null-test, stretch and command
renders through CsRender are byte-identical to main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Tuning struct now holds the constants of the envelopes, LFOs,
knob laws, filters, voices, echo, declick curves, trim model,
precomputed effects, transients, time stretching and Detect tempo,
each group naming its MEASUREMENTS.md section. forEach () lists them
by name, so CsRender's tune:key=value and tuning=<file> reach every
one (an array entry by its name and index). FL's knob encodings, its
tick grid, the whole-number terms of a law and the large measured
tables stay in the code. The renders are byte-identical to main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tools/HostTest.cpp is the starter's host test with two generic
additions: --property name=value sets a root property of the plug-in's
own state in every instance it loads (Chan Sampler's test sine as its
sample), and JUCE's MIDI CC parameters are left out of the save and
reload checks as the program list is. The sampler's own host checks
(automation, MIDI, the sustain pedal, the plug-in-side state, the
editor size, pitch across rates, offline renders after a change, a
stretch mode chosen while playing, a missing sample) run as
ChanSamplerPlayTests. The 1.2.0 fixture's .txt holds the two readings
that changed on purpose since (OUT's conversion, FL's time percent).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dsp/Dsp.h and Dsp.cpp held several blocks under one name; they are
Numeric.h (the comparisons, rounding and constants), Modes.h (the
engine's modes), KnobLaws.h/.cpp (FL's knob laws and song tick),
Envelope.h, Lfo.h and Filter.h/.cpp, each included where it is used.
The changelog and the contributing guide describe the new layout and
tests. The renders are byte-identical to main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GCC and Clang report the constructor's channels argument as shadowing
the member of the same name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaymiPR
MaymiPR merged commit 0190269 into main Nov 11, 2026
4 checks passed
@MaymiPR
MaymiPR deleted the chore/standard-deviations branch November 11, 2026 13:57
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.

1 participant