Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/style.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
77 changes: 77 additions & 0 deletions scripts/tidy.sh
Original file line number Diff line number Diff line change
@@ -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
4 changes: 2 additions & 2 deletions source/projects/mutap.aec_tilde/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
21 changes: 11 additions & 10 deletions source/projects/mutap.aec_tilde/mutap.aec_tilde.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<double> engines as mutap.afc~ (the paper the PEM structure
/// tap::mu::pem_afc<double> 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
Expand All @@ -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
Expand Down Expand Up @@ -76,12 +76,13 @@
using namespace c74::min;

class mutap_aec : public object<mutap_aec>, public vector_operator<> {
using speech_aec = mutap::pem_afc<double>;
using warped_aec = mutap::pem_afc<double, mutap::warped_lpc_predictor<double>>;
using kalman_speech_aec = mutap::pem_afc<double, mutap::speech_predictor<double>, mutap::partitioned_fdkf<double>>;
using speech_aec = tap::mu::pem_afc<double>;
using warped_aec = tap::mu::pem_afc<double, tap::mu::warped_lpc_predictor<double>>;
using kalman_speech_aec =
tap::mu::pem_afc<double, tap::mu::speech_predictor<double>, tap::mu::partitioned_fdkf<double>>;
using kalman_warped_aec =
mutap::pem_afc<double, mutap::warped_lpc_predictor<double>, mutap::partitioned_fdkf<double>>;
using chain_aec = mutap::aec_chain<double>; ///< raw Kalman canceller + suppressor + comfort noise
tap::mu::pem_afc<double, tap::mu::warped_lpc_predictor<double>, tap::mu::partitioned_fdkf<double>>;
using chain_aec = tap::mu::aec_chain<double>; ///< 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
Expand Down Expand Up @@ -458,14 +459,14 @@ class mutap_aec : public object<mutap_aec>, 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<size_t>(m_block_size);
auto cfg = mutap::aec_chain_preset<double>(
auto cfg = tap::mu::aec_chain_preset<double>(
b, std::max<size_t>(1, (static_cast<size_t>(m_filter_length) + b - 1) / b), sr);
cfg.postfilter.comfort_noise = m_comfort;
// @gate selects the initial receive guard (switched < 14 dB send loss
Expand Down
4 changes: 2 additions & 2 deletions source/projects/mutap.afc_tilde/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
15 changes: 8 additions & 7 deletions source/projects/mutap.afc_tilde/mutap.afc_tilde.cpp
Original file line number Diff line number Diff line change
@@ -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<double> (FDAF-PEM-AFROW: a partitioned-block
/// signal. Wraps tap::mu::pem_afc<double> (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
Expand Down Expand Up @@ -54,11 +54,12 @@
using namespace c74::min;

class mutap_afc : public object<mutap_afc>, public vector_operator<> {
using speech_afc = mutap::pem_afc<double>;
using warped_afc = mutap::pem_afc<double, mutap::warped_lpc_predictor<double>>;
using kalman_speech_afc = mutap::pem_afc<double, mutap::speech_predictor<double>, mutap::partitioned_fdkf<double>>;
using speech_afc = tap::mu::pem_afc<double>;
using warped_afc = tap::mu::pem_afc<double, tap::mu::warped_lpc_predictor<double>>;
using kalman_speech_afc =
tap::mu::pem_afc<double, tap::mu::speech_predictor<double>, tap::mu::partitioned_fdkf<double>>;
using kalman_warped_afc =
mutap::pem_afc<double, mutap::warped_lpc_predictor<double>, mutap::partitioned_fdkf<double>>;
tap::mu::pem_afc<double, tap::mu::warped_lpc_predictor<double>, tap::mu::partitioned_fdkf<double>>;

/// 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
Expand Down
2 changes: 1 addition & 1 deletion submodules/MuTap
Submodule MuTap updated 88 files
+19 βˆ’3 .github/workflows/ci.yml
+4 βˆ’2 .github/workflows/style.yml
+4 βˆ’0 .gitmodules
+8 βˆ’82 CMakeLists.txt
+18 βˆ’8 README.md
+14 βˆ’14 bench/bench_aec.cpp
+5 βˆ’5 bench/icount/icount_main.cpp
+45 βˆ’14 docs/itu-compliance.md
+16 βˆ’10 docs/optimization.md
+2 βˆ’2 include/mutap/fd_kalman.h
+2 βˆ’2 include/mutap/fdaf.h
+15 βˆ’290 include/mutap/fft.h
+2 βˆ’2 include/mutap/lpc.h
+3 βˆ’3 include/mutap/pem_afc.h
+2 βˆ’2 include/mutap/postfilter.h
+77 βˆ’0 scripts/tidy.sh
+1 βˆ’0 submodules/dsptap
+0 βˆ’2 tests/CMakeLists.txt
+1 βˆ’1 tests/branchless_parity_check.cpp
+5 βˆ’5 tests/support/closed_loop.h
+3 βˆ’3 tests/support/echo_scenario.h
+137 βˆ’9 tests/support/itu_chain.h
+3 βˆ’3 tests/support/itu_signals.h
+19 βˆ’19 tests/test_adaptation_control.cpp
+7 βˆ’6 tests/test_aec.cpp
+4 βˆ’4 tests/test_closed_loop.cpp
+15 βˆ’15 tests/test_fd_kalman.cpp
+19 βˆ’19 tests/test_fdaf.cpp
+0 βˆ’212 tests/test_fft.cpp
+0 βˆ’112 tests/test_fft_backend.cpp
+20 βˆ’17 tests/test_float32.cpp
+97 βˆ’75 tests/test_g168.cpp
+24 βˆ’17 tests/test_itu_doubletalk.cpp
+51 βˆ’40 tests/test_itu_dynamics.cpp
+60 βˆ’41 tests/test_itu_echo.cpp
+2 βˆ’2 tests/test_itu_signals.cpp
+35 βˆ’35 tests/test_lpc.cpp
+22 βˆ’22 tests/test_pem_afc.cpp
+19 βˆ’19 tests/test_postfilter.cpp
+2 βˆ’2 tests/test_rir_fixtures.cpp
+0 βˆ’318 third_party/cmsis-dsp/Include/arm_common_tables.h
+0 βˆ’86 third_party/cmsis-dsp/Include/arm_const_structs.h
+0 βˆ’749 third_party/cmsis-dsp/Include/arm_helium_utils.h
+0 βˆ’80 third_party/cmsis-dsp/Include/arm_math.h
+0 βˆ’224 third_party/cmsis-dsp/Include/arm_math_memory.h
+0 βˆ’729 third_party/cmsis-dsp/Include/arm_math_types.h
+0 βˆ’193 third_party/cmsis-dsp/Include/arm_mve_tables.h
+0 βˆ’864 third_party/cmsis-dsp/Include/dsp/basic_math_functions.h
+0 βˆ’86 third_party/cmsis-dsp/Include/dsp/bayes_functions.h
+0 βˆ’345 third_party/cmsis-dsp/Include/dsp/complex_math_functions.h
+0 βˆ’785 third_party/cmsis-dsp/Include/dsp/controller_functions.h
+0 βˆ’386 third_party/cmsis-dsp/Include/dsp/distance_functions.h
+0 βˆ’379 third_party/cmsis-dsp/Include/dsp/fast_math_functions.h
+0 βˆ’2,570 third_party/cmsis-dsp/Include/dsp/filtering_functions.h
+0 βˆ’275 third_party/cmsis-dsp/Include/dsp/interpolation_functions.h
+0 βˆ’871 third_party/cmsis-dsp/Include/dsp/matrix_functions.h
+0 βˆ’576 third_party/cmsis-dsp/Include/dsp/none.h
+0 βˆ’153 third_party/cmsis-dsp/Include/dsp/quaternion_math_functions.h
+0 βˆ’988 third_party/cmsis-dsp/Include/dsp/statistics_functions.h
+0 βˆ’539 third_party/cmsis-dsp/Include/dsp/support_functions.h
+0 βˆ’46 third_party/cmsis-dsp/Include/dsp/svm_defines.h
+0 βˆ’280 third_party/cmsis-dsp/Include/dsp/svm_functions.h
+0 βˆ’1,408 third_party/cmsis-dsp/Include/dsp/transform_functions.h
+0 βˆ’272 third_party/cmsis-dsp/Include/dsp/utils.h
+0 βˆ’812 third_party/cmsis-dsp/Include/dsp/window_functions.h
+0 βˆ’201 third_party/cmsis-dsp/LICENSE
+0 βˆ’20 third_party/cmsis-dsp/PrivateInclude/arm_compiler_specific.h
+0 βˆ’325 third_party/cmsis-dsp/PrivateInclude/arm_vec_fft.h
+0 βˆ’45,787 third_party/cmsis-dsp/Source/CommonTables/arm_common_tables.c
+0 βˆ’519 third_party/cmsis-dsp/Source/CommonTables/arm_const_structs.c
+0 βˆ’6,484 third_party/cmsis-dsp/Source/CommonTables/arm_mve_tables.c
+0 βˆ’148 third_party/cmsis-dsp/Source/TransformFunctions/arm_bitreversal2.c
+0 βˆ’1,306 third_party/cmsis-dsp/Source/TransformFunctions/arm_cfft_f32.c
+0 βˆ’365 third_party/cmsis-dsp/Source/TransformFunctions/arm_cfft_init_f32.c
+0 βˆ’706 third_party/cmsis-dsp/Source/TransformFunctions/arm_rfft_fast_f32.c
+0 βˆ’386 third_party/cmsis-dsp/Source/TransformFunctions/arm_rfft_fast_init_f32.c
+0 βˆ’42 third_party/cmsis-dsp/VENDOR.md
+0 βˆ’220 third_party/cmsis-dsp/cmsis-core/Include/cmsis_compiler.h
+0 βˆ’1,024 third_party/cmsis-dsp/cmsis-core/Include/cmsis_gcc.h
+0 βˆ’720 third_party/cmsis-dsp/cmsis-core/Include/m-profile/cmsis_gcc_m.h
+0 βˆ’3,325 third_party/ooura/fftsg.c
+0 βˆ’62 third_party/ooura/fftsg_float.c
+0 βˆ’166 third_party/ooura/readme.txt
+12 βˆ’10 tools/capi/mutap_capi.cpp
+6 βˆ’6 tools/capi/mutap_capi.h
+4 βˆ’4 tools/notebook/build_afc_demo.py
+3 βˆ’3 tools/notebook/build_itu_compliance.py
+1 βˆ’1 tools/notebook/itu_dump.cpp
Loading