Skip to main content

Implementing sox Noise Reduction and rnnoise Noise Reduction on RK3576

· 13 min read
Yuxuan
100askTeam yuxuan.

Overview

The development of audio noise reduction technology has evolved from combating physical noise to intelligent recognition and separation.

Analog Era (mid-20th century)

  • Dolby A (1965): A pioneering dynamic noise reduction technology that used the "companding" principle to reduce tape background noise.
  • Dolby B (1968): A consumer-simplified version of Dolby A, which brought cassette tapes into millions of households.
  • dbx (1971): A more aggressive companding system with a larger dynamic range.
  • Subsequent developments: More advanced analog systems such as Dolby C and SR followed.

Early Digital Era (1980s-1990s)

  • The emergence of digital signal processing chips made real-time digital filtering and spectral subtraction possible
  • Algorithms began shifting from time-domain to frequency-domain processing
  • Adaptive filtering theory matured and was applied in communications

Digital Algorithm Popularization (1990s-2010s)

  • Improvements in personal computer performance and the popularization of professional audio software (such as Audition and iZotope RX) made digital noise reduction tools widely accessible
  • The application of psychoacoustic models improved the sound quality of noise reduction
  • Active noise canceling headphones began to be commercialized (driven by manufacturers such as Bose)

Artificial Intelligence Era (2010s to present)

  • Deep learning has completely transformed noise reduction, enabling it to handle complex non-stationary noise
  • The technology is widely applied in fields such as video conferencing, voice assistants, and music streaming
  • Research directions have expanded from simple noise reduction to refined tasks such as speech separation and vocal extraction

Main Noise Reduction Methods

Spectrum-based Noise Reduction The core idea is to distinguish between noise and signal in the frequency domain:

  • Spectral subtraction: Subtract the noise spectrum from the audio
  • Wiener filtering: A better statistical noise reduction method
  • Masking effect method: Leverages human ear characteristics to preserve sound quality

Machine Learning Noise Reduction

  • Uses deep learning models (RNN, CNN, Transformer, etc.) to learn noise reduction from data
  • Can effectively handle complex scenarios and non-stationary noise
  • Supports end-to-end waveform or spectrum processing

Filtering Noise Reduction

  • Adaptive filtering: Requires a reference noise signal, used in telephony and active noise canceling headphones
  • Fixed filtering: Removes noise at specific frequencies, such as 50Hz power-line interference

Multi-microphone Technology

  • Forms a directional beam through a microphone array
  • Enhances sound from the target direction and suppresses ambient noise
  • Common in phones, conferencing equipment, and smart speakers

Traditional Processing Methods

  • Noise gate: Mutes low-level signals via a threshold
  • Simple and effective, commonly used in music production and live streaming

The following uses two methods for audio noise reduction: sox noise reduction and rnnoise noise reduction.

sox Noise Reduction

sox's noisered is a classic, non-AI noise reduction tool based on noise sampling and spectral subtraction. Its principle is intuitive and relatively simple to implement, and it is remarkably effective on stationary noise (such as fan noise, air conditioner noise, and constant current noise). The noisered effect is the core of its noise reduction. The core principle steps are as follows:

sox
  1. Analysis/Training phase: The core is building a noise fingerprint. SoX needs to first "learn" what the noise looks like. You can provide a pure noise segment (such as ambient background noise recorded before the actual recording), or let it automatically detect the low-energy "silent" portions of the audio. It analyzes these segments, computes an average noise spectrum, and saves it as a .prof file. This file is the reference baseline for subsequent noise reduction.
  2. Noise Reduction Processing phase: The core is spectral subtraction.
    • Framing and Transform: The continuous audio signal is sliced into short-time overlapping frames and converted to the frequency domain via FFT. In the frequency domain, the signal is represented as energy (amplitude) and phase at different frequencies.
    • Key Operation - Spectral Subtraction: This is the most critical step. The algorithm compares the spectrum of the current frame with the previously learned noise sample spectrum. The basic idea is very simple: clean signal spectrum ≈ noisy signal spectrum - noise spectrum.
      • Energy Subtraction: The main operation is subtraction on the energy/amplitude spectrum. If the energy of a certain frequency in the current frame is lower than or close to the energy of the noise sample at that frequency, it will be heavily suppressed; if it is much higher, it will be preserved.
      • Phase Preservation: Phase information is critical for reconstructing the sound waveform. Spectral subtraction usually does not change the phase of the original signal; it directly synthesizes a new signal using the denoised amplitude spectrum and the original phase spectrum.
      • Suppression Factor: SoX's amount parameter (0.0 to 1.0) controls the strength of the subtraction. 0.5 means only half of the noise energy is subtracted, which is more conservative and reduces distortion.
    • Synthesis and Output: The processed frequency-domain data is converted back to a time-domain waveform via IFFT, and then the short-time frames are synthesized into a continuous audio signal through the overlap-add method, ultimately producing the denoised audio.

