Skip to content

BNR GPU Noise Removal

Jeremy Fielder edited this page Mar 28, 2026 · 3 revisions

BNR — GPU-Accelerated AI 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.

How It Works

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.

Requirements

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.

Step-by-Step Setup

1. Create an NVIDIA NGC Account

  1. Go to https://build.nvidia.com
  2. Click Sign InCreate Account (or sign in with an existing NVIDIA account)
  3. Complete registration — free tier is sufficient

2. Generate an NGC API Key

  1. Go to https://org.ngc.nvidia.com/setup/api-key
  2. Click Generate API Key
  3. 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 ~/.bashrc

3. Install Docker

Arch Linux:

sudo pacman -S docker
sudo systemctl enable --now docker
sudo usermod -aG docker $USER

Ubuntu/Debian:

sudo apt install docker.io
sudo systemctl enable --now docker
sudo usermod -aG docker $USER

Log out and back in (or run newgrp docker) for the group change to take effect.

4. Install NVIDIA Container Toolkit

Arch Linux (AUR):

yay -S nvidia-container-toolkit

Ubuntu/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-toolkit

Configure the Docker runtime:

sudo nvidia-ctk runtime configure --runtime=docker
sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml
sudo systemctl restart docker

Verify GPU access in Docker:

docker run --rm --gpus all nvidia/cuda:12.8.0-base-ubuntu24.04 nvidia-smi

You 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.

5. Pull and Run the BNR Container

# 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 STREAMING environment variable check that selects between them, but it is commented out in the current image. The bash -c 'sed ...' entrypoint override uncomments the check so -e STREAMING=true activates 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-bnr

Look 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_service

You 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.

6. Build AetherSDR with BNR Support

BNR requires gRPC and protobuf development libraries:

Arch Linux:

sudo pacman -S grpc

Ubuntu/Debian:

sudo apt install libgrpc++-dev protobuf-compiler-grpc

Build 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.

7. Enable BNR in AetherSDR

  1. Verify the container is running — Radio Setup → Audio → NVIDIA BNR panel should show a green dot and "Running"
  2. Click BNR in the VFO DSP tab or the spectrum overlay DSP panel
  3. 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.

Container Management

Radio Setup → Audio → NVIDIA BNR Panel

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

Manual Container Management

# 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)

Daily Use

After initial setup, the workflow is:

  1. Boot your PC — Docker and the BNR container start automatically
  2. Launch AetherSDR — autostart sends docker start as a safety net
  3. Click BNR when you want noise removal
  4. Adjust the intensity slider to taste

No NGC key, no Docker commands, no model downloads — just click and listen.

Performance

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)

Comparison with Other DSP Modes

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%)

Troubleshooting

"Not found" in Radio Setup

The container doesn't exist. Run the docker run command from Step 5 to create it.

Container shows "Running" but BNR won't connect

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).

BNR connects but no denoised audio (silence)

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.pywrong (transactional mode, batch processing)
  • /opt/maxine/grpc-streaming/bnr_service.pycorrect (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 5

The 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.

"unable to get number of CUDA devices" in container logs

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.

"No space left on device" / shared memory errors

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).

Choppy audio with BNR enabled

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.

BNR button not visible

AetherSDR was built without -DENABLE_BNR=ON. Rebuild with the flag enabled.

Container keeps restarting

Check docker logs maxine-bnr — likely a GPU access issue. See the "unable to get number of CUDA devices" fix above.

Clone this wiki locally