Pulseaudio 및 Sox를 사용한 저지연 실시간 사운드 필터링

Pulseaudio 및 Sox를 사용한 저지연 실시간 사운드 필터링

오디오 실험에는 Linux를 사용하므로 PulseAudio와 ALSA를 사용합니다. 일관된 낮은 대기 시간을 달성할 수 없습니다.

컴퓨터를 사용하여 스펙트럼의 동일한 부분에서 소음을 생성함으로써 원치 않는 주변 소음(예: 사이렌 또는 백업 알람)을 가리는 아이디어가 있습니다.

매우 간단한 방법은 입력 샘플에 "핑크 노이즈"(1/f) 또는 "브라운 노이즈"(1/f^2)와 같은 일부 거듭제곱 노이즈를 곱하고 그 결과를 스피커에서 재생하는 것입니다. 나는 이것이 주파수 영역의 컨볼루션에 해당한다고 생각하므로 주파수 스파이크를 더 넓고 덜 짜증나게 만드는 효과가 있어야 합니다.

나는 PulseAudio의 열렬한 팬은 아니지만 Linux의 표준 애플리케이션 수준 오디오 프레임워크이며 가변 속도 리샘플링이 가능한 가장 간단한 도구인 것 같습니다. 리샘플링은 여러 장치(이 경우 마이크 및 스피커)를 사용할 때 클럭 왜곡을 수정하는 데 사용됩니다. 지연 시간을 줄이기 위한 몇 가지 제안이 있습니다.PulseAudio의 경우 여기그리고유닉스 파이프의 경우 여기.

원하는 필터링 효과를 달성하는 Sox 명령이 있지만 PulseAudio의 입력 및 출력이 예측 가능한 대기 시간을 갖도록 하는 방법을 모르겠습니다. 아래의 단순화된(Zsh) 파이프라인 명령은 샘플을 마이크에서 스피커로 직접 전송하지만 때로는 이를 실행할 때 주관적인 지연 시간이 거의 무시할 정도이고 때로는 지연 시간이 500ms에 가까울 때도 있습니다(예: 손가락을 스피커 앞에서 찰칵하는 경우). 마이크) , 일부 실행에서는 즉시 들리기도 하고 다른 실행에서는 초당 두 번 울립니다.) 이러한 차이점은 파이프라인을 다시 시작할 때 발생하며 PulseAudio 서버를 다시 시작할 필요가 없습니다.

PFMT=(--rate 48000 --format s16le --channels 1)
pacat -r --latency-msec=1 $PFMT | pacat --latency-msec=1 $PFMT

stdbuf -o64 -i64문제가 Unix 파이프 버퍼로 인해 발생한 경우를 대비하여 각 항목 앞에 넣어 보았지만 pacat동작이 바뀌지 않는 것 같습니다.

항상 파이프라인을 종료하고 다시 시작하고 파이프라인이 낮은 지연 시간으로 시작될 때까지 계속 반복할 수 있지만 매번 작동하는 솔루션이 있으면 좋을 것입니다. PulseAudio 로그에서는 높은 대기 시간 실행과 낮은 대기 시간 실행 간의 차이를 파악할 수 없습니다.

짧은 대기 시간에서 실행(첫 번째 줄은 가상 "모니터" 소스):

$ (pactl list sources; pactl list sinks) | grep Latency
Latency: 0 usec, configured 1999818 usec
Latency: 4193 usec, configured 66000 usec
Latency: 2861 usec, configured 15012 usec

높은 대기 시간에서 실행:

$ (pactl list sources; pactl list sinks) | grep Latency
Latency: 0 usec, configured 1999818 usec
Latency: 505 usec, configured 66000 usec
Latency: 3305 usec, configured 15012 usec

다음은 인터넷 제안에서 복사한 PulseAudio 구성의 관련 라인입니다. 그 중 어떤 것도 효과적인지 잘 모르겠습니다.

