Kompleksowy przewodnik diagnostyki i optymalizacji dźwięku we FreeBSD, szczególnie dla urządzeń USB DAC i interfejsów muzycznych pracujących w trybie bitperfect i czasie rzeczywistym. Solidna dokumentacja praktycznych rozwiązań analizy i kalibracji systemu audio.
W przypadku zastosowań profesjonalnych i audiofilskich, gdzie liczy się każdy bit i każda milisekunda, diagnostyka systemu dźwięku staje się kluczowym elementem osiągnięcia optymalnej jakości odtwarzania. Dlatego znajomość metod diagnostycznych i umiejętność interpretacji ich wyników pozwala podejmować świadome decyzje oparte na mierzalnych parametrach, a nie subiektywnych wrażeniach.
Zdarza się również, że dążąc do optymalnych parametrów systemu, wprowadzamy zmiany, które komplikują konfigurację audio lub wprowadzają nieoczekiwane rezultaty. FreeBSD w zaksiesie audio oferuje wyjątkowe możliwości: szczegółową kontrolę nad parametrami podsystemu dźwięku, obsługi procesów, zarządzania energią USB i stanami procesora, co pozwala precyzyjnie dostroić system do wymagań profesjonalnego sprzętu audio.
Szczegółowy przewodnik na temat konfiguracji dźwięku we FreeBSD opisałem w artykule: FreeBSD i konfiguracja audio hi-fi: bit-perfect, equalizer, real-time.
Zbieranie informacji o systemie dźwięku i urządzeniu audio
Dokładna diagnostyka i analiza wymaga pełnego obrazu parametrów systemu oraz konfiguracji urządzeń audio. FreeBSD oferuje kilka uzupełniających się narzędzi, które razem dostarczają kompletnych informacji o stanie podsystemu audio.
Analiza /dev/sndstat
Podstawowym narzędziem diagnostycznym we FreeBSD dotyczącym dźwięku jest syscall hw.snd oraz plik /dev/sndstat, który dostarcza szczegółowych informacji o wykrytych urządzeniach audio i ich aktualnym stanie. Przed odczytem warto włączyć pełny tryb verbose dla pełniejszego obrazu:
# cat /dev/sndstat
Installed devices:
pcm0: <ATI R6xx (HDMI)> (play)
pcm1: <ATI R6xx (HDMI)> (play)
pcm2: <ATI R6xx (HDMI)> (play)
pcm3: <ATI R6xx (HDMI)> (play)
pcm4: <Realtek ALC236 (Analog)> (play/rec)
pcm5: <Realtek ALC236 (Front Analog Headphones)> (play)
pcm6: <Focusrite Scarlett Solo 4th Gen> (play/rec) default
# sysctl hw.snd.verbose=4
# cat /dev/sndstat
Wybrany output dla głównego interfejsu dźwięku: Focusrite Scarlett Solo 4th Gen:
pcm6: <Focusrite Scarlett Solo 4th Gen> on uaudio0 (1p:0v/1r:0v) default
snddev flags=0x20fc<SOFTPCMVOL,BUSY,MPSAFE,REGISTERED,BITPERFECT,VPC,RVCHANS>
[dsp6.play.0]: spd 44100, fmt 0x00201000, flags 0x2000014c, 0x00000001, pid 2032 (musicpd)
interrupts 8678947, underruns 0, feed 8678946, ready 16384
[b:2832/1416/2|bs:16384/2048/8]
channel flags=0x2000014c<RUNNING,TRIGGERED,NBIO,BUSY,BITPERFECT>
{userland} -> feeder_root(0x00201000) -> {hardware}
[dsp6.record.0]: spd 48000, fmt 0x00200010/0x00401000, flags 0x00000000, 0x00000063
interrupts 0, overruns 0, feed 0, hfree 6144, sfree 32768
[b:6144/3072/2|bs:32768/256/128]
channel flags=0x0
{hardware} -> feeder_root(0x00401000) -> feeder_format(0x00401000 -> 0x00400010) -> feeder_matrix(4.0 -> 2.0) -> feeder_volume(0x00200010) -> {userland}
Kluczowe elementy:
Nagłówek urządzenia: pcm6: (1p:0v/1r:0v) default informuje o numerze urządzenia PCM, nazwie sprzętu, liczbie kanałów fizycznych i wirtualnych (1 kanał play, 0 wirtualnych / 1 kanał record, 0 wirtualnych) oraz statusie domyślnego urządzenia.
Flagi urządzenia (snddev flags):
SOFTPCMVOL— programowa kontrola głośności PCM (software volume control)BUSY— urządzenie aktualnie w użyciuMPSAFE— bezpieczne dla wielowątkowości (symmetric multiprocessing)REGISTERED— urządzenie poprawnie zarejestrowane w systemie dźwiękuBITPERFECT— brak konwersji formatu, dane przesyłane 1:1 do sprzętuVPC— Volume Per Channel, niezależna kontrola głośności dla każdej aplikacjiRVCHANS— Record Virtual Channels, wsparcie dla wirtualnych kanałów nagrywania
Parametry kanału play:
spd 44100, fmt 0x00201000— częstotliwość 44.1 kHz, format s32le:2.0 (32-bit signed little-endian, stereo)pid 2020 (musicpd)— proces i nazwa aplikacji używającej urządzeniainterrupts 361669, underruns 0— liczba przerwań i underrunów (xrunów – to istotny parametr, o czym w dalszej części artykułu)
Struktura buforów: [b:2832/1416/2|bs:4096/128/32], gdzie pierwsza część to bufor sprzętowy (2832 bajtów / 1416 ramek / 2 bloki), a druga to bufor programowy (4096 bajtów / 128 ramek / 32 bloki).
Flagi kanału:
RUNNING— kanał aktywnie przetwarza audioTRIGGERED— kanał wyzwolony do startu (precyzyjna kontrola momentu rozpoczęcia odtwarzania)NBIO— non-blocking I/O, operacje nie blokują procesuBITPERFECT— dane przechodzą do urządzenia bez konwersji i resamplingu
Łańcuch feederów: {userland} -> feeder_root(0x00201000) -> {hardware} pokazuje prostą ścieżkę sygnału — dane z aplikacji trafiają bezpośrednio do sprzętu bez pośredniego przetwarzania. To pożądany stan dla trybu bitperfect.
Ustawienia sterownika sound(4) – hw.snd
Oprócz informacji z /dev/sndstat warto sprawdzić globalne ustawienia podsystemu dźwięku sound(4) FreeBSD, które wpływają na wszystkie urządzenia audio:
# sysctl hw.snd
Z wynikowych parametrów w kontekście diagnostyki systemu dźwięku, szczególnie interesować nas będą:
hw.snd.latency: 2— globalny profil opóźnień (0-10, gdzie niższe wartości = mniejsze późnienie i mniejsze bufory)hw.snd.latency_profile: 1— włączony profil latencjihw.snd.syncdelay: -1— opóźnienie synchronizacji (-1 = automatyczne)hw.snd.usefrags: 0— tryb fragmentacji buforów (0 = wyłączony)hw.snd.timeout: 5— timeout operacji audio w sekundach
W trybie bitperfect – dev.pcm.X.bitperfect=1 wiele z pozostałych parametrów wynikowych jest pomijanych — resampling, miksowanie vchan i konwersja formatu nie zachodzą, a dane audio trafiają bezpośrednio do sprzętu. Parametry resamplera (feeder_rate_*) mają znaczenie tylko gdy bitperfect jest wyłączony lub dana aplikacja używa częstotliwości nieobsługiwanej natywnie przez urządzenie.

