Powrót do strony głównej

AGC dla Linux ALSA: implementacja i konfiguracja

Artykuł opisuje implementację AGC do normalizacji głośności w systemach VoIP na Linux ALSA. Porównywane są wtyczki speex, FFmpeg dynaudnorm i własny kod C++20. Osiągnięto opóźnienie 400 ms przy +3% CPU.

AGC w działaniu: od speex do C++20 dla VoIP
Advertisement 728x90

Automatyczna regulacja wzmocnienia dźwięku: implementacja AGC dla systemów embedded

Algorytm AGC (Automatic Gain Control) normalizuje poziom sygnału w czasie rzeczywistym, eliminując potrzebę ręcznej regulacji. W systemach komunikacyjnych na Linuksie z ALSA rozwiązuje to problem nierównej głośności z różnych źródeł. Implementacja jest zoptymalizowana pod format S16_LE, 8000 Hz, mono, z opóźnieniem do 500 ms i obciążeniem CPU poniżej 3%.

Cel — przetwarzanie krótkich transmisji głosowych bez uśredniania całego pliku. Testy obejmują kryteria subiektywne (rozumialność mowy) i obiektywne (redukcja zakresu dynamicznego).

Analiza gotowych rozwiązań: AI i wtyczki

Model Nvidia studiovoice normalizuje głośność i tłumi szumy, ale wymaga resamplingu z 48 kHz do 8 kHz, co zwiększa opóźnienie. Lokalne użycie jest niemożliwe z powodu zależności.

Google AdInline article slot

Wtyczka ALSA speex (oparta na speexdsp) aktywowana parametrami agc on i agc_level (1–32768). Konfiguracja w /etc/asound.conf:

pcm.agc_pcm {
  type speex
  agc on
  agc_level 23400
  slave.pcm "dev_out"
}

pcm.test_agc {
  type plug
  slave.pcm agc_pcm
}

Test: arecord -D dev_in | aplay -D test_agc. Problemy: początkowe tłumienie, efekt „trzasków” z powodu underrun, niedokumentowane frames i filter_length. Rozwiązanie — rezygnacja.

FFmpeg dynaudnorm: analiza algorytmu

Filtr dynaudnorm idealnie pasuje: ffmpeg -f alsa -i dev_in -filter:a "dynaudnorm=f=20:g=33:m=100:c=1" output.wav.

Google AdInline article slot

Parametry:

  • f=20 — ramka 20 ms dla krótkich transmisji;
  • g=33 — wygładzanie gaussowskie (równowaga opóźnienia i płynności);
  • m=100 — maks. wzmocnienie (powiązane z poziomem głośności);
  • c=1 — korekcja DC (usuwa przesunięcia od zakłóceń).

Algorytm:

  • Wejściowa ramka o rozmiarze F;
  • Korekcja DC;
  • Wyszukiwanie szczytu;
  • Obliczenie współczynnika wzmocnienia;
  • Filtr Gaussa do wygładzania;
  • Wzmocnienie i wyjście.

Filtr nie tłumi szumów. Alternatywy: afftdn, anlmdn, arnndn w FFmpeg lub ALSA rnnoise na RNN.

Google AdInline article slot

Własna implementacja w C++20

Prototyp w Python/Jupyter symuluje przetwarzanie w czasie rzeczywistym: obsługa buforów po 20 ms bez ładowania całego pliku. Oscylogramy potwierdzają kompresję zakresu dynamicznego.

Rezultat: C++20, klasy AutomaticGainControl i GaussianFilter. Struktura projektu:

  • libagc — statyczna biblioteka;
  • agc_pipe — narzędzie do potoku;
  • Wtyczka ALSA libasound_module_pcm_agc.so.

Opcje agc_pipe:

Allowed options:

-h [ --help ] Print help

-m [ --msec ] arg (=20) Frame length in msec

-c [ --channel ] arg (=1) Channels to filter

-r [ --rate ] arg (=8000) Sample rate

-f [ --filter ] arg (=13) Gaussian filter size

-p [ --peak ] arg (=0.950000) Max peak value

-g [ --gain ] arg (=100) Max gain value

-v [ --verbose ] Enable verbose logs

Test: arecord -D <input> -f S16_LE -t raw | ./agc_pipe -f 7 -g 99 | aplay -D <output> -f S16_LE -t raw.

Wydajność: +3% CPU przy jednym źródle, opóźnienie ~400 ms (FrameLenMs=20, FilterSize=13). Używa std::span dla bezpieczeństwa.

Co jest najważniejsze

  • AGC zmniejsza zakres dynamiczny bez utraty zrozumiałości mowy;
  • Korekcja DC jest niezbędna do eliminacji artefaktów sprzętowych;
  • Filtr Gaussa zapewnia płynne przejścia, minimalizując przeciążenia;
  • Implementacja w C++20 z programowaniem obiektowym przewyższa FFmpeg pod względem utrzymania i rozszerzalności;
  • Nadaje się do embedded VoIP: niskie obciążenie, małe opóźnienia.

— Editorial Team

Advertisement 728x90

Czytaj dalej