Conversation
…r v1.2 APIs - types.h: add AcousticResult, DownbeatResult, MeterResult, KeyCandidateResult, ChordHmmResult, and LoudnessResult structs; tighten optional<float> usage for blind-mode c50/c80 (null vs NaN) - exception.h: add AnalysisException subclass for analysis-layer errors - sonare.h: expose all new analysis module headers - quick.h/cpp: add quick_detect_acoustic, quick_detect_downbeats, quick_detect_meter, quick_get_key_candidates convenience wrappers
…ation - Blind estimation mode derives room acoustics from music signals using energy-decay curve fitting and statistical modeling - Impulse-response mode processes measured IR for precise RT60 per octave band (125 Hz through 8 kHz), EDT, and clarity metrics - C50/C80 exposed as null (not NaN) in blind mode where undefined - AcousticResult carries per-band octave results alongside broadband summary
…fier - downbeat_analyzer: Viterbi decoding over beat-synchronous chroma and spectral flux to assign downbeat positions; outputs DownbeatResult with beat-level confidence scores - meter_analyzer: classifies 3/4, 4/4, and 6/8 compound meter via auto-correlation of onset strength at candidate beat subdivisions; candidate lookup is value-based (not enum-cast) to avoid silent mismatches - Both analyzers consume BeatResult from beat_analyzer as input
…ntext scoring - chord_hmm: Viterbi-based HMM over chroma-template posteriors; backtrack guard prevents out-of-bounds access on very short segments - chord_analyzer: integrates HMM smoother; adds detect-inversions flag (bass note tracking via chroma lowest-weighted bin) and key-context rescoring that boosts diatonic chords for the detected key - chord_templates: expand template set with suspended, augmented, diminished, and add9 voicings; normalize template vectors for cosine-distance matching
- nnls_chroma: non-negative least squares chroma from log-frequency spectrogram; more accurate than standard chroma for polyphonic music, enabled via --nnls flag - chroma: refactor to share filterbank logic with NNLS path; add tuning compensation pre-processing - rhythm: add compute_tempogram (Fourier), compute_cyclic_tempogram, and tempogram_ratio helpers used by the enhanced BPM/beat pipeline
- key_analyzer/key_profiles: add Krumhansl-Kessler, Temperley, Shaath, and EDMA profiles selectable at runtime; expose key candidates with correlation scores; add mode (major/minor) and genre-hint weighting - bpm_analyzer: integrate tempogram-based BPM refinement for librosa parity; add fractional BPM via parabolic interpolation - beat_analyzer: use tempogram for initial period estimate; add librosa-parity beat tracking with dynamic-programming cost function - music_analyzer: wire all new sub-analyzers; expose top-level detect_downbeats and detect_meter entry points - rhythm_analyzer: align onset-strength parameters with librosa defaults
…ain stages - lufs: implement integrated, momentary, and short-term loudness per EBU R128; correct overlap windows for momentary (400 ms/75%) and short-term (3 s/66%); add LRA (loudness range) and multichannel K-weighting support - presets: add streaming, youtube, broadcast, podcast, audiobook, cinema, jpop, ambient, lofi, and classical target presets - named_processor: add repair/dynamics chain stages (noise gate, transient shaper, de-esser) and progress callback support per stage
…ules - sonare_c.h/cpp: add sonare_detect_acoustic, sonare_analyze_impulse_response, sonare_detect_downbeats, sonare_detect_meter, sonare_get_key_candidates, sonare_measure_loudness, and sonare_free_* counterparts - sonare_c_internal: route new entry points through music_analyzer and acoustic_analyzer with proper lifetime management - sonare_c_memory: register all new result types in the memory-tracking table - sonare_c_compat: preserve deprecated symbol aliases for backward compatibility - wasm/bindings.cpp: expose all new C++ types and functions via embind; register optional<float> value_or binding for nullable fields
…yping - Node addon: add napi wrappers for detectAcoustic, analyzeImpulseResponse, detectDownbeats, detectMeter, getKeyCandidates, measureLoudness in sonare_wrap_analysis.cpp; update index.ts and types.ts - Python: add detect_acoustic, analyze_impulse_response, detect_downbeats, detect_meter, get_key_candidates, measure_loudness to analyzer.py and _ffi.py; generate PEP 561 .pyi stubs for all public modules (__init__, analyzer, audio, types) and add py.typed marker - WASM: extend public_types.ts, wasm_types.ts, sonare.js.d.ts, and index.ts with all new result types and entry points - tools/gen-typescript-types.ts: code-gen script that derives TypeScript interfaces from C++ type definitions to keep bindings in sync
- sonare_cli.cpp: add acoustic, downbeats, meter, key-candidates, loudness subcommands; add --use-hmm, --detect-inversions, --key-context, --nnls, --use-hpss, --hpss, --loudness-weighted flags - cli_support.cpp: fix boolean-flag registration bug where --use-hpss, --hpss, --loudness-weighted, --nnls, --use-hmm, --detect-inversions, and --key-context were consuming the next positional argument instead of acting as switches - cli.py: add Python CLI equivalents for all new subcommands and flags
…and fixture tooling - New C++ tests: acoustic_analyzer, downbeat_analyzer, meter_analyzer, nnls_chroma, chord_synthetic_matrix, key_synthetic_matrix, ebu_r128_compliance; tighten tolerances in bpm/beat/chord/key tests after review fixes - Librosa high-level parity: beat_tracking_test, bpm_parity_test exercise the tempogram-backed pipeline against librosa reference outputs - Fixture infrastructure: manifest TSVs (acoustic, ebu_r128, music_eval/*) plus Python tooling (audit_manifests, run_optional_fixture_report, evaluate_optional_fixture_targets, compare_optional_fixture_reports, json_safe) for optional dataset-based regression evaluation - Typing smoke tests: node_smoke.ts and python_smoke.py verify that generated type stubs compile/import without errors
…or v1.2 - CMakeLists (root/src/tests/node): register acoustic_analyzer, downbeat_analyzer, meter_analyzer, chord_hmm, nnls_chroma new source files; add test targets for all new test files; wire gen-typescript-types into build - .github/workflows/ci.yml: extend matrix with new test binaries; add EBU R128 compliance job; update coverage paths - .gitignore: exclude fixture result caches and Python __pycache__ artefacts - Makefile: add gen-types and fixture-eval convenience targets - README.md / README_ja.md: document all new analysis APIs, CLI flags, Python stubs, and mastering presets - bindings/*/README.md: update Node, Python, and WASM binding docs - pyproject.toml / requirements-dev.lock: bump version, add py.typed, update dev dependencies
…n C API and WASM embind - Add sonare_onset_strength, sonare_fourier_tempogram, sonare_tempogram_ratio, and sonare_nnls_chroma to sonare_c.h / sonare_c_features.cpp / sonare_c_compat.cpp - Add SonareLufsResult struct and sonare_lufs / sonare_momentary_lufs / sonare_short_term_lufs (no heap pointer in struct; no free required) - Add corresponding WASM embind functions in src/wasm/bindings.cpp: js_onset_envelope, js_fourier_tempogram, js_tempogram_ratio, js_nnls_chroma, js_lufs, js_momentary_lufs, js_short_term_lufs - Register all new functions in the EMSCRIPTEN_BINDINGS block
…FS in Node, Python, and WASM bindings - Node (N-API): add OnsetEnvelope, FourierTempogram, TempogramRatio, NnlsChroma, Lufs, MomentaryLufs, ShortTermLufs in sonare_wrap_features/analysis.cpp; register in sonare_wrap.cpp/.h; export typed wrappers and Audio methods in index.ts; add LufsResult interface in types.ts - Python: add SonareLufsResult ctypes struct and FFI signatures for all seven new functions in _ffi.py; implement onset_envelope, fourier_tempogram, tempogram_ratio, nnls_chroma, lufs, momentary_lufs, short_term_lufs in analyzer.py with .pyi stubs; expose LufsResult dataclass in types.py; re-export everything via __init__.py; add Audio convenience methods in audio.py/.pyi - WASM TypeScript: add typed wrappers for all new embind functions in index.ts; add LufsResult and chromagram object types in public_types.ts, wasm_types.ts, and sonare.js.d.ts
…pogram-ratio, and nnls-chroma subcommands - C++ CLI (tools/sonare_cli.cpp): add cmd_acoustic (blind and IR-based RT60/EDT/ C50/C80/D50), cmd_lufs (integrated + optional momentary/short-term series), cmd_onset_envelope, cmd_fourier_tempogram, cmd_tempogram_ratio, cmd_nnls_chroma; register all in get_commands() - Python CLI (cli.py): add matching subcommands for acoustic, rhythm, dynamics, timbre, lufs (--series flag), onset-envelope, nnls-chroma, tempogram, plp, mastering, mastering-processor, and mastering-pair-analyze; add _write_wav, _array_stats, and _parse_kv_params helpers
…nls_chroma, and LUFS - C++ (tests/api/sonare_c_test.cpp): add TEST_CASEs for sonare_onset_strength, sonare_fourier_tempogram (shape: n_bins x n_frames), sonare_tempogram_ratio (default 5 factors + explicit factors), sonare_nnls_chroma, sonare_lufs, sonare_momentary_lufs, sonare_short_term_lufs; include null/invalid-param rejection checks for each - C++ (tests/librosa/tempogram_test.cpp): fix clang-format line-length in existing double-cast expression - Node (bindings/node/tests/basic.test.ts): add test suite covering onsetEnvelope, fourierTempogram, tempogramRatio, nnlsChroma, lufs, momentaryLufs, shortTermLufs, and Audio method equivalents - Python (bindings/python/tests/test_analyzer.py): add test_onset_envelope, test_fourier_tempogram, test_tempogram_ratio (default and explicit factors), test_nnls_chroma (non-negative NNLS output), test_lufs (louder > quieter), test_momentary_and_short_term_lufs - WASM (bindings/wasm/tests/new-apis.test.ts): new file covering onset, Fourier tempogram, tempogram ratio, PLP, NNLS chroma, and full LUFS metering suite
…S in README - Update feature bullet and capability table to include downbeat tracking, time signature, HMM/inversion chord detection, NNLS chroma, Fourier tempogram / PLP, and EBU R128 LUFS - Add TypeScript code examples for rhythm/chord extras and the onsetEnvelope -> tempogram -> tempogramRatio -> nnlsChroma -> lufs pipeline - Add Python examples for the same APIs via Audio methods and module functions - Expand Python CLI reference with acoustic, lufs --series, rhythm, dynamics, timbre, tempogram, nnls-chroma, and updated mastering examples - Mirror all additions in README_ja.md with Japanese prose
- Implement frequency-domain pseudo-inverse using the cached CQT kernel - Add librosa reference test with icqt.json for output validation - Extend generate_librosa_reference.py to produce icqt fixtures
- Implement pYIN (Mauch & Dixon) fundamental-frequency estimation - Add HMM/Viterbi decoding for voiced/unvoiced state transitions - Match librosa.pyin API and output behavior - Add unit tests and pyin.json reference fixtures for parity validation
Validates predominant-local-pulse output against the existing plp.json reference fixture, increasing coverage of the tempogram family.
…on units - Move JSON serialization into chain_json.cpp - Move flat-params bridge into chain_params.cpp - Move StreamingMasteringChain into chain_streaming.cpp - Move processor-name registry into named_processor_registry.cpp - Update src/CMakeLists.txt to list the new translation units Pure code move with no logic change; chain.h and chain.cpp retain only the core MasteringChain class.
- Add DrumAndBass, Techno, Metal, Trap, RnB, Jazz, KPop, Trance, and GameOst presets to presets.h/presets.cpp - Expose new preset names in Node, Python, and WASM type definitions - Add preset_test.cpp coverage for all nine new presets
- Add audio_profile.h/cpp for loudness, dynamic range, and spectral profiling of an input signal - Add suggester.h/cpp for genre inference and chain recommendation based on the audio profile - Wire assistant into the CLI via a --assistant flag in sonare_cli.cpp - Register assistant translation units in src/CMakeLists.txt - Add assistant_test.cpp and cli_test.cpp coverage
…ic drive - Design real RBJ/Vicanek biquads in linear_phase.cpp and evaluate the true magnitude response via a new biquad_magnitude() helper instead of prior ad-hoc approximations - Add harmonic_drive blend control to TubeSaturator (default 1.0 preserves existing behavior) - Extend eq_test.cpp and saturation_test.cpp for new behavior
Documents that repair/denoise is intentionally classical DSP (spectral subtraction, MMSE-STSA, LogMMSE) and that DNN restoration, source separation, and spectral repair are explicitly out of scope.
…ure tooling - Add golden_hash_test.cpp for preset output hash regression testing - Add property_test.cpp for property-based mastering chain invariants - Add preset_hashes.tsv as the golden baseline for hash comparisons - Add ebu_r128/README.md documenting the EBU R128 fixture contract - Add --require-complete option to run_optional_fixture_report.py - Register property_test and golden_hash_test in tests/CMakeLists.txt
Update the masteringPresetNames() example output in the Node, Python, and WASM READMEs to include the nine new presets: drumAndBass, techno, metal, trap, rnb, jazz, kpop, trance, gameOst.
… editor, voice changer, and C/WASM bindings New modules: - rt/: Shared DSP primitives extracted from mastering/common (biquad, delay line, envelope follower, oversampler, param smoother, partitioned convolver, true-peak filter, polyphase FIR, ADAA, nonlinearities, scoped-no-denormals, sliding max, processor base/chain). mastering/common headers now re-export from rt/ for backward compatibility. - mixing/: Gain, pan law (equal-power), panner, channel strip (pre/post EQ, aux send, metering), bus, FX bus, send, VCA group, alignment delay, meter (peak/RMS/LUFS), stereo width, goniometer buffer, mixer controller. - graph/: Audio routing graph with topological sort, cycle detection, and latency compensation (connection.h, graph.cpp/.h, node.cpp/.h). - effects/reverb/: Dattorro plate, velvet-noise, FDN with per-line damping, and partitioned-convolution reverb. - effects/delay/: Stereo delay with tap/feedback/LPF. - effects/modulation/: LFO, modulated delay line, chorus, flanger, phaser. - effects/native_spectral_stretch + phase_vocoder: Dependency-free phase- locked spectral stretch replacing Signalsmith adapter (dropped). - analysis/pitch_editor/: F0 provider, note segmenter, scale quantizer, note editor, per-frame TD-PSOLA pitch corrector. - analysis/voice_changer/: LPC-envelope formant warp, grain-OLA streaming retune, voice changer core/controller. - tools/sonare_cli.cpp: CLI frontend for analysis and effects. - src/sonare_c_daw.cpp: C API extensions covering mixing/graph/DAW surfaces. - wasm/bindings.cpp: WASM embind coverage for new DAW surfaces. Quality hardening (review reconciliation): - Real reverb topologies (Dattorro, velvet noise, FDN, partitioned convolution) replacing earlier stubs. - Real LPC-envelope formant warp in voice changer (was placeholder). - Real grain-OLA streaming pitch shift in streaming_retune. - RT-safety: no audio-thread allocation in alignment_delay or convolution_reverb; sidechain HPF state preallocated; graph guards against duplicate connections. - DC blocker made sample-rate-dependent. - Mono pan-law corrected. - pitch_shift duration bug fixed to match librosa semantics (duration preserved rather than extended by shift ratio). Tests: 1122 cases / 771,319 assertions all pass
…FS metering The channel strip was a thin fader+pan wrapper; this commit turns it into a production-ready stage matching typical DAW architecture. ChannelStrip (channel_strip.h/cpp): - Add ParametricEq stage with atomic EqPosition (PreFader / PostFader) - Add pre/post-fader tap buffers (zero-allocation after prepare()) - Add MeterProcessor embedded at the end of the chain - Add dynamic aux-send bus via add_send() / mix_send(); pre/post-fader routing derived from send timing; send gain is smoothed - Warm up ParametricEq during prepare() so first process() is RT-safe - Extend reset() to cover eq, meter, sends, and scratch buffers MeterProcessor (meter.h/cpp): - Add optional BS.1770-3 K-weighting (high-shelf pre-filter + RLB highpass) using hardcoded 48 kHz coefficients or runtime biquad design - Add momentary (400 ms), short-term (3 s), and gated-integrated LUFS via a single shared ring buffer and a bounded loudness histogram - Replace double-buffer snapshot with a seqlock for wait-free reads - Add MeterConfig to gate LUFS work; peak/RMS path unchanged when disabled - Default MeterSnapshot fields use constants::kFloorDb instead of -120 f literals GainProcessor (gain.h/cpp): - Make gain_db() read from an atomic<float> for thread-safe observer access Support files: - panner.h/cpp, stereo_width.h/cpp: minor accessor and smoothing cleanups - Reverb headers (dattorro, fdn, velvet): align trailing comment whitespace - dc_blocker, phase_vocoder, graph, voice changer, pitch corrector: clang-format line-length fixes only tests/mixing/mixing_test.cpp (+361 lines): - StereoWidthProcessor: steady-state convergence and zipper-noise guard - MeterProcessor: seqlock seq counter, peak/RMS finiteness, LUFS sine reference against offline LUFS calculation, integrated gating, and MeterConfig disable path - ChannelStrip: EQ insertion, pre/post-fader EQ position, aux send pre/post routing, and embedded meter reads
…g surface
Expand the mixing module with sample-accurate automation, a JSON scene
schema with three built-in presets, and a unified C / Python / Node /
WASM / CLI surface.
Channel strip (src/mixing/):
- AutomationLane: lock-free SPSC ring buffer for fader, pan, width, and
per-send automation; block splitting via consume_block template
- ChannelStrip: process_at() with block segmentation, polarity invert,
AlignmentDelay, StereoWidthProcessor, dual pre/post MeterProcessor,
GoniometerBuffer, pre/post insert slots, schedule_*_automation()
- AlignmentDelay: sub-sample fractional delay (Q8 fixed-point) exposed
via delay_samples_q8()
- Panner: balance / stereo-pan / dual-pan modes
- api/scene.h + scene_json.cpp: pure-data Scene schema with Strip, Bus,
VcaGroup, Connection; scene_to_json / scene_from_json
- api/presets.h + presets.cpp: VocalReverbSend, DrumBusSubgroup,
CommentaryDucking presets
Graph (src/graph/):
- Latency compensation upgraded to Q8 fixed-point arithmetic
- FractionalDelayLine path for sub-sample compensation in process_block
C API (src/sonare_c.h + src/sonare_c_mixing.cpp):
- SonareMixer / SonareStrip opaque types
- sonare_mixer_create/destroy, sonare_mixer_add_strip
- sonare_strip_set_{fader_db,pan,dual_pan,width,muted}
- sonare_strip_add_send, sonare_strip_set_send_db
- sonare_mixer_process_stereo, sonare_mixer_{to,from}_scene_json
- sonare_mixing_scene_preset_{names,json}
WASM (src/wasm/bindings.cpp): mixStereo, mixingScenePresetNames/Json
Python (bindings/python/): mix_stereo, mixing_scene_preset_{names,json},
MixResult type; FFI stubs for add_send, set_send_db, from/to_scene_json
Node/TypeScript (bindings/node/): same surface via N-API addon
Tests and QA:
- tests/mixing/golden_hash_test.cpp: FNV-1a quantized stereo hashes for
unity-balance, panned-fader, stereo-pan-wide scenarios
- tests/mixing/no_alloc_test.cpp: RT no-allocation process checks
- tests/mixing/mixing_test.cpp: round-trip scene JSON, C API coverage
- tests/graph/graph_test.cpp: fractional delay and Q8 latency tests
- tests/mixing/golden/strip_hashes.tsv: reference hash fixture
CI / build / docs:
- .github/workflows/ci.yml: native-matrix job (macos-latest, windows-latest)
- benchmarks/mixing_bench.cpp: mixing throughput benchmark target
- README.md / README_ja.md: mixing section, CMake flag docs, CLI examples
- CHANGELOG.md: Unreleased mixing entry
…ssover helper - dereverb_classical.cpp regularization now uses constants::kSpectrumEpsilon - Rename butterworth_section_specs to unscaled_rt_butterworth_sections in crossover.cpp
- Update doc comment to state the librosa default returns the biased autocorrelation matrix
- Add chordStartTime to progressive estimate types in wasm index.ts, sonare.js.d.ts, stream_types.ts, and wasm_types.ts - Add Python stream-type stub exports to __init__.py, __init__.pyi, and types.pyi
…ocated channel state Pre-allocate per-channel state up to kPreparedChannels = 64 in prepare() for Gate, Compressor, Expander, DeEsser, TransientShaper, UpwardCompressor, and UpwardExpander. process() now throws std::invalid_argument if num_channels exceeds prepared capacity instead of heap-allocating on the audio thread. - Gate/Compressor: pre-size hpf_x1_/hpf_y1_ to 64 in prepare(); throw on overflow - Expander/DeEsser: pre-resize followers/filter state to 64; throw on overflow - TransientShaper: move all channel-state allocation into prepare(); store max_block_size_ for use in set_config(); introduce kEnvelopeFloor constant - UpwardCompressor/UpwardExpander: raise kPreparedChannels from 2 to 64; ensure_followers() throws instead of reallocating - wasm/bindings.cpp: expose DeEsserConfig bandpassQ field - tests/mixing/no_alloc_test.cpp: add zero-allocation tests for all seven processors covering mono/stereo channel-count changes after prepare
…aming-safe flag - Add resolve_platform_loudness() in suggester.cpp that maps target_platform to preset LUFS/ceiling pairs (broadcast: -23/-1, podcast: -16/-1, club/cd: -9/-0.3) while only overriding values the caller left at default - Gate denoise repair stage behind !prefer_streaming_safe so streaming-safe mode keeps declick but skips denoise; adjust explanation text accordingly - Add TEST_CASE in tests/mastering/assistant_test.cpp covering broadcast loudness resolution, streaming-safe repair exclusion, and full offline repair
…malize_matrix helper - chroma.cpp: remove hand-written L1/L2/Inf per-column loops; delegate to normalize_matrix(axis=0) with NormType mapped from the norm integer arg - nnls_chroma.cpp: replace per-frame max-norm loop with normalize_matrix (NormType::Inf); add #include "util/vector_normalize.h" - nnls_chroma.cpp: clarify kStddevFloor comment explaining why it exceeds constants::kEpsilon (prevent over-amplification of flat CQT rows) - No behavior change; 42 lines removed, 10 added
… NumPy - Replace std::nth_element on a rounded index with std::sort + linear interpolation between the two surrounding ranks - Matches NumPy/librosa percentile behavior (method='linear') - Affects dynamics percentile calculations in acoustic_analyzer.cpp
- Add TempogramMode enum (kAutocorrelation default, kCosine) to rhythm.h - Cosine mode normalizes each lagged-onset dot product by the product of slice magnitudes, making output scale-invariant and bounded to [-1, 1] - Expose sonare_tempogram_with_mode() in sonare_c.h; original sonare_tempogram() becomes a thin wrapper forwarding kAutocorrelation - Thread mode through Node addon (TempogramModeFromValue), WASM embind (tempogramModeFromValue), and Python ctypes (_ffi.py + _conversions.py) - All binding public APIs accept 'autocorrelation'/'auto'/'ac'/'cosine' or numeric 0/1; TypeScript TempogramMode union type added to all targets - Tests: scale-invariance and [-1,1] bound verified in C++ (librosa + C API suites), Node, Python, and WASM
…tics Monitor/cue bus: - Add process_with_monitor() writing PFL/AFL cue into a dedicated monitor_out buffer instead of folding it into the main output - Refactor process() and process_subblock() to share process_impl() with a fold_monitor_to_main flag; existing callers retain foldback - Extract block_end_frame/command_belongs_to_block helpers and replace duplicate inline arithmetic in drain_commands - Expose kMaxAudioChannels constant (64) replacing the magic literal Telemetry diagnostics: - Add TelemetryErrorCode::kAutomationBindTargetOverflow, kStaleAutomationLanes, kSmoothedParameterCapacity to telemetry.h - Enqueue kAutomationBindTargetOverflow and kStaleAutomationLanes delta counts from process_impl() each block - Report kSmoothedParameterCapacity (with target_id as payload) instead of silently falling back when all smoother slots are saturated - Drop mutable/const from stale_lane_apply_count_ in AutomationEngine (atomic write now required from non-const apply path) - Init automation_bind_overflow_reported_ and automation_stale_lane_reported_ snapshots in prepare() to suppress spurious errors on first block Bindings (all exposing process_with_monitor + new error enum values): - C API: sonare_engine_process_with_monitor in sonare_c.h / sonare_c_daw.cpp - WASM embind: bindings.cpp, worklet.ts, wasm_types.ts, public_types.ts - Node addon: sonare_wrap_engine.cpp/.h, index.ts, types.ts - Python: _ffi.py, engine.py/.pyi, types.py/.pyi Tests: C++ engine, telemetry, C API, Node, Python, and WASM all updated
…l_limits.h Each dynamics processor (Compressor, DeEsser, Expander, Gate, TransientShaper, UpwardCompressor, UpwardExpander) previously defined its own identical `static constexpr size_t kPreparedChannels = 64`. - Add channel_limits.h with a single shared constant `kRealtimePreparedChannels = 64` in namespace `sonare::mastering::dynamics` - Replace all seven local definitions with an include of that header - Remove the now-redundant `#include <cstddef>` from each header No behaviour change; process() paths are unaffected.
Also fixes the stale SONARE_VERSION_* macros in sonare.h (was 1.0.4) so runtime version() reports correctly.
- Ran ncu -u in wasm/node bindings: vitest, biome 2.4.8→2.4.15, cmake-js 7→8, node-addon-api, typescript bumped - Kept @types/node at ^22 to match the Node 22 runtime target - Fixed newly-flagged biome 2.4.15 lint: removed unused wasmModule/ SharedEngineRing, added block-statement braces, reordered imports - Bumped biome.json $schema to 2.4.15
Align local make test/make test-optional-fixtures and the publish.yml C++ test step with ci.yml, which already passed --parallel.
- Define NOMINMAX on MSVC so <windows.h> (via dr_libs) stops clobbering std::min/std::max, fixing C2589/C2059 in audio_io.cpp and resample.cpp - Mark third_party (kissfft/dr_libs/minimp3/r8brain) and the fetched Eigen as SYSTEM includes and add /external:W0 so MSVC /W4 /WX no longer errors on third-party warnings (C4244/C4127) - Suppress the intentional alignas-padding warning C4324 via /wd4324 - Add explicit static_cast<int> in cqt.cpp for float-to-int narrowing (C4244)
- Only register CLI tests when BUILD_CLI is ON; they shell out to the sonare binary which is absent under -DBUILD_CLI=OFF, causing exit 127 in CI - Flow-control the RtSnapshot concurrent-readers stress test so the producer never runs more than kRetain/2 generations ahead of the slowest reader, making it robust under parallel oversubscription (was a heap-use-after-free / bad_read under ctest --parallel; the RtSnapshot primitive itself is correct for its documented bounded contract and is unchanged) - Replace EqualizerProcessor exact-hash golden assertion with a tolerance-based (WithinAbs 1e-4) comparison against reference samples; exact float hashes are not portable across compilers and failed on Linux GCC
Reorder includes to satisfy Google style include ordering enforced by clang-format; no logic changes.
ASan caught stack-use-after-scope in ChannelStrip::process_insert_chain and SidechainRouter::set_sidechain (via BusProcessor). The graph StripNode/BusNode build a transient on-stack key[2] array of channel pointers and pass it to set_insert_sidechain, which previously stored the borrowed array-of-pointers; it was dereferenced after the stack array went out of scope. InsertSidechain now owns a by-value copy of the channel pointers (the pointed-to sample buffers stay valid for the block), eliminating the dangling borrow.
On Windows CI there is no system Eigen, so the fetched-Eigen fallback was used with non-system includes, making MSVC /W4 /WX error on warnings inside Eigen (C4127 etc.). Mark the fetched eigen target's includes as system (INTERFACE_SYSTEM_INCLUDE_DIRECTORIES); find_package'd Eigen on Linux/macOS is already system.
The test prepared the limiter with max_block_size 512 but processed 2048-sample blocks, overrunning the oversampled buffers (heap-buffer-overflow / Linux segfault). process() must never receive more samples than the prepared maximum; prepare with 2048 to match the blocks it feeds.
Welcome to Codecov 🎉Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests. ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment Thanks for integrating Codecov - We've got you covered ☂️ |
Populate the fetched-Eigen fallback as headers-only (manual SYSTEM INTERFACE target) instead of running Eigen's CMake project, which on platforms without a system Eigen (Windows and macOS CI, WASM) registered Eigen's ~880 unit tests into our CTest where they failed as "Unable to find executable". Also define _CRT_SECURE_NO_WARNINGS on MSVC so C4996 deprecation of standard C functions (e.g. strncpy in the C API) does not break the /WX build.
The control thread hammered set_tempo() thousands of times unpaced while the audio thread processed, exceeding RtSnapshot's 64-generation retention window under parallel oversubscription and tripping a heap-use-after-free in TempoMap. Pace the control loop (20us/iteration) and shrink the CI case to 256 blocks so it stays within the retention window deterministically; move the heavy 20000-block soak into a hidden [.stress] test that the default CI run does not execute. The engine/RtSnapshot code is correct for its documented bounded contract and is unchanged.
MSVC /W4 flags double->float, size_t->int, and literal narrowing (C4244/C4267/ C4305) that the primary GCC/Clang build does not, since -Wall -Wextra deliberately excludes -Wconversion. This audio library performs such narrowing intentionally, so silence those warnings on MSVC to hold all toolchains to the same established bar rather than a stricter one.
… init - Set splitting: false in tsup.config.ts so each entry point (index.js, worklet.js) is a fully self-contained bundle; a real AudioWorkletGlobalScope cannot resolve sibling code-split chunks, so the worklet must stand alone - Re-export init/isInitialized from worklet.ts so the worklet realm can initialize its own wasm module instance independently of the main thread - Initialize both modules in worklet.test.ts beforeAll, since each bundle owns its own module singleton after code-splitting is disabled - Clean stale chunk-*.js / *-*.d.ts artifacts in build:js before running tsup to avoid leftover files from prior code-split builds
Adds .github/workflows/develop-ci.yml with three jobs triggered on push and PR to develop (docs/markdown paths excluded): - clang-format: verifies C/C++ formatting across all non-third-party sources - lint: runs Biome on bindings/wasm (Node 22 + Yarn cache) - build-and-test: single-platform Linux/Debug CMake build + ctest The heavy multi-OS, ASan/UBSan, coverage, and WASM validation stays in ci.yml as the pre-release gate (PRs to main, pushes to main). Concurrency group with cancel-in-progress avoids redundant runs on rapid pushes.
MSVC rejected the Windows CI build with C1061 ("blocks nested too
deeply") because apply_one_param_to_config was a single ~140-branch
else-if chain; MSVC counts each else-if as a nested block and hits its
compiler limit, whereas GCC/Clang accept it without complaint.
- Extract five flat per-stage helpers: apply_repair_param,
apply_eq_dynamics_param, apply_saturation_param,
apply_spectral_stereo_param, apply_maximizer_loudness_param
- Each helper uses independent early-return if blocks (nesting depth 1)
instead of else-if chains
- Dispatcher calls helpers in sequence and throws on an unknown key
- All 126 parameter keys preserved; semantics unchanged
These tests built on GCC/Clang but failed the newly-enabled Windows MSVC CI job: - Replaced all M_PI usages (66 occurrences across 32 files) with sonare::constants::kPiD and added the util/constants.h include. MSVC does not define M_PI without _USE_MATH_DEFINES, and the project bans M_PI in favour of sonare::constants. - Promoted function-local constexpr values referenced inside lambdas to static constexpr in eq_test, routing_test, mixing_test and realtime_engine_test; MSVC otherwise tries to capture them and rejects their use as std::array sizes / constant expressions (C2975 / C3493). - Made no_alloc_test aligned allocation portable: _aligned_malloc / _aligned_free on Windows, posix_memalign / std::free elsewhere (C3861). - Added MSVC warning(disable : 4996) branches alongside the existing GCC/Clang -Wdeprecated-declarations suppression in vqt_test, which intentionally exercises the deprecated ivqt API (C2220 under /WX).
The cqt tests intentionally exercise the deprecated icqt API and already suppressed the GCC/Clang -Wdeprecated-declarations warning; add the matching MSVC warning(disable : 4996) branch so the Windows /WX build does not treat C4996 as a fatal C2220 error.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Release v1.2.0. Bumps the version across all 5 locations (CMake,
sonare.h, Python, wasm, node) and updates the changelog. Includes ~50 commits since v1.1.0 — no breaking changes.Highlights:
Also in this PR:
chore(deps): ncu -u on bindings (vitest, biome 2.4.15, cmake-js 8, node-addon-api);@types/nodekept at ^22 to match the Node 22 runtime; fixed biome 2.4.15 lint.ci: run ctest with--parallelin the Makefile and publish workflow (ci.yml already did).SONARE_VERSION_*macros (were 1.0.4) so runtimeversion()is correct.Test plan