From 4f5abce6ad3e56c6f7dc9d53cd45277604b347cf Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 20 Jul 2026 23:49:44 +0000 Subject: [PATCH 1/3] Adopt TapHouse v4 (normalize style pin, distribute tidy.sh) Bump the drift-check ref v3 -> v4 and add scripts/tidy.sh (the local clang-tidy gate mirror, now distributed by TapHouse). Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MRTDgYKY38WH8Bqz17W9k1 --- .github/workflows/style.yml | 4 +- scripts/tidy.sh | 77 +++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 2 deletions(-) create mode 100755 scripts/tidy.sh diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index 0d7eb3e..172dc5b 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -11,9 +11,9 @@ on: [push, pull_request] jobs: drift: - uses: tap/taphouse/.github/workflows/drift-check.yml@v3 + uses: tap/taphouse/.github/workflows/drift-check.yml@v4 with: - ref: v3 + ref: v4 clang-format: runs-on: ubuntu-latest diff --git a/scripts/tidy.sh b/scripts/tidy.sh new file mode 100755 index 0000000..45fc009 --- /dev/null +++ b/scripts/tidy.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# Local mirror of the CI clang-tidy gate (.github/workflows/style.yml): the +# TapHouse .clang-tidy naming + mandatory-braces checks over this project's +# own translation units. Run it before pushing. +# +# WHY THIS EXISTS (and is not a pre-commit hook): the pre-commit hook only +# runs clang-FORMAT, which is cheap and context-free. clang-TIDY needs a +# compile database (a configured CMake build) and compiles every TU to reason +# about types — too slow and stateful for a per-commit hook, so CI keeps it as +# its own gate. This script is the fast local equivalent of that gate. +# +# Usage: +# scripts/tidy.sh # sweep every project TU (full CI mirror) +# scripts/tidy.sh tests/test_foo.cpp … # only the given TU(s) — fast, for a change +# +# Env: +# CLANG_TIDY=clang-tidy-18 # binary to use (default: clang-tidy-18, then clang-tidy) +# TIDY_BUILD=build-tidy # compile-database build dir (kept separate from ./build) +# TIDY_RECONFIGURE=1 # force a cmake re-configure of the compile database +set -euo pipefail + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$repo_root" + +# Prefer clang-tidy-18 — the version the CI gate installs and the .clang-tidy +# checks are validated against; a different major version may disagree. +tidy="${CLANG_TIDY:-}" +if [ -z "$tidy" ]; then + if command -v clang-tidy-18 >/dev/null 2>&1; then + tidy=clang-tidy-18 + elif command -v clang-tidy >/dev/null 2>&1; then + tidy=clang-tidy + echo "warning: clang-tidy-18 not found; using '$tidy'. CI pins v18 — results may differ." >&2 + else + echo "error: no clang-tidy found. Install clang-tidy-18 (apt) or set CLANG_TIDY=..." >&2 + exit 127 + fi +fi + +build="${TIDY_BUILD:-build-tidy}" + +# A compile database is what clang-tidy needs; reuse it across runs unless it is +# missing or a reconfigure is forced. This does not touch your ./build dir. +if [ "${TIDY_RECONFIGURE:-0}" = "1" ] || [ ! -f "$build/compile_commands.json" ]; then + echo "== configuring compile database in $build/ (one-time; reuses cached deps) ==" + cmake -B "$build" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON >/dev/null +fi + +# File list: the given TUs, or — matching CI exactly — every project TU in the +# database with third_party/ and fetched deps (_deps) excluded. +if [ "$#" -gt 0 ]; then + files=("$@") +else + mapfile -t files < <(python3 -c " +import json +for e in json.load(open('$build/compile_commands.json')): + f = e['file'] + if 'third_party' not in f and '_deps' not in f: + print(f)") +fi + +echo "== clang-tidy ($tidy) over ${#files[@]} file(s) ==" +fail=0 +for f in "${files[@]}"; do + out="$("$tidy" -p "$build" "$f" 2>/dev/null || true)" + if printf '%s\n' "$out" | grep -qE "warning:|error:"; then + printf '%s\n' "$out" + fail=1 + fi +done + +if [ "$fail" -eq 0 ]; then + echo "clang-tidy clean." +else + echo "clang-tidy found violations (above); fix before pushing." >&2 + exit 1 +fi From 28ee703ee7d873ae6cd6e80081479c6ff674d20e Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 21 Jul 2026 16:49:47 +0000 Subject: [PATCH 2/3] Track the tap::mu kernel: bump submodule, adopt namespace, fix FFT target The MuTap kernel migrated its C++ namespace mutap -> tap::mu and, as part of the DspTap extraction, replaced its vendored Ooura FFT target (MuTap::fft) with the shared DspTap real FFT (tap::dsp). This wrapper follows: - Bump the submodules/MuTap pin to the migrated kernel (tap::mu + DspTap). - Rename mutap:: -> tap::mu:: across the Min wrappers (basic_real_fft and the pem_afc/fdkf/lpc types stay reachable under tap::mu via the kernel's shim). The mutap/ include paths are unchanged. - Link the FFT objects (aec, afc) against tap::dsp instead of MuTap::fft. Verified: configure succeeds and the wrappers compile against the bumped kernel. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MRTDgYKY38WH8Bqz17W9k1 --- .../projects/mutap.aec_tilde/CMakeLists.txt | 4 ++-- .../mutap.aec_tilde/mutap.aec_tilde.cpp | 20 +++++++++---------- .../projects/mutap.afc_tilde/CMakeLists.txt | 4 ++-- .../mutap.afc_tilde/mutap.afc_tilde.cpp | 14 ++++++------- submodules/MuTap | 2 +- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/source/projects/mutap.aec_tilde/CMakeLists.txt b/source/projects/mutap.aec_tilde/CMakeLists.txt index 476990c..2da4d2b 100644 --- a/source/projects/mutap.aec_tilde/CMakeLists.txt +++ b/source/projects/mutap.aec_tilde/CMakeLists.txt @@ -19,8 +19,8 @@ add_library( ${SOURCE_FILES} ) -# MuTap headers (header-only pem_afc/fdaf/lpc) + MuTap::fft (the vendored -# Ooura rdft that mutap::basic_real_fft calls); the `mutap` interface target +# MuTap headers (header-only pem_afc/fdaf/lpc) + tap::dsp (the vendored +# Ooura rdft that tap::mu::basic_real_fft calls); the `mutap` interface target # carries both. target_link_libraries(${PROJECT_NAME} PRIVATE mutap) target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20) diff --git a/source/projects/mutap.aec_tilde/mutap.aec_tilde.cpp b/source/projects/mutap.aec_tilde/mutap.aec_tilde.cpp index 71c7c7c..d3dfa55 100644 --- a/source/projects/mutap.aec_tilde/mutap.aec_tilde.cpp +++ b/source/projects/mutap.aec_tilde/mutap.aec_tilde.cpp @@ -5,7 +5,7 @@ /// the patch sends to the speaker), so nothing the canceller does feeds back /// around — what survives from the feedback problem is DOUBLE-TALK, the /// near-end talker speaking over the echo. Wraps the same -/// mutap::pem_afc engines as mutap.afc~ (the paper the PEM structure +/// tap::mu::pem_afc engines as mutap.afc~ (the paper the PEM structure /// implements — Gil-Cacho et al. 2014 — is an open-loop double-talk-robust /// AEC framework before MuTap borrowed it for feedback): the near-end model /// is re-fit every block and whitened out of the adaptive update, which is @@ -27,14 +27,14 @@ /// dominates) every few processed blocks. /// /// @postfilter swaps the whole engine for the measured AEC CHAIN -/// (mutap::aec_chain): the RAW frequency-domain Kalman canceller — not PEM; +/// (tap::mu::aec_chain): the RAW frequency-domain Kalman canceller — not PEM; /// open-loop AEC has an exogenous far end, so the predictor refit buys /// nothing and measurably floors the misalignment — plus the /// coherence-driven residual suppressor, comfort noise matched to the /// near-end noise floor, and the initial receive guard. This is the /// configuration MuTap's ITU-T compliance battery certifies at 48 and /// 16 kHz (docs/itu-compliance.md in MuTap; every requirement met at both -/// rates), built from the library's own preset (mutap::aec_chain_preset), +/// rates), built from the library's own preset (tap::mu::aec_chain_preset), /// which rescales every per-block time constant for the actual @block and /// host sample rate. With @postfilter on, @mu, @warp and @kalman are ignored (the /// chain's canceller is already the Kalman core) and @gate selects the @@ -76,12 +76,12 @@ using namespace c74::min; class mutap_aec : public object, public vector_operator<> { - using speech_aec = mutap::pem_afc; - using warped_aec = mutap::pem_afc>; - using kalman_speech_aec = mutap::pem_afc, mutap::partitioned_fdkf>; + using speech_aec = tap::mu::pem_afc; + using warped_aec = tap::mu::pem_afc>; + using kalman_speech_aec = tap::mu::pem_afc, tap::mu::partitioned_fdkf>; using kalman_warped_aec = - mutap::pem_afc, mutap::partitioned_fdkf>; - using chain_aec = mutap::aec_chain; ///< raw Kalman canceller + suppressor + comfort noise + tap::mu::pem_afc, tap::mu::partitioned_fdkf>; + using chain_aec = tap::mu::aec_chain; ///< raw Kalman canceller + suppressor + comfort noise /// One canceller plus its vector-size bridging buffers, all sized for one /// block. Built on the control thread; used (and only used) on the audio @@ -458,14 +458,14 @@ class mutap_aec : public object, public vector_operator<> { return cfg; } - /// The compliance chain IS the library preset (mutap::aec_chain_preset — + /// The compliance chain IS the library preset (tap::mu::aec_chain_preset — /// the configuration MuTap's ITU battery certifies, with every per-block /// time constant rescaled for the actual block and sample rate; its /// header documents the rule and the two deliberate exceptions). Only the /// external's own toggles are applied on top. typename chain_aec::config make_chain_config(double sr) const { const auto b = static_cast(m_block_size); - auto cfg = mutap::aec_chain_preset( + auto cfg = tap::mu::aec_chain_preset( b, std::max(1, (static_cast(m_filter_length) + b - 1) / b), sr); cfg.postfilter.comfort_noise = m_comfort; // @gate selects the initial receive guard (switched < 14 dB send loss diff --git a/source/projects/mutap.afc_tilde/CMakeLists.txt b/source/projects/mutap.afc_tilde/CMakeLists.txt index 7b08551..1bc677e 100644 --- a/source/projects/mutap.afc_tilde/CMakeLists.txt +++ b/source/projects/mutap.afc_tilde/CMakeLists.txt @@ -19,8 +19,8 @@ add_library( ${SOURCE_FILES} ) -# MuTap headers (header-only pem_afc/fdaf/lpc) + MuTap::fft (the vendored -# Ooura rdft that mutap::basic_real_fft calls); the `mutap` interface target +# MuTap headers (header-only pem_afc/fdaf/lpc) + tap::dsp (the vendored +# Ooura rdft that tap::mu::basic_real_fft calls); the `mutap` interface target # carries both. target_link_libraries(${PROJECT_NAME} PRIVATE mutap) target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_20) diff --git a/source/projects/mutap.afc_tilde/mutap.afc_tilde.cpp b/source/projects/mutap.afc_tilde/mutap.afc_tilde.cpp index 634e333..ee7165d 100644 --- a/source/projects/mutap.afc_tilde/mutap.afc_tilde.cpp +++ b/source/projects/mutap.afc_tilde/mutap.afc_tilde.cpp @@ -1,17 +1,17 @@ /// @file /// mutap.afc~ — acoustic feedback (howling) canceller: subtract an adaptive /// estimate of the loudspeaker→microphone feedback path from the microphone -/// signal. Wraps mutap::pem_afc (FDAF-PEM-AFROW: a partitioned-block +/// signal. Wraps tap::mu::pem_afc (FDAF-PEM-AFROW: a partitioned-block /// frequency-domain adaptive filter whose update is decorrelated from the /// near-end source by prediction-error-method prewhitening — the closed loop /// biases any naive adaptive estimate, and the PEM prewhitening removes that /// bias; Gil-Cacho et al. 2014, Rombouts et al. 2007). @warp swaps the /// speech-cascade near-end model for the frequency-warped one built for -/// music/tonal material (mutap::warped_lpc_predictor), and keeps IPC step +/// music/tonal material (tap::mu::warped_lpc_predictor), and keeps IPC step /// scaling on while it is active — the warped whitener requires it for /// room-robust closed-loop stability (see include/mutap/lpc.h in MuTap). /// @kalman swaps the NLMS core for the frequency-domain Kalman filter -/// (mutap::partitioned_fdkf, the v2 engine): @mu is ignored, @gate selects +/// (tap::mu::partitioned_fdkf, the v2 engine): @mu is ignored, @gate selects /// the burst floor, and the warped model needs no IPC pairing there. /// /// Signal inlet 0 is the microphone signal y; signal inlet 1 is the @@ -54,11 +54,11 @@ using namespace c74::min; class mutap_afc : public object, public vector_operator<> { - using speech_afc = mutap::pem_afc; - using warped_afc = mutap::pem_afc>; - using kalman_speech_afc = mutap::pem_afc, mutap::partitioned_fdkf>; + using speech_afc = tap::mu::pem_afc; + using warped_afc = tap::mu::pem_afc>; + using kalman_speech_afc = tap::mu::pem_afc, tap::mu::partitioned_fdkf>; using kalman_warped_afc = - mutap::pem_afc, mutap::partitioned_fdkf>; + tap::mu::pem_afc, tap::mu::partitioned_fdkf>; /// One canceller plus its vector-size bridging buffers, all sized for one /// block. Built on the control thread; used (and only used) on the audio diff --git a/submodules/MuTap b/submodules/MuTap index 6897f55..2e02473 160000 --- a/submodules/MuTap +++ b/submodules/MuTap @@ -1 +1 @@ -Subproject commit 6897f55991f2363b436c7eb4ca24348e878fb111 +Subproject commit 2e024739bfb54aab8c23224a5b1ef28b1870c1ad From 6769ba10c5ad31d60e62540a26ed48d0be4b6bc1 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 21 Jul 2026 17:55:34 +0000 Subject: [PATCH 3/3] Reflow clang-format alignment after the namespace rename tap::mu differs in width from mutap, shifting clang-format's alignment columns. Reformat with the Tap-wide pinned clang-format (v18.1.3). No functional change. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MRTDgYKY38WH8Bqz17W9k1 --- source/projects/mutap.aec_tilde/mutap.aec_tilde.cpp | 7 ++++--- source/projects/mutap.afc_tilde/mutap.afc_tilde.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/source/projects/mutap.aec_tilde/mutap.aec_tilde.cpp b/source/projects/mutap.aec_tilde/mutap.aec_tilde.cpp index d3dfa55..1d354fa 100644 --- a/source/projects/mutap.aec_tilde/mutap.aec_tilde.cpp +++ b/source/projects/mutap.aec_tilde/mutap.aec_tilde.cpp @@ -76,9 +76,10 @@ using namespace c74::min; class mutap_aec : public object, public vector_operator<> { - using speech_aec = tap::mu::pem_afc; - using warped_aec = tap::mu::pem_afc>; - using kalman_speech_aec = tap::mu::pem_afc, tap::mu::partitioned_fdkf>; + using speech_aec = tap::mu::pem_afc; + using warped_aec = tap::mu::pem_afc>; + using kalman_speech_aec = + tap::mu::pem_afc, tap::mu::partitioned_fdkf>; using kalman_warped_aec = tap::mu::pem_afc, tap::mu::partitioned_fdkf>; using chain_aec = tap::mu::aec_chain; ///< raw Kalman canceller + suppressor + comfort noise diff --git a/source/projects/mutap.afc_tilde/mutap.afc_tilde.cpp b/source/projects/mutap.afc_tilde/mutap.afc_tilde.cpp index ee7165d..8da4d9b 100644 --- a/source/projects/mutap.afc_tilde/mutap.afc_tilde.cpp +++ b/source/projects/mutap.afc_tilde/mutap.afc_tilde.cpp @@ -54,9 +54,10 @@ using namespace c74::min; class mutap_afc : public object, public vector_operator<> { - using speech_afc = tap::mu::pem_afc; - using warped_afc = tap::mu::pem_afc>; - using kalman_speech_afc = tap::mu::pem_afc, tap::mu::partitioned_fdkf>; + using speech_afc = tap::mu::pem_afc; + using warped_afc = tap::mu::pem_afc>; + using kalman_speech_afc = + tap::mu::pem_afc, tap::mu::partitioned_fdkf>; using kalman_warped_afc = tap::mu::pem_afc, tap::mu::partitioned_fdkf>;