Podobnie jak na konsolecie mikserskiej profesjonalnego studia nagraniowego, FreeBSD oferuje rozbudowany panel kontrolny podsystemu audio – dziesiątki parametrów pozwalających precyzyjnie dostroić każdy aspekt ścieżki sygnału.
Praca z sndctl(8)
Kolejnym i ostatnim narzędziem przydatnym w diagnostyce dźwięku jest aplikacja sndctl(8), które funkcjonuje w systemie FreeBSD od wersji 14.0. De facto operuje na m.in. na danych pobranych z /dev/snd i dostarcza komplet uporządkowanych informacji o możliwościach oraz aktualnej konfiguracji konkretnego urządzenia audio. W trybie wywołania bez dodatkowych parametrów wskazuje stan głównego (domyślnego) urządzenia:
# sndctl -v
pcm6: <Focusrite Scarlett Solo 4th Gen> on uaudio0 (play/rec)
name = pcm6
desc = Focusrite Scarlett Solo 4th Gen
status = on uaudio0
devnode = dsp6
from_user = 0
unit = 6
caps = INPUT,MMAP,OUTPUT,REALTIME,TRIGGER
bitperfect = 1
autoconv = 0
realtime = 0
play.format = s32le:2.0
play.rate = 44100
play.vchans = 0
play.min_rate = 44100
play.max_rate = 192000
play.min_chans = 2
play.max_chans = 2
play.formats = s32le
rec.rate = 48000
rec.format = s16le:2.0
rec.vchans = 1
rec.min_rate = 44100
rec.max_rate = 192000
rec.min_chans = 4
rec.max_chans = 4
rec.formats = s32le
dsp6.play.0
parentchan =
unit = 0
caps = MMAP,OUTPUT,REALTIME,TRIGGER
latency = 2
rate = 44100
format = s32le:2.0
pid = 2049
proc = musicpd
interrupts = 1969614
xruns = 0
feedcount = 1969613
volume = 0.45:0.45
hwbuf.format = s32le:2.0
hwbuf.rate = 44100
hwbuf.size_bytes = 2832
hwbuf.size_frames = 354
hwbuf.blksz = 1416
hwbuf.blkcnt = 2
hwbuf.free = 0
hwbuf.ready = 2832
swbuf.format = s32le:2.0
swbuf.rate = 44100
swbuf.size_bytes = 16384
swbuf.size_frames = 2048
swbuf.blksz = 2048
swbuf.blkcnt = 8
swbuf.free = 1416
swbuf.ready = 14968
feederchain = [userland -> feeder_root(s32le:2.0) -> hardware]
Oprócz parametrów, które znamy już z wyników /dev/sndstat i hw.snd, warto zwrócić uwagę na kilka poniższych:
caps = INPUT,MMAP,OUTPUT,REALTIME,TRIGGER
Możliwości i funkcje urządzenia pcm6, tutaj Focusrite Scarlett Solo 4th Gen., inaczej suma możliwości wszystkich kanałów:
INPUT– urządzenie obsługuje nagrywanie (kanał rec).OUTPUT– urządzenie obsługuje odtwarzanie (kanał play).MMAP– oba kierunki wspierają mapowanie bufora do pamięci.REALTIME– urządzenie wspiera operacje z priorytetem czasu rzeczywistego.TRIGGER– oba kierunki wspierają precyzyjne wyzwalanie.
bitperfect = 1
Potwierdzenie pracy urządzenia w trybie bitperfect sterownika dźwięku FreeBSD.
realtime = 0
Pole realtime jest nieco mylące — nie chodzi tu o pracę systemu operacyjnego w trybie realtime ani nie odnosi się do parametrów urządzenia audio czy jego kanałów. realtime to wewnętrzny parametr programu sndctl(8) kontrolujący zestaw trzech parametrów systemowych wpływających na buforowanie i precyzję timerów. Wartość realtime=0 oznacza standardowe ustawienia, wartość 1 — konfigurację zoptymalizowaną pod kątem minimalnych opóźnień, zmieniając następujące sysctl:
hw.snd.latency=0— kontroluje domyślny rozmiar bufora audio. Wartość 0 oznacza minimalne buforowanie, wartości wyższe zwiększają bufor kosztem latencji.hw.snd.latency_profile=0— wybiera profil latencji. Wartość 0 to profil agresywny (mniejsze bufory), wartość 1 to profil zachowawczy (większe bufory, mniej xrunów).kern.timecounter.alloweddeviation=0— określa dopuszczalne odchylenie zegara systemowego w mikrosekundach. Wartość 0 wymusza maksymalną precyzję, co jest istotne dla synchronizacji strumieni audio. Niższa latencja zwiększa ryzyko xruns bez zauważalnych korzyści wywołując słyszalne artefakty podczas odtwarzania lub nagrywania (na tematalloweddeviationixrunsw dalszej części artykułu).
caps = MMAP,OUTPUT,REALTIME,TRIGGER (dsp6.play.0)
Możliwości kanału play urządzenia pcm6. wskazujące na pełne wsparcie dla niskolatencyjnego audio:
MMAP– kanał obsługuje mapowanie bufora do pamięci aplikacji. Zamiast write() aplikacja pisze bezpośrednio do współdzielonego bufora — mniej kopiowania, niższa latencja.OUTPUT– aktualnie obsługiwany kanał — odtwarzanie dźwięku. Dla nagrywania byłoby INPUT.REALTIME– kanał wspiera pracę z niską latencją i małymi buforami. Sterownik gwarantuje przewidywalne timingi.TRIGGER– kanał obsługuje precyzyjne wyzwalanie startu/stopu. Aplikacja może napełnić bufor, a potem atomowo wystartować odtwarzanie w dokładnym momencie — przydatne do synchronizacji wielu strumieni.
latency = 2
Profil opóźnień – jak wyżej, dla hw.snd.
interrupts = 1969614 feedcount = 196961
Pola interrupts oraz feedcount w wyjściu sndctl to liczniki obrazujące aktywność kanału audio od momentu jego uruchomienia:
interruptsto liczba przerwań sprzętowych wygenerowanych przez urządzenie audio. Każde przerwanie sygnalizuje, że sprzęt przetworzył blok danych z bufora i jest gotowy na kolejny. Przy sample rate 44100 Hz i rozmiarze bloku 1416 bajtów (354 ramki) przerwania występują około 125 razy na sekundę.feedcountto liczba bloków danych dostarczonych przez łańcuch feederów do bufora sprzętowego. W prawidłowo działającym systemie wartość ta powinna być zbliżona do liczby przerwań — każde przerwanie powinno skutkować dostarczeniem nowego bloku danych.
Różnica między tymi wartościami jest diagnostycznie istotna. W przedstawionym przykładzie interrupts = 1969614 i feedcount = 1969613 — różnica wynosi 1 i wynika najprawdopodobniej z momentu próbkowania, co oznacza, że system nadąża z dostarczaniem danych. Większa rozbieżność mogłaby wskazywać na problemy z wydajnością i potencjalne atrefakty dźwiękowe, wynikające również z xruns.
Warto jeszcze zwrócić uwagę i porównać format próbki w play.format (s32le:2.0 — gdzie s32le to format, a 2.0 to układ kanałów) z listą natywnych formatów w play.formats (s32le). Pozwala to zweryfikować, czy zachodzi konwersja. Gdy format próbki jest obecny na liście natywnych formatów, dane nie wymagają przetwarzania przez feeder konwersji. Podobnie play.rate mieszczące się w zakresie min_rate–max_rate potwierdza, że urządzenie obsługuje daną częstotliwość natywnie bez resamplingu.
xruns = 0
xruns to ostatni i bodaj najistotniejszy parametr systemu pod kątem diagnostyki dźwięku i rozwiązywania problemów z audio w trybie bitperfect i w czasie rzeczywistym. Więcej w poniższym rozdziale.
xruns
Parametr xruns dostępny na podstawie danych jądra systemu FreeBSD, to mierzalna wartość potencjalnych słyszalnych artefaktów dźwiękowych. Podczas kalibracji systemu lub urządzeń audio, w szczególności USB DAC do pracy w trybie bitperfect lub niskich opóźnień, mogą pojawić się słyszalne trzaski, kliknięcia lub przerwy podczas odtwarzania lub nagrywania dźwięku. Najczęstszą przyczyną są właśnie tzw. xruns (buffer underrun / overrun) czyli sytuacje, gdy system nie nadąża z dostarczaniem danych audio do urządzenia:
- underrun (odtwarzanie) – aplikacja nie dostarcza danych wystarczająco szybko — bufor się opróżnia, słychać artefakty lub ciszę.
- overrun (nagrywanie) – aplikacja nie odbiera danych wystarczająco szybko — bufor się przepełnia, dane są tracone.
Przyczyną najczęściej są źle dobrane wartości latencji i bufora USB. Wartość xruns różna od zera wyraźnie wskazuje na ten problem.
Parametr xruns najszybciej odczytamy za pomocą /dev/sndstat (z włączonym trybem verbose=4), sprawdzając pola underruns i overruns:
# <span class="token">grep</span> -E <span class="token">'under|over'</span> /dev/sndstat
Parametr xruns dla konkretnego urządzenia zweryfiktujemy również za pomocą sndctl(8):
# sndctl -v | grep xruns
Możemy uruchomić polecenie w pętli, wyświetlające wartość parametru xruns w momencie wystąpienia i jego zmiany wraz z znacznikiem czasowym, co ułatwia analizę podczas odsłuchu:
while true; do
sndctl -v | awk -F= -v t="$(date +%H:%M:%S)" '/xruns/ && $2 != 0 {print t, $0}'
sleep 1
done
W repozytorum GitHuba opublikowałem również własny program: xruns napisany w C, odczytujący SNDSTIOC_GET_DEV bezpośrednio z interfejsu ioctl(2):
xruns -help
usage: xruns [-d device] [-p] [-w] [-i interval]
Options:
-d N Monitor device pcmN (default: system default)
-p Show only playback channels
-w Watch mode - loop and show only changes
-i SEC Interval in seconds for watch mode (default: 1)
-h Show this help
Examples:
xruns Show xruns for default device
xruns -d 1 Show xruns for pcm1
xruns -d 0 -p Show only playback xruns for pcm0
xruns -d 0 -p -w Watch playback xruns on pcm
Przykłady użycia i możliwości:
# Pokaż xruns dla domyślnego urządzenia audio
xruns
# Pokaż xruns dla pcm6
xruns -d 6
# Pokaż tylko xruns kanału play dla pcm6
xruns -d 6 -p
# Tryb watch — monitoruj zmiany w czasie rzeczywistym
xruns -w
# Monitoruj xruns odtwarzania na pcm6, sprawdzaj co 2 sekundy
xruns -d 6 -p -w -i
Parametry latency dla sound(4)
Parametry hw.snd.latency i hw.snd.latency_profile sterownika dźwięku sound(4) we FreeBSD kontrolują rozmiary buforów audio, ale nie w sposób, który moglibyśmy intuicyjnie oczekiwać. Zamiast bezpośrednio ustawiać latencję w milisekundach, operują one na tabelach konwersji wbudowanych w podsystem sound(4).
Sposób działania parametrów:
hw.snd.latency_profiledefiniuje strategię bufowania: 0 – profil agresywny (niska latencja, ryzyko underrunów przy wysokim obciążeniu); 1 – profil umiarkowany/bezpieczny (domyślny, zrównoważony).hw.snd.latencyokreśla poziom latencji w zakresie 0-10: 0 – najniższa latencja; 2 – niska, ale stabilna latencja (rekomendowana dla większości zastosowań); 10 – najwyższa latencja.
Rekomendowane ustawienia latency
Typowe odtwarzanie muzyki (domyślne):
hw.snd.latency: 2hw.snd.latency_profile: 1
Aplikacje profesjonalne (nagrywanie, monitoring):
hw.snd.latency: 0-1hw.snd.latency_profile: 0
Wymaga stabilnego obciążenia systemu, w przeciwnym razie mogą wystąpić przerwy w dźwięku.
Maksymalna stabilność (słabe maszyny, wysokie obciążenie):
hw.snd.latency: 4-7hw.snd.latency_profile: 1
Należy pamiętać, że rzeczywista latencja zależy od kombinacji bufora sprzętowego i programowego oraz częstotliwości próbkowania. Parametry systemowe są jedynie wskazówkami dla aplikacji nieokreślających własnych preferencji bufowania. Programy audio profesjonalnego (JACK, DAW) ustawiają własne rozmiary buforów, ignorując hw.snd.latency.
Parametr alloweddeviation
kern.timecounter.alloweddeviation to parametr jądra FreeBSD, który kontroluje maksymalne dopuszczalne odchylenie między zegarem programowym a sprzętowym przed wymuszeniem synchronizacji. Jest to istotny parametr dla aplikacji audio, gdzie precyzja czasowa bezpośrednio wpływa na jakość odtwarzania.
W skrócie, mechanizm działania kern.timecounter.alloweddeviation działa następująco: systemy z rodzny BSD używają zegarów programowych do synchronizacji budzenia procesów. Parametr alloweddeviation określa (w nanosekundach) maksymalny dozwolony dryft przed korektą. Niższa wartość oznacza ściślejszą synchronizację i precyzyjniejsze budzenie procesów. Więcej na ten temat w artykule Paula Hermana.
Poniżej wyniki testu latencji budzenia procesów (wakeup latency) przy użyciu benchmarku Paula Hermana dla domyślnej wartości wynoszącej 5 ms (kern.timecounter.alloweddeviation=5):
# ./wakeup_latency
0.007341
0.014410
0.037370
0.037336
0.037375
0.037345
0.037356
Po ustawieniu kern.timecounter.alloweddeviation=0:
# sysctl kern.timecounter.alloweddeviation=0
# ./wakeup_latency
0.000061
0.000095
0.000077
0.000093
0.000096
0.000090
0.000062
Redukcja latencji budzenia z ~37 mikrosekund do ~0.09 mikrosekundy to poprawa o około 400x. Dla aplikacji audio oznacza znacznie precyzyjniejsze dostarczanie danych do buforów.
Aby włączyć maksymalną precyzję zegarów, należy dodać do /etc/sysctl.conf:
kern.timecounter.alloweddeviation=0
USB Polling Rate
W kontekście urządzeń audio USB (DAC, interfejsy audio) termin polling rate odnosi się do częstotliwości, z jaką system operacyjny odpytuje urządzenie o dane audio. Wpływa na jakość odtwarzania przez zmniejszenie jittera i poprawę stabilności strumienia danych.
FreeBSD kontroluje USB audio polling przez parametr hw.usb.uaudio.buffer_ms (domyślnie 4 ms), który określa okres danych audio przetwarzanych jednorazowo. Dokumentacja FreeBSD ostrzega, że zbyt niski buffer_ms może powodować “słyszalne przerwy z powodu częstego budzenia CPU”. Jednak w praktyce:
hw.usb.uaudio.buffer_ms=2: bezpieczny dla większości systemów, dobra równowaga.hw.usb.uaudio.buffer_ms=4: domyślny, najstabilniejszy.hw.usb.uaudio.buffer_ms=8: dla słabszych systemów lub oszczędzania energii (niedopuszczalne w audio).
Dlatego wartość buffer_ms=2 zapewnia najbardziej regularny i regularny stabilny strumień danych do urządzenia DAC bez ryzyka xrunów. Mniejsze parametry mogą powodować słyszalne przerwy.
Diagnostyka transferu USB
Oprócz parametru xruns mamy kolejne istotne i mierzalne parametry, które morzemy skorelować z ew. artefaktami dźwiękowymi: UE_CONTROL_FAIL i UE_ISOCHRONOUS_FAIL.Odpowiadają za błędy transferu danych oraz kontrolnych (np. zmiana sample rate, volume, routing). Parametry odczytamy za pomocą usbconfig(8).
Lista zainstalowanych urządzeń USB:
# usbconfig list
ugen0.1: <XHCI root HUB AMD> at usbus0, cfg=0 md=HOST spd=SUPER (5.0Gbps) pwr=SAVE (0mA)
ugen0.2: <RTL2838 DVB-T Realtek Semiconductor Corp.> at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (500mA)
ugen0.3: <USB2.1 Hub HP, Inc> at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (0mA)
ugen0.4: <Scarlett Solo 4th Gen Focusrite-Novation> at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (0mA)
ugen0.5: <USB3.1 Hub HP, Inc> at usbus0, cfg=0 md=HOST spd=SUPER (5.0Gbps) pwr=SAVE (0mA)
Parametrów wybranego urządzenia:
# usbconfig -d 0.4 dump_stats
ugen0.4: <Scarlett Solo 4th Gen Focusrite-Novation> at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (0mA)
{
UE_CONTROL_OK : 294
UE_ISOCHRONOUS_OK : 8660417
UE_BULK_OK : 23581
UE_INTERRUPT_OK : 0
UE_CONTROL_FAIL : 0
UE_ISOCHRONOUS_FAIL : 0
UE_BULK_FAIL : 0
UE_INTERRUPT_FAIL : 0
}
Zerowe wyniki parametrów UE_CONTROL_FAIL i UE_ISOCHRONOUS_FAIL wskazują na brak problemów i są też potwierdzeniem wyników odsłuchowych. W innym przypadku należałoby skorygować parametr hw.usb.uaudio.buffer_ms lub też przyjrzeć się fizycznemu połączeniu urządzenia USB z komputerem.
Tryb oszczędzania energii USB
Zarządzanie energią portów USB to również jeden z elementów mogących powodować słyszalne artefakty (kliknięcia, trzaski, popy) w urządzeniach USB DAC, szczególnie gdy system próbuje zawiesić nieaktywne urządzenia USB lub gdy występuje opóźnienie w dostarczaniu danych.
Parametr hw.usb.power_timeout=0 we FreeBSD wyłącza automatyczne monitorowanie zasilania portów USB, które pozostają aktywne przez cały czas, niezależnie od aktywności podłączonych urządzeń. Zapewnia to stabilność połączenia z DAC-ami – zewnętrzne przetworniki cyfrowo-analogowe utrzymują stałe połączenie bez procesu ponownej identyfikacji.
hw.usb.power_timeout dodajemy do pliku /etc/sysctl.conf.
Drugą opcją jest całkowite wyłącznie parametrów oszczędzania energii dla urządzeń USB oraz hub-ów USB. FreeBSD domyślnie włącza tryb power_save dla hubów USB i pozwala urządzeniom przechodzić w stan uśpienia.
Przykładowo, w prezentowanej konfiguracji Fosucrite Scarlet Solo 4th Gen siedzi za hubem ugen0.3 (USB 2.1, 480Mbps). Jeśli hub wchodzi w tryb power_save, może to wpływać na stabilność urządzeń, które są do niego przyłączone.
W celu wyłączenia trybu power_save dla poszczególnych urządzeń i hubów USB wykorzystujemy narzędzie usbconfig(8).
Najpierw sprawdzamy stan zasilania urządzeń USB:
# usbconfig
ugen0.1: at usbus0, cfg=0 md=HOST spd=SUPER (5.0Gbps) pwr=SAVE (0mA)
ugen0.2: at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (500mA)
ugen0.3: at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=SAVE (0mA)
ugen0.4: at usbus0, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (0mA)
ugen0.5: at usbus0, cfg=0 md=HOST spd=SUPER (5.0Gbps) pwr=SAVE (0mA)
Etykiety pwr=SAVE świadczą o pracy urządzeń w trybie oszczędzania energii: ugen0.1 — root hub (XHCI), ugen0.3 — HP USB2.1 Hub oraz ugen0.5 — HP USB3.1 Hub.
Aby wyłączyć tryb power_save dla konkretnego urządzenia uruchamiamy polecenie:
# usbconfig -d ugen0.3 power_on
Możemy również za pomocą usługi devd(8) możemy automatycznie wprowadzić tryb power_save podczas startu i podłączenia urządznia.
Najpierw sprawdzamy id, urządzeń które chcemy dodać do grupy wykluczeń z power_save:
# usbconfig -d ugen0.3 dump_device_desc | grep -E "idVendor|idProduct"
idVendor = 0x03f0
idProduct = 0x1847
# usbconfig -d ugen0.5 dump_device_desc | grep -E "idVendor|idProduct"
idVendor = 0x03f0
idProduct = 0x0620
Daemon devd(8) przy starcie czyta wszystkie pliki w lokalizacji /etc/devd/*.conf. Tworzymy więc plik /etc/devd/usb-hubs.conf i zapisujemy w nim nasze urządzenia:
# Plik /etc/devd/usb-hubs.conf
#
# HP USB2.1 Hub
notify 100 {
match "system" "USB";
match "subsystem" "DEVICE";
match "type" "ATTACH";
match "vendor" "0x03f0";
match "product" "0x1847";
action "usbconfig -d $cdev power_on";
};
# HP USB3.1 Hub
notify 100 {
match "system" "USB";
match "subsystem" "DEVICE";
match "type" "ATTACH";
match "vendor" "0x03f0";
match "product" "0x0620";
action "usbconfig -d $cdev power_on";
};
Po zapisaniu możemy zweryfikować naszą konfigurację przeładowując deamona devd(8):
# service devd restart
i zweryfikować ustawienia przez usbconfig(8).
Optymalizacja C-states CPU w audio
Jeśli doświadczasz artefaktów lub opóźnień audio we FreeBSD, przyczyną mogą być też stany oszczędzania energii procesora — tzw. C-states. Producenci sprzętu audio również zalecają wyłączenie C-states, bo przejścia między stanami mogą powodować dropouty.
Na czym polega problem z C-States? Gdy CPU jest bezczynny, system może przełączyć go w tryb niskiego poboru mocy. Wybudzenie z głębszych stanów C trwa jednak mikrosekundy, które dla audio w czasie rzeczywistym bywają krytyczne — bufor się opróżnia szybciej niż procesor zdąży dostarczyć nowe próbki.
Na szczęście FreeBSD ma pełną kontrolę nad C-states i pozwala je kontrolować programowo:
Sprawdzamy C-States dla CPU:
# sysctl hw.acpi.cpu.cx_lowest
Jeśli wynik jest inny niż C1, wymuszamy pozostanie CPU w najwyższym stanie wydajności (C1):
# sysctl hw.acpi.cpu.cx_lowest=C1
Jeśli rozwiązanie okaże się to pomocne, dodajemy ustawienie do /etc/sysctl.conf na stałe.
Podsumowanie
Artykuł jest podsumowaniem mojej blisko dwuletniej pracy nad dogłębnym poznaniem architektury dźwięku FreeBSD, która nota bene stale się rozwija.
System ten oferuje rozbudowany zestaw narzędzi do diagnostyki i optymalizacji podsystemu audio. Kluczowe źródła informacji: /dev/sndstat, parametry hw.snd.* oraz sndctl(8) – pozwalają zweryfikować stan urządzeń, strukturę buforów i łańcuch przetwarzania sygnału.
Dość istotnym parametrem z perspektywy jakości dźwięku pozostaje xruns. Wartość różna od zera jednoznacznie wskazuje na artefakty dźwiękowe i wymaga korekty konfiguracji. Monitorowanie xruns w czasie rzeczywistym ułatwia identyfikację źródła zakłóceń podczas odsłuchu.
Stabilna praca audio w trybie bitperfect i niskich opóźnień wymaga uwzględnienia kilku warstw systemu:
- parametrów latencji sound(4)
- precyzji zegarów systemowych
- interwału pollingu USB
- zarządzania energią portów USB i hubów
- stanów oszczędzania energii procesora
Każda z tych warstw wpływa na końcowy rezultat, a ich łączna optymalizacja daje przewidywalne i mierzalnie poprawne wyniki. FreeBSD udostępnia narzędzia do kontroli każdej z nich.








