Noise Suppression Model (NSNet)
NSNet is a deep-learning-based noise suppression model for low-power embedded MCUs.
Overview
The current NSNet model is nsnet2, a quantized neural noise suppression model with the following features:
Sample rate: 16 kHz, 16-bit PCM
Frame length: 1024 samples (64 ms), frame shift: 512 samples (32 ms)
ERB-based spectral masking: the network estimates a time-frequency mask which is applied to the noisy spectrum
Single-channel processing, plus a multi-channel shared-mask mode (see Multi-Channel Shared-Mask Processing below)
Supported chips: ESP32-S3, ESP32-S31 and ESP32-P4
Note
Select the model via idf.py menuconfig -> ESP Speech Recognition -> Select noise suppression model -> Deep noise suppression v2 (nsnet2).
Use NSNet
The interface is defined in esp_nsn_iface.h. All operations go through the esp_nsn_iface_t function table, which is obtained from the model name:
Basic Flow (single channel):
Get the model interface and create an instance
#include "esp_nsn_iface.h" #include "esp_nsn_models.h" #include "model_path.h" srmodel_list_t *models = esp_srmodel_init("model"); char *model_name = esp_srmodel_filter(models, ESP_NSNET_PREFIX, NULL); const esp_nsn_iface_t *nsnet = esp_nsnet_handle_from_name(model_name); esp_nsn_data_t *nsnet_data = nsnet->create(model_name);
Process audio frames
Each call to
process()consumes and returnsget_samp_chunksize()samples (512 samples, i.e. one 32 ms frame shift at 16 kHz):int chunk = nsnet->get_samp_chunksize(nsnet_data); // 512 samples int16_t in[512], out[512]; nsnet->process(nsnet_data, in, out);
Release resources
nsnet->destroy(nsnet_data);
Examples
The examples/nsnet application demonstrates both interfaces:
SD card test: reads a 16 kHz 16-bit WAV file from the SD card, processes all input channels (using
create_mc()/process_mc()when the input has more than one channel, with channel 0 as the reference), writes the enhanced multi-channel WAV back, and reports CPU load, real-time factor and memory usage (also written to a performance log file on the SD card).USB_SERIAL_JTAG streaming test: streams audio between a host PC and the chip over the USB serial interface. On the host side, run:
python3 stream_host.py --port /dev/ttyACM1 --in test_4ch_in.wav --out out.wav
The host sends interleaved 16 kHz 16-bit frames (512 samples per channel per frame) and reads back the enhanced frames; the output WAV keeps the processed channel count.
Resource Consumption
Measured on ESP32-P4 @ 400 MHz, per 32 ms frame (512 samples):
Channels |
Time per Frame (us) |
CPU Usage (%) |
|---|---|---|
1 |
4534 |
14.2 |
4 (shared mask) |
6476 |
20.2 |
Note
With the shared-mask mode, 4 channels cost only about 1.43x the single-channel processing time, far less than running 4 independent instances.
For general model resource occupancy, see Resource Occupancy.