It looks complicated, but it is simple to operate. Now let's use the sox command to demonstrate and make it clear.

sox Command Noise Reduction

#noise.wav is the background noise, a 10s audio clip recorded in a quiet state
ls
noise.wav speech.wav
#Generate a noise profile (manually extract 5-10 seconds of pure noise)
sox noise.wav -n noiseprof noise.prof
#Noise reduction, 0.21 is an empirical value, the vast majority of material will not produce water sound
sox speech.wav noisered_speech.wav noisered noise.prof 0.21
#Compare playback, the effect is obviously noticeable
aplay noise.wav
Playing WAVE 'noise.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Stereo
aplay speech.wav
Playing WAVE 'speech.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Stereo
aplay noisered_speech.wav
Playing WAVE 'noisered_speech.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Stereo

Using only the sox command for noise reduction cannot be integrated into an embedded system. Next, we will use the C language with sox's library and API to perform audio noise reduction.

Using sox's Library and API for Audio Noise Reduction

The code structure is as follows:

(base) ubuntu@ubuntu-2204:~/baiwen/sox_noise_reduction$ tree -L 2
.
├── CMakeLists.txt
├── deps
│ ├── include
│ └── lib
├── include
│ ├── custom_effects.h
│ └── sox_noise_reduction.h
├── Makefile
└── src
├── custom_effects.c
├── main.c
└── sox_noise_reduction.c

5 directories, 7 files

Build

To build this demo, you need to set the toolchain in CMakeLists.txt

# Specify the cross compiler
set(CMAKE_C_COMPILER /home/ubuntu/rk3576_AI/buildroot/output/rockchip_rk3576/host/bin/aarch64-buildroot-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER /home/ubuntu/rk3576_AI/buildroot/output/rockchip_rk3576/host/bin/aarch64-buildroot-linux-gnu-g++)

# Set sysroot
set(CMAKE_SYSROOT /home/ubuntu/rk3576_AI/buildroot/output/rockchip_rk3576/staging)
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})

# Add link libraries
target_link_libraries(sox_noise_reduction
sox
)
#Build on ubuntu22.04
(base) ubuntu@ubuntu-2204:~/baiwen/sox_noise_reduction$ make
Configuring CMake...
-- The C compiler identification is GNU 11.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/ubuntu/baiwen/sox_noise_reduction/build
Building with 16 jobs...
make[1]: Entering directory '/home/ubuntu/baiwen/sox_noise_reduction/build'
make[2]: Entering directory '/home/ubuntu/baiwen/sox_noise_reduction/build'
make[3]: Entering directory '/home/ubuntu/baiwen/sox_noise_reduction/build'
make[3]: Leaving directory '/home/ubuntu/baiwen/sox_noise_reduction/build'
make[3]: Entering directory '/home/ubuntu/baiwen/sox_noise_reduction/build'
[ 75%] Building C object CMakeFiles/sox_noise_reduction.dir/src/sox_noise_reduction.c.o
[ 75%] Building C object CMakeFiles/sox_noise_reduction.dir/src/custom_effects.c.o
[ 75%] Building C object CMakeFiles/sox_noise_reduction.dir/src/main.c.o
[100%] Linking C executable sox_noise_reduction
make[3]: Leaving directory '/home/ubuntu/baiwen/sox_noise_reduction/build'
[100%] Built target sox_noise_reduction
make[2]: Leaving directory '/home/ubuntu/baiwen/sox_noise_reduction/build'
make[1]: Leaving directory '/home/ubuntu/baiwen/sox_noise_reduction/build'

#make push will push the sox_noise_reduction executable to buildroot's /develop via adb
(base) ubuntu@ubuntu-2204:~/baiwen/sox_noise_reduction$ make push
Running build/sox_noise_reduction...
build/sox_noise_reduction: 1 file pushed. 10.6 MB/s (23840 bytes in 0.002s)

Run

On the rk3576

root@rk3576-buildroot:/develop# ls
live_life.mp3 noise.wav sox_noise_reduction speech.wav

First, record a background noise clip noise.wav in a quiet environment, then speak a sentence into the microphone to record speech.wav

