Audio routing for digital modes on Mac, Linux, and Windows.
FT8, FT4, JS8, RTTY, and PSK all need the same plumbing: get the radio's receive audio into WSJT-X (or JS8Call, or FLDIGI), and get the app's transmit audio back to the radio. On every desktop OS that means a software audio "cable" — and each OS does it a different way. This guide is the honest, platform-by-platform reference.
TL;DR
Audio routing for digital modes means moving RX audio from the radio into a digital-modes app (typically WSJT-X, JS8Call, or FLDIGI), and moving the app's TX audio back to the radio. On macOS, RigPlane Pro bundles the BlackHole 2ch installer and you click "Install" once. On Linux, RigPlane Pro auto-provisions a PipeWire pw-loopback pair on modern distros, with a PulseAudio module-null-sink fallback for legacy setups. On Windows, you install VB-Cable from VB-Audio manually — RigPlane Pro does not bundle it today — and then RigPlane and your digital-mode app share it as a normal soundcard. After that, the WSJT-X settings are identical across platforms: pick the loopback device as input and output, point Hamlib NET rigctl at localhost:4532, set TX audio level for clean ALC, and you are decoding.
What is actually happening
WSJT-X, JS8Call, and FLDIGI were designed for the old soundcard-interface world: a USB audio dongle (SignaLink, RIGblaster, the radio's built-in USB codec) appears as a soundcard, and the digital-modes app records from it and plays back into it. For an IP-connected setup — Icom IC-7610 LAN, IC-705 over Wi-Fi, anything where the radio audio arrives over the network rather than as a literal soundcard — there is no USB sound device for the digital-modes app to find. So we synthesize one in software. The operating system needs a virtual "loopback" device that has both an input side and an output side, wired internally. RigPlane plays the radio's receive audio into the loopback's input; WSJT-X reads from the loopback's output and decodes. On TX, WSJT-X writes its outgoing tones to the loopback's input; RigPlane reads from the loopback's output and ships the PCM out to the radio. The loopback is the only piece of plumbing that has to exist; everything else — Hamlib over TCP for PTT and frequency, mode selection, ALC levels — is the same as a conventional soundcard interface.
The reason this guide exists is that every desktop OS solves the "virtual loopback device" problem with a different component, and the install story is different in each case. Linux and macOS make this fairly painless if you let RigPlane Pro handle it; Windows still requires one manual install step today.
On macOS — BlackHole
macOS has no built-in virtual audio device, so the community standard is BlackHole from Existential Audio — a free, open-source virtual audio driver that registers a 2-channel input/output pair (BlackHole 2ch) with Core Audio. WSJT-X sees it like any other soundcard.
RigPlane Pro bundles the BlackHole 2ch installer on macOS. The Pro .dmg ships the signed BlackHole2ch-v*.pkg inside the app, and the Settings → Audio screen has an "Install BlackHole 2ch" button that runs the installer with a single admin prompt. After install, restart RigPlane Pro so Core Audio re-enumerates devices, pick BlackHole 2ch as the bridge target in Settings → Audio, and you are done.
If you prefer to install BlackHole yourself — for example because you already have it via Homebrew (brew install blackhole-2ch) or downloaded the package directly from Existential Audio — RigPlane will detect the existing install and skip the bundled prompt. Either route lands on the same configuration: BlackHole 2ch shows up as a soundcard, RigPlane Pro routes through it, and WSJT-X selects it for both Input and Output.
One subtle macOS-specific tip: BlackHole is a one-way virtual cable per channel pair. If you want to monitor the received audio in your headphones while WSJT-X is decoding from BlackHole, create a Multi-Output Device in Audio MIDI Setup.app that contains both BlackHole 2ch and your normal speakers/headphones, and point RigPlane's RX output at that multi-output device. WSJT-X still reads from BlackHole 2ch directly; the multi-output just duplicates the audio so you can hear it.
On Linux — PipeWire (preferred) or PulseAudio
Linux audio is in the middle of a generational transition from PulseAudio to PipeWire, with ALSA still living underneath both. RigPlane Pro targets that stack honestly: the audio bridge first tries to provision a PipeWire pw-loopback pair, and falls back to a PulseAudio module-null-sink when PipeWire is not the active sound server. Both run entirely in userspace — no kernel modules, no root.
PipeWire (modern: Fedora 34+, Ubuntu 22.10+, Debian 12+, Arch). RigPlane Pro launches a pw-loopback child process with sink and source nodes named icom_bridge_sink / icom_bridge_source. The nodes exist for the lifetime of the process, so cleanup is automatic on exit. WSJT-X (or any PortAudio-based app) sees the source and sink as regular ALSA-style devices via the PipeWire pulse and ALSA shims, and selects them like any other soundcard.
PulseAudio fallback. On systems still running PulseAudio (or PipeWire's pipewire-pulse shim without pw-loopback available), RigPlane Pro runs pactl load-module module-null-sink with a stable sink name, then unloads the module on shutdown. The sink's .monitor source is what WSJT-X reads from. This is the same approach hams have used manually for years; the Pro app just spares you the pactl incantations and the cleanup discipline.
If you want to wire things by hand, the manual two-terminal workflow still works — pw-loopback directly, or pactl load-module module-null-sink sink_name=icom_bridge_sink — and RigPlane will detect and reuse an already-loaded sink with the matching name instead of trying to create a duplicate.
On Linux — ALSA fallback (snd-aloop)
For headless boxes, embedded targets, or minimal installs that have neither PipeWire nor PulseAudio, the kernel's snd-aloop ALSA loopback module is the bare-metal option. The open-core rigplane Python library acknowledges snd-aloop as a documented loopback target alongside PipeWire and PulseAudio. The Pro desktop app is built for normal desktop sessions and does not auto-provision snd-aloop, so this path is manual:
- Load the module:
sudo modprobe snd-aloop(add to/etc/modules-load.d/to make it persistent). - The kernel exposes a pair of ALSA devices, typically
hw:Loopback,0andhw:Loopback,1, that are wired together. - Point RigPlane's audio bridge at one side; configure WSJT-X to use the other side as its input/output.
This is the same loopback technique used in Raspberry Pi all-in-one digital-mode setups. It is bulletproof but coarse — sample-rate negotiation is rigid, and you do not get the per-app routing that PipeWire enables — so prefer PipeWire or PulseAudio whenever they are available.
On Windows — VB-Cable
On Windows today, the documented loopback bridge for RigPlane is VB-Cable from VB-Audio Software. It is the same component WSJT-X, JTDX, JS8Call, and most established Windows ham workflows already use, so if you have been doing FT8 on Windows for a while you almost certainly have it installed already. RigPlane Pro does not bundle VB-Cable. The Windows installer will not place a virtual cable on your system automatically; you install VB-Cable yourself from the VB-Audio site, then point RigPlane at it.
Install steps:
- Download VB-Cable from vb-audio.com/Cable/. VB-Cable is donationware; the basic 1-cable version is the one most digital-mode setups use.
- Unzip, right-click
VBCABLE_Setup_x64.exe, run as administrator. Reboot when prompted — VB-Cable is a driver and Windows wants the reboot. - After reboot, open Windows Sound settings. You will see CABLE Input (VB-Audio Virtual Cable) as a playback device and CABLE Output (VB-Audio Virtual Cable) as a recording device. These two are wired together inside the driver — anything played to CABLE Input is readable from CABLE Output.
- Open RigPlane Pro. The first-run readiness check detects whether VB-Cable is installed; once it is, set RigPlane's audio bridge to play RX into CABLE Input and read TX from CABLE Output (or the reverse, depending on which side you assign to the radio vs. the digital-modes app).
Future Windows builds plan to bundle a loopback driver automatically, the way the macOS build already bundles BlackHole. That is roadmap, not present-tense; today, the VB-Cable install is a one-time manual step.
BlackHole is a trademark of Existential Audio. VB-Cable and VB-Audio Virtual Cable are trademarks of VB-Audio Software. RigPlane is independent of, and not endorsed by, either project; this guide links to their canonical sites and recommends them as the standard tooling on their respective platforms.
Configuring WSJT-X, JS8Call, and FLDIGI to use the loopback
Once the loopback device exists, the digital-modes app configuration is almost identical across platforms. The only thing that changes is the device name. Concrete steps for WSJT-X (the other apps follow the same pattern in their own UIs):
- File → Settings → Audio. Set Input and Output to the loopback device:
- macOS:
BlackHole 2chon both sides. - Linux:
icom_bridge_sourcefor input andicom_bridge_sinkfor output (PipeWire), or the equivalentmonitor of icom_bridge_sinksource under PulseAudio. - Windows:
CABLE Output (VB-Audio Virtual Cable)as input,CABLE Input (VB-Audio Virtual Cable)as output. (Yes — VB-Cable's naming is backwards from how you would read it. CABLE Input is where you write; CABLE Output is where you read.)
- macOS:
- File → Settings → Radio. Set Rig to
Hamlib NET rigctl, Network Server tolocalhost:4532(the standard rigctld port), and PTT method toCAT. RigPlane exposes a rigctld-compatible server so WSJT-X can ask for frequency, mode, and PTT over a TCP socket exactly the way Hamlib expects. JS8Call and FLDIGI use the same Hamlib NET rigctl integration with the same settings. - Mode. Set the radio mode to
PKTUSB(orDATA-U, or whatever your radio calls "USB with data audio routed to the rear audio jack instead of the mic"). For Icom radios with LAN audio, the route policy in RigPlane already steers the digital audio path to DATA2/LAN without changing DATA1's modulation input. - Test decode. Tune to an active FT8 band (14.074 MHz is the easiest sanity check during daylight). You should see a green waterfall in WSJT-X with decode lines appearing every 15 seconds. If you see a flat black waterfall, the input side of the loopback is wrong; if you see a red overload bar, the input is too hot — see "Levels and PTT" below.
For per-radio configuration walk-throughs, the rigplane.dev docs cover the IC-7610, IC-7300, IC-705, and IC-9700 in detail, including the WSJT-X-specific notes in guide/wsjtx-setup and the full PCM/Opus contract details in the audio recipes reference.
Levels and PTT
Audio level matters more on TX than on RX. WSJT-X's TX level is set in File → Settings → Audio → Pwr as a slider; the right value depends on your radio's audio chain and how you have RigPlane configured. The honest version of the advice is: start low, watch ALC, and bring it up until ALC just starts to move. If ALC is pumping (the bar bouncing into the red on every transmission), the audio is clipping in the radio's modulator and your transmitted signal is splattering across neighboring frequencies. Operators with ALC running flat to the right are the operators other hams quietly mute.
On the RX side, set the loopback / radio output level so WSJT-X's input meter sits in the recommended 30–60 dB band. Too low and weak FT8 signals will not decode; too high and intermodulation in the decoder's internal AGC eats real signals. RigPlane Pro's audio bridge does not apply RX gain on top of the radio's own audio output — what the radio sends is what WSJT-X sees — so the adjustment is usually on the radio's USB-audio or LAN-audio output level setting, not in RigPlane.
PTT goes over the same Hamlib NET rigctl connection (localhost:4532) rather than VOX or a separate serial line. Keep VOX off on the radio for digital modes — VOX-triggered PTT loses the first syllable of every transmission, which on FT8 means the leading symbol of the 13-character message gets clipped.
Troubleshooting
Top five issues operators hit when wiring up digital-mode audio, in roughly the order they happen:
- No decodes; flat waterfall. The loopback's input side is not getting RX audio. Verify in RigPlane that the bridge is started and the output device is the loopback (BlackHole 2ch,
icom_bridge_sink, or CABLE Input). On macOS, BlackHole devices sometimes do not appear until you restart the app that needs them; quit WSJT-X and reopen. - ALC pumping on TX. TX audio level is too high. Drop WSJT-X's Pwr slider to roughly half, transmit a short signal (the "Tune" button generates a continuous tone), and adjust until ALC just barely moves. If ALC is still pegged at the lowest WSJT-X setting, the radio's USB / LAN audio input gain is too high — turn that down in the radio menus before adjusting the app.
- Wrong device picked. Windows is the worst offender here, with two CABLE devices that are easy to mix up. Remember: CABLE Input is a playback device (you write to it); CABLE Output is a recording device (you read from it). On Linux, if you started RigPlane after WSJT-X, WSJT-X will not see the new loopback until you reopen its Settings → Audio panel.
- Sample-rate mismatch. Most loopback bridges run at 48 kHz, which matches WSJT-X's expectations. If you have manually overridden
ICOM_AUDIO_SAMPLE_RATE(for example to 16 kHz over a constrained VPN), expect WSJT-X to resample, and expect a small amount of decode degradation. Reset to 48 kHz when troubleshooting. - Latency / jitter. FT8 is tolerant of a few hundred milliseconds of latency — it only matters that the audio gets there inside the 15-second slot. If you are on a slow link (cellular tether, distant VPN), you will hear audible breakup during heavy band activity but FT8 will usually still decode. CW operation over the same path is much less forgiving; for CW use the open-core
rigplanelibrary's CW console rather than relying on the audio path.
Where this fits
The platform-specific framing on this page lines up with the rest of the site: the Mac landing page documents the BlackHole-bundled story, the Linux landing page covers the PipeWire / PulseAudio auto-provision flow, the Raspberry Pi page covers the Pi-specific audio constraints, and the Windows landing page is honest that VB-Cable is a manual install today. If you came here from a per-radio page like IC-7610, the audio routing here is the missing piece that turns "RigPlane controls the radio" into "WSJT-X decodes FT8 through RigPlane." If you are comparing options before committing, the vs wfview page covers the broader software-choice tradeoffs, and the FAQ covers the most common questions about what RigPlane does and does not do today.
What to do next
Last reviewed 2026-05-19.