-
-
Notifications
You must be signed in to change notification settings - Fork 107
BNR GPU Noise Removal
AetherSDR v0.7.6 introduces NVIDIA Maxine BNR (Background Noise Removal) — the world's first GPU-accelerated AI noise removal in an SDR client. BNR uses a deep neural network running on your NVIDIA RTX GPU to remove background noise from received audio in real time.
Radio audio (24kHz stereo) → Upsample to 48kHz mono → gRPC to GPU container
→ Neural denoising (TensorRT) → gRPC back → Downsample to 24kHz stereo → Speakers
BNR runs inside a self-hosted Docker container on your local machine. AetherSDR sends audio chunks to the container via gRPC, the GPU processes them through the neural network, and denoised audio comes back — all in about 15ms.
| Requirement | Details |
|---|---|
| GPU | NVIDIA RTX 4000+ series (Ada Lovelace or Blackwell) |
| VRAM | ~1.1 GB used by the model |
| Docker | Docker Engine with NVIDIA Container Toolkit |
| NGC Account | Free NVIDIA NGC account for API key |
| Disk Space | ~8 GB for the container image |
| Build Flag | AetherSDR built with -DENABLE_BNR=ON
|
Note: RTX 2000/3000 series GPUs are NOT supported by the Maxine BNR container.
- Go to https://build.nvidia.com
- Click Sign In → Create Account (or sign in with an existing NVIDIA account)
- Complete registration — free tier is sufficient
- Go to https://org.ngc.nvidia.com/setup/api-key
- Click Generate API Key
- Copy the key and save it securely — you'll need it for Docker login
Optional: store it in your shell profile for convenience:
echo 'export NGC_API_KEY="your-key-here"' >> ~/.bashrc
source ~/.bashrcArch Linux:
sudo pacman -S docker
sudo systemctl enable --now docker
sudo usermod -aG docker $USERUbuntu/Debian:
sudo apt install docker.io
sudo systemctl enable --now docker
sudo usermod -aG docker $USERLog out and back in (or run newgrp docker) for the group change to take effect.
Arch Linux (AUR):
yay -S nvidia-container-toolkitUbuntu/Debian:
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt update && sudo apt install nvidia-container-toolkitConfigure the Docker runtime:
sudo nvidia-ctk runtime configure --runtime=docker
sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml
sudo systemctl restart dockerVerify GPU access in Docker:
docker run --rm --gpus all nvidia/cuda:12.8.0-base-ubuntu24.04 nvidia-smiYou should see your GPU listed. If you get "unable to get number of CUDA devices", re-run the nvidia-ctk cdi generate command and restart Docker.
# Login to NGC registry
docker login nvcr.io
# Username: $oauthtoken (literally type this)
# Password: <paste your NGC API key>
# Pull and run the container (STREAMING MODE — required for real-time audio)
docker run -d \
--runtime=nvidia \
-e NVIDIA_VISIBLE_DEVICES=all \
--shm-size=256m \
-p 8001:8001 -p 8000:8000 \
-e NGC_API_KEY=$NGC_API_KEY \
-e MODEL_TYPE=v1-48k \
-e STREAMING=true \
--restart unless-stopped \
--name maxine-bnr \
nvcr.io/nim/nvidia/maxine-bnr:latest \
bash -c 'sed -i "s/^#if/if/;s/^#then/then/;s|^#/opt/maxine/grpc-streaming|/opt/maxine/grpc-streaming|;s/^#else/else/" /opt/maxine/grpc/run_grpc_service.sh && exec start_server'Critical: Streaming vs Transactional mode. The Maxine BNR container (v1.6.1) ships with two gRPC services:
Path Mode Description /opt/maxine/grpc/Transactional (batch) Accumulates all audio to a file, runs inference, returns result. NOT compatible with real-time use. /opt/maxine/grpc-streaming/Streaming (real-time) Processes each 10ms chunk through Triton and returns denoised audio immediately. Required by AetherSDR. The container's startup script has a
STREAMINGenvironment variable check that selects between them, but it is commented out in the current image. Thebash -c 'sed ...'entrypoint override uncomments the check so-e STREAMING=trueactivates the streaming service.If you omit the entrypoint override, the container will always run the transactional service and BNR will silently fail — the client connects and sends audio, but never receives denoised audio back.
The first run downloads the model (~1-2 GB). Subsequent starts use the cached model and boot in ~2 seconds.
Wait for the server to be ready:
docker logs -f maxine-bnrLook for:
Maxine GRPC Service: Listening to 0.0.0.0:8001
Verify the streaming service is running (not the transactional one):
docker exec maxine-bnr ps aux | grep bnr_serviceYou should see /opt/maxine/grpc-streaming/bnr_service.py. If you see /opt/maxine/grpc/bnr_service.py instead, the container is running in transactional mode — delete it and recreate with the command above.
The --restart unless-stopped flag means the container automatically starts when Docker starts (on boot). You only need to run the docker run command once.
BNR requires gRPC and protobuf development libraries:
Arch Linux:
sudo pacman -S grpcUbuntu/Debian:
sudo apt install libgrpc++-dev protobuf-compiler-grpcBuild with BNR enabled:
cd ~/build/AetherSDR
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_BNR=ON
cmake --build build -j$(nproc)BNR is an optional build flag (
-DENABLE_BNR=ON). Without it, AetherSDR builds normally with no gRPC dependency. The BNR button will be hidden in the UI.
- Verify the container is running — Radio Setup → Audio → NVIDIA BNR panel should show a green dot and "Running"
- Click BNR in the VFO DSP tab or the spectrum overlay DSP panel
- Adjust intensity — the slider next to the BNR button in the overlay DSP panel controls denoising strength (0 = off, 100 = maximum)
BNR is mutually exclusive with NR2 and RN2 — enabling BNR automatically disables the other two.
| Control | Function |
|---|---|
| Autostart Container | When enabled, AetherSDR runs docker start maxine-bnr on launch |
| Container | Name of the Docker container (default: maxine-bnr) |
| Check Status | Queries Docker for container state |
| Start | Starts the container (docker start) |
| Stop | Stops the container (docker stop) |
| Status indicator | Green = running, Yellow = stopped, Red = not found |
# Check status
docker ps --filter name=maxine-bnr
# Start
docker start maxine-bnr
# Stop
docker stop maxine-bnr
# View logs
docker logs -f maxine-bnr
# Verify streaming mode
docker exec maxine-bnr ps aux | grep bnr_service
# Should show: /opt/maxine/grpc-streaming/bnr_service.py
# Remove and recreate (e.g., after GPU driver update)
docker rm -f maxine-bnr
# Re-run the full docker run command from Step 5 (with the streaming entrypoint override)After initial setup, the workflow is:
- Boot your PC — Docker and the BNR container start automatically
-
Launch AetherSDR — autostart sends
docker startas a safety net - Click BNR when you want noise removal
- Adjust the intensity slider to taste
No NGC key, no Docker commands, no model downloads — just click and listen.
| Metric | Value |
|---|---|
| Added latency | ~15ms (10ms chunk + gRPC round-trip + resampling) |
| GPU utilization | ~5% on RTX 4090 |
| GPU memory | ~1.1 GB |
| CPU overhead | Minimal (resampling + format conversion) |
| Priming time | ~50ms (first enable, then smooth) |
| Feature | NR2 (Spectral) | RN2 (RNNoise) | BNR (NVIDIA GPU) |
|---|---|---|---|
| Algorithm | Ephraim-Malah MMSE-LSA | Recurrent Neural Network | Large-scale Neural Network (TensorRT) |
| Runs on | CPU (in-process) | CPU (in-process) | GPU (Docker container) |
| GPU required | No | No | RTX 4000+ |
| Added latency | ~10ms | ~10ms | ~15ms |
| Dependencies | FFTW3 (optional) | Bundled | grpc++, Docker, NVIDIA GPU |
| Quality | Good (classical spectral) | Very good (neural) | Excellent (large-scale neural, GPU-optimized) |
| Setup | None | None | Docker + NGC key (one-time) |
| Adjustable | No | No | Yes (intensity 0–100%) |
The container doesn't exist. Run the docker run command from Step 5 to create it.
The gRPC server inside the container may still be loading the model. Wait 5-10 seconds after container start, then try again. AetherSDR will retry automatically up to 5 times (2 seconds apart).
Most likely cause: the container is running the transactional (batch) service instead of the streaming service.
Verify which service is running:
docker exec maxine-bnr ps aux | grep bnr_service-
/opt/maxine/grpc/bnr_service.py— wrong (transactional mode, batch processing) -
/opt/maxine/grpc-streaming/bnr_service.py— correct (streaming mode, real-time)
The transactional service accumulates all audio into a file before running inference. Since AetherSDR streams audio indefinitely, inference never starts and no denoised audio is returned.
To fix, delete the container and recreate it with the streaming entrypoint override from Step 5:
docker rm -f maxine-bnr
# Re-run the full docker run command from Step 5The Maxine BNR container (v1.6.1) has the streaming mode selector commented out in its startup script. The sed command in the Step 5 docker run uncomments it. If the container was created without this override (e.g., from a plain docker run without the bash -c entrypoint), it will always use the transactional service.
The container can't access the GPU. This is usually caused by using --gpus all instead of --runtime=nvidia, or after a driver update. Fix:
sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml
sudo systemctl restart docker
docker rm -f maxine-bnr
# Re-run the docker run command from Step 5 (must use --runtime=nvidia)Important: The container must be created with --runtime=nvidia, not --gpus all. On some systems with newer NVIDIA drivers (595+), --gpus all does not properly pass GPU access to the container. If you created the container with --gpus all, delete it and recreate with the command from Step 5.
The Triton inference server needs shared memory for its Python backend. Fix by recreating the container with --shm-size=256m (included in the Step 5 command).
This was fixed in v0.7.6 with the jitter buffer. If you still experience it, check docker logs maxine-bnr for errors — the model may have failed to load.
AetherSDR was built without -DENABLE_BNR=ON. Rebuild with the flag enabled.
Check docker logs maxine-bnr — likely a GPU access issue. See the "unable to get number of CUDA devices" fix above.
- Panadapter Controls
- VFO Widget
- RX Controls
- TX Controls
- Aetherial Audio
- Multi-Slice Operation
- Diversity and ESC
- TNF (Tracking Notch Filters)
- Memory Channels
- Profile Management
- Slice Colors
- XVTR (Transverters)
- CWX Panel
- CW Decoder
- DVK Panel
- RTTY Operation
- RADE Digital Voice
- DAX Virtual Audio
- DAX IQ Streaming
- WSJT-X Integration
- CAT Control
- TCI Server