# .config/pulse/daemon.conf
;; https://forums.linuxmint.com/viewtopic.php?t=44862
default-fragments = 2
default-fragment-size-msec = 5

high-priority = yes
rlimit-nice = 31
nice-level = -11
realtime-scheduling = yes
rlimit-rtprio = 9
realtime-priority = 9

저는 몇 년 된 PulseAudio 버전을 실행하고 있으므로 수정된 알려진 버그를 발견하면 알려주시기 바랍니다.

다음은 내가 실행하고 싶은 전체 노이즈 곱셈 명령(Zsh 다시)입니다. 이 명령은 위의 간단한 파이프라인과 마찬가지로 예측할 수 없는 대기 시간 문제를 겪습니다. 이는 현재 겪고 있는 대기 시간 문제와 실제로 관련이 없지만 이것이 바로 PulseAudio를 사용하여 module-loopback소스에서 싱크로 샘플을 라우팅하는 것이 아닌 이유입니다.

SFMT=(-e signed -r 48000 -b 16 -c 1 -t raw)
PFMT=(--rate 48000 --format s16le --channels 1)
STDB=(stdbuf -o64 -i64)
sox -n $SFMT - synth brownnoise vol 0.01 | sox --buffer 64 -T $SFMT - $SFMT <($STDB pacat -r --latency-msec=1 $PFMT) $SFMT >($STDB pacat --latency-msec=1 $PFMT) vol 100

감사해요.


2023년 12월 5일에 업데이트됨:

내 오디오 설정 및 ALSA에 대한 몇 가지 질문에 댓글로 답변해 드립니다. 입력은 USB 마이크 "JMTek, LLC. USB PnP 오디오 장치"이고 출력은 AMD 오디오 컨트롤러를 통해 내 노트북에 내장된 3.5mm 오디오 잭입니다.

ALSA(aplay, arecord)를 사용하면 더 일관되게 낮은 대기 시간을 달성하는 것 같지만 -B를 사용하더라도 버퍼 크기가 50마이크로초로 단축됩니다. 또한 Pulse와 달리 ALSA의 명백한 대기 시간은 때때로 몇 분에 걸쳐 점차적으로 증가합니다(예: 10ms에서 100ms로). Pulse와 마찬가지로 ALSA에는 한 호출에서 다음 호출까지 임의의 대기 시간 변화 문제가 있습니다. 때로는 <10ms, 때로는 >400ms를 얻습니다. 그러나 앞서 말했듯이 ALSA의 대기 시간은 더 일반적인 것 같습니다. ALSA를 실험할 때 사용한 쉘 코드입니다. 채널 속도나 수를 변경하기 위해 "플러그" PCM을 사용하지 않고 장치에서 직접 데이터를 읽거나 장치에 데이터를 쓰고 있다는 점에 유의하세요.

#!/bin/zsh
SFMT=(-e signed -r 48000 -b 16 -c 1 -t raw)
AFMT=(-r 48000 -f S16_LE -c 1)
AOPT=(-B 50 $AFMT)
STDB=(stdbuf -o64 -i64)
sox -n $SFMT - synth brownnoise vol 0.01 | sox --buffer 64 -T $SFMT - $SFMT <($STDB arecord $AOPT -Dhw:2) $SFMT -c 2 >($STDB aplay $AOPT -c 2 -Dhw:1) vol 300

위 ALSA 실험의 출력 예:

Recording WAVE 'stdin' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono
Playing raw data 'stdin' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo
underrun!!! (at least 18304.245 ms long)
underrun!!! (at least 870598.858 ms long)
underrun!!! (at least 241414.917 ms long)
underrun!!! (at least 1.451 ms long)
underrun!!! (at least 12.687 ms long)
overrun!!! (at least 4.934 ms long)
underrun!!! (at least 10.253 ms long)
underrun!!! (at least 11.326 ms long)
overrun!!! (at least 0.549 ms long)
...

관련 정보