Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
0395d83
feat: FX node contract (node protocol, configs, built-in parameter sp…
JacobCoffee Oct 30, 2026
c351bc5
feat: host the Airwindows effect suite (AirwindowsNode, AirwindowsCat…
JacobCoffee Oct 30, 2026
a360e93
feat: host Audio Units (v2 in-process, v3) as voice-chain stages
JacobCoffee Oct 30, 2026
5d99874
feat: JSFX hosting via vendored ysfx/EEL2 (CYSFX), catalog, node, gfx…
JacobCoffee Oct 30, 2026
067c738
feat: FX engine core - FXChain, FXEngine, EffectsPreset v2, app-audio…
JacobCoffee Oct 30, 2026
7d1e891
docs: measure JSFX allocation, binary size, real-world smoke test; do…
JacobCoffee Oct 30, 2026
2eacd4b
fix: host v2 Audio Units through the C API, not AUAudioUnit's bridge
JacobCoffee Oct 30, 2026
41bdd25
fix: FXChain graph lifecycle, AB bypass timing, lock-free AppAudioPro…
JacobCoffee Oct 30, 2026
fa81543
feat: echo cancellation via SystemAudioTap + SpeexDSP MDF EchoCanceller
JacobCoffee Oct 30, 2026
b755a1d
feat: replace SpeexDSP MDF echo canceller with WebRTC AEC3
JacobCoffee Oct 30, 2026
34f06d4
fix: tune AEC3 double talk to meet 3dB target at realistic echo ratios
JacobCoffee Oct 30, 2026
3d43ac2
merge fx/core: FX engine core
JacobCoffee Oct 30, 2026
6843afc
merge fx/au: Audio Unit hosting
JacobCoffee Oct 30, 2026
73a9a3d
merge fx/jsfx
JacobCoffee Oct 30, 2026
5da29ef
merge fx/airwin
JacobCoffee Oct 30, 2026
19954af
fix: commit abseil internal/ headers hidden by a global gitignore
JacobCoffee Oct 30, 2026
4281bc3
merge fx/comms: echo cancellation (WebRTC AEC3, system audio tap)
JacobCoffee Oct 30, 2026
e86d9cc
merge fx/comms: abseil internal headers
JacobCoffee Oct 30, 2026
d29494d
feat: built-in FX DSP stages (gate, EQ, compressor, leveler, de-esser…
JacobCoffee Oct 30, 2026
1834195
merge fx/dsp: pro built-in stages and voice activity detector
JacobCoffee Oct 30, 2026
9fea6dd
merge fx/dsp: pro built-in stages and voice activity detector
JacobCoffee Oct 30, 2026
be66236
test: fix VoiceBus comment
JacobCoffee Oct 30, 2026
34fc1e8
feat: wire echo cancellation into routing, add EchoCancellationSection
JacobCoffee Oct 30, 2026
606ed40
fix: scope system audio tap to the default output device
JacobCoffee Oct 30, 2026
67f5e31
feat: mic mute/push-to-talk, app-based preset auto-switch, Shortcuts/…
JacobCoffee Oct 30, 2026
2d1742f
feat: add Stream Mix, a second virtual mic routing target
JacobCoffee Oct 30, 2026
4584d51
merge fx2/comms
JacobCoffee Oct 30, 2026
13fd71b
merge fx2/control
JacobCoffee Oct 30, 2026
06ff032
merge fx2/stream: Stream Mix virtual device and per-target routes
JacobCoffee Oct 30, 2026
ccc36f0
feat: redesign Effects page (Simple/Advanced, chain editor, mic check…
JacobCoffee Oct 30, 2026
cebbbcd
fix: offscreen-safe glass fallback and real visual-review fixes
JacobCoffee Oct 30, 2026
2c03b52
fix: Simple-mode slider labels, toolbar Mode picker, connector glyphs…
JacobCoffee Oct 30, 2026
36c8012
feat: v2 factory presets, FXMacros, AutoSetup, call-app advice
JacobCoffee Oct 30, 2026
1a85618
test: loosen noise-floor-independence tolerance for VAD classificatio…
JacobCoffee Oct 30, 2026
054b544
merge fx2/presets: business/gaming presets, macros, auto setup, call-…
JacobCoffee Oct 30, 2026
b82cf51
merge fx2/ui: Effects page redesign, mic check, auto setup UI
JacobCoffee Oct 30, 2026
ae04cec
fix: build vendored DSP for x86_64 (CodeQL)
JacobCoffee Oct 30, 2026
f5433e1
merge fx3/x86: build vendored DSP for x86_64
JacobCoffee Oct 30, 2026
85e9220
fix(fx): apply A/B ratio, reclaim superseded graphs, skip settled byp…
JacobCoffee Oct 30, 2026
ed57e9e
fix(fx): capture hosted state from the edited chain; isolate meter po…
JacobCoffee Oct 30, 2026
d0c1d15
fix(fx): wire FXChain.setMasterEnabled into the two preset.isEnabled …
JacobCoffee Oct 30, 2026
d03dab6
merge fx3/chain: master enable, A/B ratio, bypass skip, graph reclama…
JacobCoffee Oct 30, 2026
ae62c9b
fix(aec): give each echo canceller its own reference-ring reader; pri…
JacobCoffee Oct 30, 2026
d823ea8
fix(aec): remove the exact registered output-listener block; convert …
JacobCoffee Oct 30, 2026
a1555d9
fix(router): give every voice route its own MicGate mute/PTT ramp state
JacobCoffee Oct 30, 2026
47d33ff
fix(router): key app-capture sessions by bundle and target so Stream …
JacobCoffee Oct 30, 2026
b2fb0e3
fix(router): share NS/AEC/FX only within a processing group; reclaim …
JacobCoffee Oct 30, 2026
b02ed0d
fix: reset push-to-talk held state when hotkey is disabled or replaced
JacobCoffee Oct 30, 2026
e385bd3
fix: preserve v1 EQ bypass on migration, cap preset import size (LB-R…
JacobCoffee Oct 30, 2026
d06c672
fix: capture live preset before automation engages, re-evaluate after…
JacobCoffee Oct 30, 2026
8fe7b85
fix: persist hosted plugin editor state independent of the Effects view
JacobCoffee Oct 30, 2026
12f38c0
fix: real duck-gain meter, meter width clamp, sanitized hosted param …
JacobCoffee Oct 30, 2026
d53a4ed
feat: gate loopbacker:// URL commands behind an opt-in setting (LB-UR…
JacobCoffee Oct 30, 2026
7201ca3
merge fx3/router: review fixes
JacobCoffee Oct 30, 2026
46a8482
merge fx3/ux: review fixes
JacobCoffee Oct 30, 2026
ded49e7
fix(router): free detached processors at once for stopped routes; bac…
JacobCoffee Oct 30, 2026
9e63dbc
fix(fx): correct EQ publish race, gate zero-range stall, pitch-shift …
JacobCoffee Oct 30, 2026
098d710
fix(fx): share correct BS.1770 K-weighting, fix noise macro direction…
JacobCoffee Oct 30, 2026
83639aa
merge fx3/dsp: DSP review fixes
JacobCoffee Oct 30, 2026
1ca5294
merge main (v4.6.0) into feat/fx-engine
JacobCoffee Oct 30, 2026
9c3a23f
merge main (v4.6.1)
JacobCoffee Oct 30, 2026
d8bf729
fix: harden plugin hosting (quarantine, ref validation, JSFX state/JI…
JacobCoffee Oct 30, 2026
817d7af
merge fx3/host: plugin hosting hardening
JacobCoffee Oct 30, 2026
fbdaf7e
fix(fx): leveler measures loudness over speech only
JacobCoffee Oct 30, 2026
42093a0
docs: FX engine, plugin hosting, echo cancellation, Stream Mix, hotkeys
JacobCoffee Oct 30, 2026
c420eeb
perf(fx): effects off costs nothing and adds no latency
JacobCoffee Oct 30, 2026
3f20a66
build: ship Shortcuts metadata, build with SwiftPM's native build system
JacobCoffee Oct 30, 2026
ea2619f
fix(fx): presets leave echo cancellation alone; show it in both Effec…
JacobCoffee Oct 30, 2026
e463162
fix: tests can never write the installed app's data; room for glass s…
JacobCoffee Oct 30, 2026
e95b1fc
ci: CodeQL workflow replaces default setup
JacobCoffee Oct 30, 2026
8dae1ee
ci: fix CodeQL workflow comment
JacobCoffee Oct 30, 2026
2520246
bump version to 4.7.0 (build 20)
JacobCoffee Oct 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ jobs:
cd App/Loopbacker
swift build -c release

# Release: the factory-preset matrix runs 51 voice-chain passes and is skipped in
# unoptimized builds. Swift's bounds and overflow checks stay on at -O.
- name: Test Swift app
run: |
cd App/Loopbacker
swift test
swift test -c release
73 changes: 73 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Replaces GitHub's default CodeQL setup. Default setup builds Swift with an unbounded
# `swift build` under Rosetta; since the app links ~1,500 vendored C/C++ files that build
# wedged the macOS runner (3 runs, none finished). It also can't skip vendored code.
# Categories match the old default setup so existing alerts and dismissals carry over.
name: CodeQL

on:
push:
branches:
- main
pull_request:
schedule:
- cron: "17 6 * * 1"

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
analyze:
name: Analyze (${{ matrix.language }})
runs-on: ${{ matrix.runner }}
timeout-minutes: 120
permissions:
security-events: write
actions: read
contents: read
strategy:
fail-fast: false
matrix:
include:
- language: actions
runner: ubuntu-latest
build-mode: none
- language: python
runner: ubuntu-latest
build-mode: none
- language: c-cpp
runner: ubuntu-latest
build-mode: none
- language: swift
runner: macos-26
build-mode: manual

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
config: |
paths-ignore:
- App/Loopbacker/CAirwindows
- App/Loopbacker/CRNNoise
- App/Loopbacker/CWebRTCAEC
- App/Loopbacker/CYSFX

# Fewer parallel compiles than the default, to keep the Rosetta-traced build light.
- name: Build Swift app
if: matrix.language == 'swift'
working-directory: App/Loopbacker
run: swift build -j 2

- name: Analyze
uses: github/codeql-action/analyze@v4
with:
category: /language:${{ matrix.language }}
22 changes: 18 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,15 @@ jobs:
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build

# The const-values flags feed scripts/extract-app-intents.sh (Shortcuts metadata); the
# native build system doesn't emit them on its own.
- name: Build Swift app
run: |
cd App/Loopbacker
swift build -c release
swift build -c release \
-Xswiftc -emit-const-values-path -Xswiftc "$RUNNER_TEMP/Loopbacker.swiftconstvalues" \
-Xswiftc -Xfrontend -Xswiftc -const-gather-protocols-file \
-Xswiftc -Xfrontend -Xswiftc "$GITHUB_WORKSPACE/scripts/app-intents-const-protocols.json"

# ── Package .app bundle ──────────────────────────────────────
- name: Create .app bundle
Expand All @@ -77,12 +82,18 @@ jobs:
cp App/Loopbacker/Resources/DPDFNet-LICENSE.txt Loopbacker.app/Contents/Resources/
cp App/Loopbacker/Resources/RNNoise-LICENSE.txt Loopbacker.app/Contents/Resources/
cp App/Loopbacker/Resources/FastEnhancer-LICENSE.txt Loopbacker.app/Contents/Resources/
cp App/Loopbacker/Resources/Airwindows-LICENSE.txt Loopbacker.app/Contents/Resources/
cp App/Loopbacker/Resources/YSFX-LICENSE.txt Loopbacker.app/Contents/Resources/
cp App/Loopbacker/Resources/WDL-LICENSE.txt Loopbacker.app/Contents/Resources/
cp App/Loopbacker/CWebRTCAEC/LICENSE-webrtc-audio-processing.txt Loopbacker.app/Contents/Resources/
cp App/Loopbacker/CWebRTCAEC/LICENSE-abseil.txt Loopbacker.app/Contents/Resources/
cp -R Driver/build/Loopbacker.driver Loopbacker.app/Contents/Resources/
cp -R App/Loopbacker/.build/artifacts/sparkle/Sparkle/Sparkle.xcframework/macos-arm64_x86_64/Sparkle.framework \
Loopbacker.app/Contents/Frameworks/
xcrun actool App/Loopbacker/Resources/Assets.xcassets --compile Loopbacker.app/Contents/Resources \
--platform macosx --minimum-deployment-target 26.0 --accent-color AccentColor \
--output-partial-info-plist "$RUNNER_TEMP/assets-partial.plist" >/dev/null
LB_CONST_VALUES="$RUNNER_TEMP/Loopbacker.swiftconstvalues" scripts/extract-app-intents.sh Loopbacker.app

# ── Code Signing ─────────────────────────────────────────────
- name: Import signing certificate
Expand Down Expand Up @@ -120,13 +131,14 @@ jobs:
- name: Code sign (Developer ID)
if: steps.secrets.outputs.has_cert == 'true'
run: |
codesign --force --options runtime \
codesign --force --options runtime --timestamp \
--sign "$SIGNING_IDENTITY" \
Loopbacker.app/Contents/Resources/Loopbacker.driver

scripts/sign-sparkle.sh Loopbacker.app "$SIGNING_IDENTITY" --hardened

codesign --force --options runtime \
codesign --force --options runtime --timestamp \
--entitlements App/Loopbacker/Resources/Loopbacker.entitlements \
--sign "$SIGNING_IDENTITY" \
Loopbacker.app

Expand All @@ -137,7 +149,9 @@ jobs:
codesign --force --sign - \
Loopbacker.app/Contents/Resources/Loopbacker.driver
scripts/sign-sparkle.sh Loopbacker.app -
codesign --force --sign - \
codesign --force --options runtime \
--entitlements App/Loopbacker/Resources/Loopbacker.entitlements \
--sign - \
Loopbacker.app

# ── Notarization ─────────────────────────────────────────────
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ DerivedData/
.vscode/
*.swp
*~

# Vendored abseil keeps headers in internal/ directories; never let a global ignore drop them.
!App/Loopbacker/CWebRTCAEC/**/internal/
6 changes: 4 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ audio path, and `PRODUCT.md` / `DESIGN.md` before touching UI.
## Build and test

```bash
make bundle # driver + app → build/Loopbacker.app
cd App/Loopbacker && swift test # DSP tests (noise suppression, meters); CI runs these
make bundle # driver + app → build/Loopbacker.app
cd App/Loopbacker && swift test # fast; skips the factory-preset matrix
cd App/Loopbacker && swift test -c release # everything; what CI runs
cd App/Loopbacker && swift build -c release
LOOPBACKER_RENDER_SNAPSHOTS=1 swift test --filter EffectsRenderTests # Effects page PNGs in /tmp
```

- Code that runs in a CoreAudio IO callback must not allocate, lock, call Objective-C, or block.
Expand Down
Loading
Loading