root@rk3576-buildroot:/develop# ./sox_noise_reduction
SoX audio noise reduction processing started
=======================
Noise file: noise.wav
Input file: speech.wav
Output file: noisered_output.wav
Noise reduction sensitivity: 0.21
-----------------------
Processing...
[1/2] Creating noise profile...
Creating noise profile from: noise.wav
Processing noise profile...
Noise profile created: /tmp/noise_profile_NFk1uN.prof
[2/2] Applying noise reduction...
Applying noise reduction to: speech.wav
Processing audio with noise reduction...
Noise reduction applied. Output: noisered_output.wav
Done!
Processing successful! Output file: noisered_output.wav
#Use aplay to play and compare
aplay noise.wav
aplay speech.wav
aplay noisered_output.wav

You can hear that noisered_output.wav is noticeably improved, but there is still some faint "musical noise". This is an inherent side effect of sox's spectral subtraction noise reduction. To completely remove it, you would need to design an additional Wiener filter effect plugin to further eliminate it.

The usage of sox_noise_reduction can be found in the -h help information

root@rk3576-buildroot:/develop# ./sox_noise_reduction -h
SoX audio noise reduction tool
====================

Usage: ./sox_noise_reduction [options]

Options:
-n file Noise sample file (default: noise.wav)
-i file Input speech file (default: speech.wav)
-o file Output file (default: noisered_output.wav)
-s value Noise reduction sensitivity 0.0-1.0 (default: 0.21)
-h Show this help information

Parameter description:
Sensitivity: 0.0 means strongest noise reduction (may damage speech), 1.0 means weakest noise reduction
Recommended value: 0.21 (empirical value, suitable for most audio material)

Usage examples:
./sox_noise_reduction # Use all default settings
./sox_noise_reduction -n mynoise.wav # Specify noise file
./sox_noise_reduction -i myspeech.wav # Specify input file
./sox_noise_reduction -s 0.3 # Adjust noise reduction strength
./sox_noise_reduction -o clean.wav # Specify output file

rnnoise Noise Reduction

RNNoise is an excellent open-source audio noise reduction tool, very suitable for scenarios that require entry-level learning, quick integration, and moderate performance.

  1. Technical Principle:
    • Combines traditional signal processing (spectral analysis) with deep learning (RNN neural network).
    • Input audio framing -> feature extraction (such as band energy, pitch) -> RNN predicts the gain mask for each band (VAD is also integrated within) -> outputs the denoised spectrum -> reconstructs the waveform.
  2. Lightweight Design:
    • The model is only about 86KB, suitable for embedded or real-time processing.
    • A single-core CPU can process in real time.

Advantages:

  • Open source and easy to use: Clear code, provides a C language API, easy to integrate into various projects.
  • Low latency: Frame processing latency is about 10ms (default frame length 20ms), suitable for real-time communication.
  • Strong compatibility: No third-party deep learning framework dependencies, pure C implementation.
  • Good speech preservation: While suppressing stationary noise (such as fan noise), it causes little damage to speech.

Limitations:

  • Not a general-purpose noise reduction: Mainly optimized for voice communication, limited effect on music and sudden noise (such as keyboard sounds).
  • Fixed parameters: The model is trained for general scenarios, difficult to customize for specific noise.
  • Residual "musical noise": In some scenarios, it may introduce residual noise similar to water ripples.
  • No support for high sampling rates: By default, only supports 48kHz/16kHz mono, music noise reduction requires adjustment.

Build

## Set the cross-compile toolchain path
export TOOLCHAIN_DIR="/home/ubuntu/rk3576_AI/buildroot/output/rockchip_rk3576/host/bin"
export CC="${TOOLCHAIN_DIR}/aarch64-buildroot-linux-gnu-gcc"
export CXX="${TOOLCHAIN_DIR}/aarch64-buildroot-linux-gnu-g++"
export AR="${TOOLCHAIN_DIR}/aarch64-buildroot-linux-gnu-ar"
export LD="${TOOLCHAIN_DIR}/aarch64-buildroot-linux-gnu-ld"
export RANLIB="${TOOLCHAIN_DIR}/aarch64-buildroot-linux-gnu-ranlib"
export STRIP="${TOOLCHAIN_DIR}/aarch64-buildroot-linux-gnu-strip"

# Set target architecture
export ARCH="aarch64"
export CROSS_COMPILE="aarch64-buildroot-linux-gnu-"

# Set sysroot (important!)
export SYSROOT="/home/ubuntu/rk3576_AI/buildroot/output/rockchip_rk3576/staging"
export CFLAGS="--sysroot=${SYSROOT} -O2"
export LDFLAGS="--sysroot=${SYSROOT}"

