Skip to content

feat: Virtual loopback audio device for lossless inter-app routing#310

Open
alexlanderzander wants to merge 3 commits into
ronitsingh10:mainfrom
alexlanderzander:feature/loopback-virtual-audio-device
Open

feat: Virtual loopback audio device for lossless inter-app routing#310
alexlanderzander wants to merge 3 commits into
ronitsingh10:mainfrom
alexlanderzander:feature/loopback-virtual-audio-device

Conversation

@alexlanderzander

Copy link
Copy Markdown

Summary

Adds a CoreAudio HAL plugin that creates a virtual input device called FineTune Loopback, enabling DAWs (Ableton Live, Logic Pro, etc.) to record audio from any app that FineTune taps — lossless, 32-bit float, zero additional latency.

Use Case

DJs and producers can now route audio from Rekordbox, Spotify, or any app directly into their DAW for recording, sampling, or live performance — without any external hardware or lossy screen-recording workarounds.

Architecture

App (Rekordbox) → FineTune tap → EQ/Volume → shared memory ring buffer
                                                      ↓
DAW (Ableton) ← HAL driver ← reads from shared memory
  • Lock-free SPSC ring buffer over POSIX shared memory
  • RT-safe write path: memcpy + atomic head counter only — no alloc, no locks, no ObjC
  • Single-writer enforcement: only one app at a time writes to the ring buffer
  • DAW exclusion: Ableton/Logic/etc. excluded from loopback to prevent feedback loops

New Files

HAL Plugin (FineTuneLoopback/)

  • FTLoopbackDriver.cpp — Full AudioServerPlugInDriverInterface (~1200 LOC)
  • FTLoopbackDriver.h — Constants, supported sample rates (44.1/48/96 kHz)
  • SharedTypes.h — Shared memory binary protocol
  • Info.plist — CFPlugIn metadata

Swift Integration (FineTune/Audio/Loopback/)

  • LoopbackRingBuffer.swift — RT-safe shared memory writer
  • LoopbackDeviceManager.swift — Driver lifecycle, admin install/uninstall
  • ShmHelper.h — C wrapper for variadic shm_open

Modified Files

  • AudioEngine.swift — Loopback lifecycle, auto-enable for non-DAW apps
  • ProcessTapController.swift — Forks processed audio to ring buffer
  • ProcessTapControlling.swift — setLoopbackBuffer protocol method

Testing

  • Rekordbox → Ableton Live recording confirmed, clean signal
  • Volume at unity = bit-identical passthrough
  • Multiple apps running (only source app writes)
  • App restart cycle (shared memory cleanup works)

Future Improvements

  • UI toggle per-app for loopback routing
  • Multi-app mixing into ring buffer
  • Settings persistence for loopback preferences
  • Automatic sample rate matching with DAW

cpupanic added 3 commits May 25, 2026 22:55
Add a CoreAudio HAL plugin (FineTuneLoopback.driver) that creates a virtual
input device called 'FineTune Loopback'. This enables DAWs like Ableton Live
to record audio from any app that FineTune taps — lossless, 32-bit float,
with zero additional latency.

Architecture:
- FineTune app taps audio → processes (vol/EQ) → writes to POSIX shared memory
- HAL driver reads from shared memory → presents as virtual mic input to DAWs
- Lock-free SPSC ring buffer with atomic head counters (no locks on RT thread)

Components:
- FineTuneLoopback/: CoreAudio HAL plugin (C++, ~1200 LOC)
  - FTLoopbackDriver.cpp: Full AudioServerPlugInDriverInterface implementation
  - SharedTypes.h: Shared memory layout (binary protocol between app & driver)
  - Info.plist: CFPlugIn metadata for CoreAudio discovery
- FineTune/Audio/Loopback/:
  - LoopbackRingBuffer.swift: RT-safe shared memory writer (memcpy + atomics only)
  - LoopbackDeviceManager.swift: Driver lifecycle, install/uninstall, app tracking
  - ShmHelper.h: C wrapper for variadic shm_open (Swift interop)
- AudioEngine integration: auto-enables loopback for first non-DAW app
- ProcessTapController: forks processed audio to ring buffer after EQ/limiting

Safety:
- SPSC single-writer enforcement (one app at a time)
- DAW exclusion list prevents feedback loops
- Stale shared memory cleanup on restart (shm_unlink before create)
- RT-safe write path: no alloc, no locks, no ObjC, no logging
- Updated FTLoopbackDriver.h to support bidirectional audio streaming, allowing applications to output to and record from the virtual device.
- Changed default buffer size from 512 to 256 frames for improved performance.
- Updated Info.plist to reflect version change from 1.0 to 2.0.
- Modified SharedTypes.h to align default buffer frames and sample rate with driver settings, and added a new field for tracking the most recent write time.
- Introduced diagnose_audio.sh script for real-time monitoring of audio issues, capturing relevant log messages for troubleshooting.
- Introduced `AudioDebugView` for real-time audio routing diagnostics, displaying app tap status, device routing, audio levels, and loopback state.
- Enhanced `ProcessTapControlling` protocol with `isUnmutedCapture`, `ioStats`, and `primaryAggregateDeviceID` properties.
- Implemented `BufferStats` in `LoopbackRingBuffer` for diagnostics on buffer state, including fill level, overruns, and underruns.
- Added debug button to `MenuBarPopupView` to open the audio debug panel.
- Integrated loopback toggle functionality in `AppRow`, `AppRowControls`, and related views, allowing users to enable/disable loopback routing.
- Updated UI components to reflect loopback availability and status, ensuring a cohesive user experience.
@EllandeVED

Copy link
Copy Markdown

Wouldn't making the app use an audio driver be a bit scary for the common users? Like maybe an expert mode you can toggle which downloads the driver and allows greater customization?
Idk... You seem to know much more than me

@alexlanderzander

Copy link
Copy Markdown
Author

i found this interesting for my own personal use since blackhole was not working that well for me. So i am also fine with it just being a branch or fork

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.

3 participants