# OPLabs Mixer Engine — Standalone Daemon

C++ standalone audio mixer daemon, extracted from the op-pedal mixer-engine branch. JACK audio I/O with Unix socket JSON control.

## Architecture

```
JACK Ports → MixerEngine::process() → JACK Ports
                  ↕
         MixerControlServer (Unix socket)
                  ↕
         FastAPI bridge (future) / socat / nc
                  ↕
         React Mixer Console (browser)
```

### Processing Pipeline (per audio cycle)

1. Clear all bus buffers
2. For each channel: apply HPF → volume/pan → accumulate to routed buses
3. Process aux sends (pre/post fader)
4. Route buses to buses according to routing matrix
5. Process each bus (apply volume, compute VU)
6. Write to physical outputs per output routing table

## Dependencies

- **JACK** (libjack-jackd2-dev on Debian, jack-audio-connection-kit-devel on Fedora)
- **CMake** >= 3.16
- **C++17** compiler
- **nlohmann/json** (auto-fetched by CMake)

## Build

```bash
git clone <repo-url> oplabs-mixer-daemon
cd oplabs-mixer-daemon
mkdir build && cd build
cmake ..
make -j$(nproc)
```

## Run

```bash
# Start JACK first
jackd -d alsa -r 48000 -p 256 -n 3 &

# Run the daemon (auto-connects to JACK)
./mixer-daemon

# With custom config
./mixer-daemon --inputs 4 --outputs 2 --buffer-size 128
```

### Command-line Options

| Option | Default | Description |
|--------|---------|-------------|
| `--socket <path>` | `/tmp/mixer-daemon.sock` | Unix socket path |
| `--inputs <N>` | 2 | Number of JACK input channels |
| `--outputs <N>` | 2 | Number of JACK output channels |
| `--sample-rate <N>` | 48000 | Audio sample rate (overridden by JACK) |
| `--buffer-size <N>` | 256 | Audio buffer size in frames (overridden by JACK) |
| `--help` | | Show help |

### Headless Mode

If JACK is not running, the daemon starts in headless mode — no audio I/O, but the control socket is active for testing.

## Control Protocol

The daemon listens on a Unix domain socket. Send one JSON command per line, receive one JSON response per line.

```bash
# Get full mixer state
echo '{"cmd":"getState"}' | nc -U /tmp/mixer-daemon.sock

# Set channel volume
echo '{"cmd":"setChannelVolume","channel":0,"volume":-6.0}' | nc -U /tmp/mixer-daemon.sock

# Get VU levels
echo '{"cmd":"getVU"}' | nc -U /tmp/mixer-daemon.sock

# Auto-create channels
echo '{"cmd":"autoCreateChannels","inputs":4,"outputs":2}' | nc -U /tmp/mixer-daemon.sock
```

### Commands

| Command | Parameters | Description |
|---------|------------|-------------|
| `getState` | — | Full mixer state as JSON |
| `getVU` | — | VU levels per channel and bus |
| `setChannelVolume` | `channel`, `volume` | Set channel fader (-96..+12 dB) |
| `setChannelPan` | `channel`, `pan` | Set pan (-1.0 left to 1.0 right) |
| `setChannelMute` | `channel`, `mute` | Mute toggle |
| `setChannelSolo` | `channel`, `solo` | Solo toggle |
| `setChannelLabel` | `channel`, `label` | Set channel name |
| `setBusVolume` | `busId`, `volume` | Set bus fader (-96..+12 dB) |
| `setBusMute` | `busId`, `mute` | Bus mute toggle |
| `routeChannelToBus` | `channel`, `busId`, `level` | Route channel to bus |
| `routeBusToBus` | `sourceBusId`, `targetBusId`, `level` | Route bus to bus |
| `removeRoute` | `sourceId`, `targetBusId` | Remove a route |
| `autoCreateChannels` | `inputs`, `outputs` | Recreate all channels for N inputs |
| `addChannel` | `physicalInput` | Add a new channel strip |
| `removeChannel` | `channel` | Remove a channel strip |

## Run Tests

```bash
cd build && ctest
# or
./mixer-test
```

## Integration

The daemon is designed to sit behind a FastAPI Python bridge that translates HTTP/WebSocket to Unix socket commands. That bridge then serves the React Mixer Console UI.

## License

Copyright (c) 2026 Ourpad Network. See LICENSE file.