echo "Toolchain setup complete"
echo "CC = $CC"

# Clone the project and build
git clone https://github.com/xiph/rnnoise.git
cd rnnoise
./autogen.sh
./configure \
--host=aarch64-buildroot-linux-gnu \
--build=x86_64-pc-linux-gnu \
--prefix=$(pwd)/tmp \
--enable-static \
--enable-shared \
CFLAGS="--sysroot=${SYSROOT} -O2" \
LDFLAGS="--sysroot=${SYSROOT}" \
CC="${CC}" \
CXX="${CXX}" \
AR="${AR}" \
LD="${LD}"
#Build
make
#Install to ./tmp
make install
(base) ubuntu@ubuntu-2204:~/rnnoise$ tree -L 2 tmp
tmp
├── include
│ └── rnnoise.h
├── lib
│ ├── librnnoise.a
│ ├── librnnoise.la
│ ├── librnnoise.so -> librnnoise.so.0.4.1
│ ├── librnnoise.so.0 -> librnnoise.so.0.4.1
│ ├── librnnoise.so.0.4.1
│ └── pkgconfig
└── share
└── doc
(base) ubuntu@ubuntu-2204:~/rnnoise$ ls examples/
rnnoise_demo rnnoise_demo.c rnnoise_demo.o

The files in the ./tmp directory are the rnnoise headers and libraries needed for integration. The rnnoise_demo under examples is a reference implementation, and there is also a .c file for reference.

adb push examples/.libs/rnnoise_demo /usr/bin/rnnoise_demo
adb push tmp/lib/librnnoise.so* /usr/lib/

Now you can do a simple test on the development board.

Test

# First check the original WAV file information
soxi speech.wav
# If the sampling rate is not 48000, first convert it to 48000
sox speech.wav -r 48000 speech_48k.wav
# Adjust the input volume to a suitable range (-3dB to -6dB)
# RNNoise requires: 48000Hz, mono, 16-bit signed integer PCM
sox speech_48k.wav -r 48000 -c 1 -e signed-integer -b 16 -t raw speech.pcm gain -n -3
# Run RNNoise noise reduction
rnnoise_demo speech.pcm rnnoise.pcm
#Convert back to WAV format
sox -r 48000 -c 1 -e signed-integer -b 16 -t raw rnnoise.pcm rnnoise.wav

Using rnnoise's Library and API for Audio Noise Reduction

Code structure

(base) ubuntu@ubuntu-2204:~/baiwen/rnnoise_reduction$ tree -L 3
.
├── CMakeLists.txt
├── deps
│ ├── include
│ │ └── rnnoise.h
│ └── lib
│ └── librnnoise.so
├── include
├── Makefile
└── src
└── main.c

5 directories, 5 files

Among them, rnnnoise.h and librnnoise.so come from the rnnoise build output, just copy them directly. CMakeLists.txt needs to update the toolchain path

# Specify the cross compiler
set(CMAKE_C_COMPILER /home/ubuntu/rk3576_AI/buildroot/output/rockchip_rk3576/host/bin/aarch64-buildroot-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER /home/ubuntu/rk3576_AI/buildroot/output/rockchip_rk3576/host/bin/aarch64-buildroot-linux-gnu-g++)

# Set sysroot
set(CMAKE_SYSROOT /home/ubuntu/rk3576_AI/buildroot/output/rockchip_rk3576/staging)
set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT})

Build

make clean
make
#push adb to the develop directory of the development board
make push

Test on the development board

root@rk3576-buildroot:/develop# ./rnnoise_reduction speech.wav rnnoise.wav -3
=== RNNoise audio noise reduction processing ===
1. Read WAV file: speech.wav
Sampling rate: 8000Hz, channels: 2, sample count: 40000 (5.00 seconds)
2. Apply gain: -3.0dB
3. Resample to 48kHz
After resampling: 240000 samples (5.00 seconds)
4. RNNoise noise reduction processing
Processed frames: 500, 480 samples per frame
First 5 original sample values of the first frame: -34 -28 -23 -17 -11
After processing: 240000 samples (5.00 seconds)
5. Save as WAV file: rnnoise.wav
=== Processing complete ===
root@rk3576-buildroot:/develop# aplay speech.wav
Playing WAVE 'speech.wav' : Signed 16 bit Little Endian, Rate 8000 Hz, Stereo
root@rk3576-buildroot:/develop# aplay rnnoise.wav
Playing WAVE 'rnnoise.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono

A noticeable noise reduction effect can be heard.