• 목록
  • 아래로
  • 위로
  • 쓰기
  • 검색
지식

리눅스에서의 Hi-fi와 Pipewire 이야기

zlzleking zlzleking
5962 6 12

이번에 Pipewire가 0.3.49버전으로 업데이트 되면서 샘플링레이트 자동 변환 기능이 안 되던 버그가 패치되었습니다. 그래서 제 블로그에 관련된 글을 썼습니다만 한번 다른 분들에게 소개해 보면 어떨까 싶어 가져와 봤습니다.


2000년대 중후반부터 PC를 통한 음악 감상이 일반화되고, 2010년대에 접어들어서는 기존의 Hi-fi 시장이 급격하게 PC과 모바일 기반으로 이동하기 시작했다. 이런 추세에 맞추어 USB DAC같은 하드웨어나 OS가 오디오 구조를 바꿔나가는 등의 변화가 있었다.

오늘날 많은 사람들이 PC를 통한 Hi-fi 시스템을 구축하고 사용하지만 그들 대부분은 윈도우를 사용하며, 일부는 macOS를 사용한다. 그래서 리눅스에서의 Hi-fi에 대한 이야기가 많이 없기에 대충 정리해보고자 한다.

OS의 오디오 출력 구조

일단은 우리가 USB 오디오를 사용한다고 가정하자. 우리가 소리를 듣기 위해서는 최종적으로 USB DAC에 신호가 전달되어야 한다. 장치 제어와 같은 일은 OS의 커널이 해야 하는 일이고, “무슨 신호를 어떻게” 장치에 전달할지를 정의하는 것은 드라이버의 역할이다. 그래서 커널의 USB를 제어하는 부분을 반드시 거치게 된다. 이 부분에 대해서는 많은 것들이 표준화되어 있어 어떤 제품이 들어가도 원하는 대로 동작하게 할 수 있다. 하지만 OS가 표준을 어디까지 구현하는지는 강제된 것이 아니기 때문에 문제가 생길 수 있는데, 윈도우 10 초창기까지는 USB Audio class 2에 대한 드라이버가 내장되지 않았기 때문에 24비트/192khz 출력, 비동기 오디오 스트리밍과 같은 몇몇 주요 기능들을 사용할 수 없었다. 하지만 현재는 우리가 보통 쓰는 OS들은 다 이정도 표준은 구현하고 있으니 신경을 안 써도 될 것이다. 하지만 제조사가 별도의 드라이버를 제공하는 경우가 있는데, 이것은 USB 오디오 표준 이외의 기능을 구현하기 위해서이다. 이를테면 하드웨어 볼륨 컨트롤을 좀 더 세세하게 나누거나, PC에서 디지털 필터를 조정한다거나, DAC의 설정을 바꾼다거나, ASIO같은 것을 구현한다거나 하면 USB 오디오 표준 외적인 내용이기 때문에 장치 제조사가 알아서 구현해야 한다.

근데 USB를 직접 제어한다면 소프트웨어 개발 난이도가 지옥으로 향하게 된다. DOS시절에는 당연하게 그래야 했지만 사용자가 어떤 장치를 연결하느냐에 따라서 소프트웨어를 각자 짜야 한다면 파편화가 심해질 것이기 때문에 OS는 어떤 하드웨어를 사용하더라도 같은 방법으로 접근할 수 있게 추상화 계층을 제공한다. 이를테면 ‘USB 장치 A에 데이터 “XXX”를 전송한다’란 것보다는 ‘오디오 장치 A에 24비트, 48khz로 구성된 오디오 스트림 “XXX”를 재생한다’가 더 편할 것이다. 윈도우에서는 WASAPI의 일부 부분, 리눅스에서는 ALSA가 이 역할을 수행하고 있다. (꼭 그렇지는 않지만) 여기 부분까지로 가면 하드웨어와 1:1로 소통할 수 있어 데이터에 대한 OS의 변경을 최소화할 수 있다. 쉽게 말해서 비트 퍼펙트가 가능하다는 뜻이다. 그래서 많은 Hi-fi 가이드는 OS의 기타 기능들을 우회하고 이 수준에서 오디오를 출력하게 설정한다.

물론 PC를 음악 재생기로만 쓴다면 이렇게 해도 큰 문제가 없다. 하지만 생각할 수 있는 몇 가지 문제가 있는데, 만약 재생하고자 하는 오디오 스트림을 해당 오디오 장치가 지원하지 않는다면 문제가 생긴다. 이를테면 많은 USB DAC는 PCM 형식의 오디오 스트림을 재생 가능하지만 돌비 디지털이나 AAC 형식의 스트림을 재생하지는 못한다. 많은 음악 형식이 44.1khz의 샘플링 레이트를 가지고 있지만 삼성 갤럭시의 많은 기기들은 44.1khz를 지원하지 않기 때문에 재생할 수 없다. 애플 USB C DAC를 사용한다면 24비트 96khz를 비롯한 고해상도 음원을 재생할 수 없다.

게다가 게임을 하면서 보이스챗을 하거나, 음악 재생 중에 알림이 오거나 하는 일이 생긴다면 이런 “저수준” API로는 하드웨어를 물고 있어야 하기 때문에 우선권을 다른 기기들에게 전달할 수가 없다. (물론 ALSA를 잘 설정한다면 가능하긴 하지만 그다지 좋은 사용법은 아니다.) 따라서 샘플링레이트 컨버터, 오디오 믹서, 세션 매니저와 같은 역할을 시키기 위한 또 하나의 추상화 계층이 필요하며, 우리는 이걸 ‘오디오 서버’라고 부른다.

Pulseaudio

흔히 그저 Pulse라고 부르는 Pulseaudio는 오랜 시간 동안 리눅스의 사실상 표준 오디오 서버로 사용되어 왔다. 현 시점에서 우분투나 데비안와 같은 배포판을 깔게 되면 애플리케이션 입장에서의 오디오 출력은 Pulseaudio에게 하게 된다. Pulseaudio는 위에 말한 믹서, 샘플링레이트 컨버터, 세션 매니저의 역할을 그저 잘 수행하기 때문에 그냥 사용한다면 별 문제가 없다. (이건 윈도우의 WASAPI도 마찬가지이다.) 하지만 기본 설정에 만족하지 못하는 사람들은 최대한 높은 퀄리티를 구현하기 위해 몇 가지 설정을 바꾸게 된다.

우선 Pulseaudio의 기본 샘플링레이트 변환기는 Speex코덱의 샘플링레이트 변환기를 사용하게 설정되어 있다. 기본 설정으로는 음질보다는 변환 속도와 최적화에 신경쓰고 있기 때문에(PC뿐만이 아니라 Arm보드와 같은 저사양 기기에서도 돌아가야 하기 때문이다) 대충 아래와 같은 느낌으로 출력하게 된다.

src.infinitewave.ca 를 참조한 Speex (Q1)의 Sweep 파형
src.infinitewave.ca 를 참조한 Speex (Q1)의 주파수 응답

단순히 주파수를 스윽 올리기만 해도 노이즈가 좀 많이 생기는 것을 볼 수 있다. 일단 고주파 대역을 깎아먹고, 저정도로 큰 노이즈는 충분히 청음가능하다. 이 상태로는 WASAPI에 비해 “좋다”고 보기 힘들다. 따라서 사람들은 대신 Sox 리샘플러를 사용하곤 한다.

src.infinitewave.ca 를 참조한 Sox (VHQ)의 Sweep 파형
src.infinitewave.ca 를 참조한 Sox (VHQ)의 주파수 응답

Sox를 사용하게 되면 거의 완벽한 결과물을 보여 준다. 이 정도라면 리샘플링 손실이 거의 없다고 봐도 될 정도이다. 그래서 이 정도 설정으로만 해 놓고 써도 별 문제는 없지만 최대한 손실을 없게 하고 싶은 사람들은 avoid-resampling 옵션을 켜게 된다.

Pulseaudio 11버전부터 추가된 이 기능은 “메인 샘플링 레이트”와 “대체 샘플링 레이트”를 설정한 다음 대체 샘플링 레이트로 설정하는 게 더 이득인 상황에는 대체 샘플링 레이트로 재생하게 된다. 이를테면 메인 샘플링 레이트가 48khz로 설정되어 있지만 44.1khz의 음원을 재생할 때에는 샘플링 레이트 변환을 수행하지 않는 것이 더 이득이기 때문에 샘플링 레이트를 44.1khz로 설정한다. 하지만 48khz로 뭔가를 재생하고 있을 때에는 44.1khz 신호가 입력되더라도 “이미 장치가 물린 다음”이기 때문에 44.1khz 신호를 48khz로 리샘플링해서 믹서로 보낸다.

그래서 일상적인 상황에서는 리샘플링을 최대한 피할 수 있지만 이것도 몇 가지 문제가 있다. 첫번째로 이것은 2022년 초 시점에서 작동하지 않는다. ALSA와 관련된 커널 버그 때문에 작동하지 않는다는 보고가 올라와 있고, 언젠가는 해결되겠지만 당분간은 이대로 사용하게 될 것이다. 두번째로는 대체 주파수를 하나만 지정할 수 있다는 것이다. 만약 96khz와 같은 고해상도 음원을 재생하게 된다면 이건 꼼짝없이 리샘플링을 하게 되거나, 다른 주파수를 포기해야 할 것이다.

Pipewire

Pipewire는 Pulseaudio를 대체하기 위한 오디오 서버이다. 시스템 어드민의 입장에서 보면 Pulse보다 가볍고 레이턴시가 적다는 특징이 있고, 좀 더 건드리는 부분이 적다. 하지만 오디오파일의 입장에서 보면 좀 재밌는 일을 할 수가 있다.

우선 Pipewire도 기본적인 아이디어는 비슷하다. 기본 샘플링 레이트와 대체 샘플링 레이트를 설정해서 가장 최적인 상황을 찾는데, Pipewire는 pulse와는 다르게 대체 샘플링 레이트가 다양하다는 특징이 있다. 예를 들면 기본 샘플링 레이트를 44.1khz로 설정하고, 대체 샘플링 레이트를 48khz, 96khz, 192khz로 설정하게 되면 사실상 현존하는 대부분의 PCM 음원은 리샘플링 없이 재생할 수 있다.

그리고 어떤 상황에서는 Pulse보다 좀 더 안정적이다. 이를테면 현재 Wine을 Pulseaudio를 경유해서 사용할 때, USB DAC를 사용한다면 레이턴시와 관련해서 오디오가 끊긴다. (이것도 역시 커널 단의 버그와 엮여 있다.) 하지만 Pipewire는 이런 문제가 없다.

또한 세션 매니저를 분리해서 사용하는데, Wireplumber와 같은 물건을 쓴다면 다양한 애플리케이션과 연동해서 Geek들이 좋아할 설정을 할 수 있다. 이를테면 Bluez와 연동해서 특정 블루투스 이어폰을 쓸 때는 AAC나 LDAC로 출력한다거나, 샘플링 레이트를 조정한다거나 하는 등의 일들을 할 수 있다. 특정 애플리케이션에서 들어오는 신호에게만 이펙트를 먹인다거나, 샘플링 레이트를 고정한다거나 하는 일들도 할 수 있다. (설정의 귀찮음을 감수한다면) 원하는 목적에 따라 유연하게 쓸 수 있다는 것이다.

Pipewire도 기본 리샘플러로 Speex코덱의 리샘플러를 사용하는데, 기본값은 퀄리티 4이고, 14까지 늘릴 수 있다.

src.infinitewave.ca 를 참조한 Speex (Q10)의 Sweep 파형
src.infinitewave.ca 를 참조한 Speex (Q10)의 주파수 응답
src.infinitewave.ca 를 참조한 Speex (Q14)의 Sweep 파형
src.infinitewave.ca 를 참조한 Speex (Q14)의 주파수 응답

Q10을 사용하다고 하면 사실상 청음하지 못할 정도의 노이즈가 발생하고 (보라색으로 보이는 영역은 -120db정도로의 크기로서 사실상 청음하기 힘들다.), Q14는 Sox보다는 못하지만 극히 적은 리샘플링 노이즈를 가지고 있다. 하지만 기본적으로는 리샘플링을 하지 않게 설정해서 쓰는 오디오파일들은 이런 리샘플링 노이즈 없이 사실상 비트퍼펙트에 가까운 퀄리티를 사용할 수 있을 것이다.

참고해야 할 점은 Speex 리샘플러의 Q14모드는 자원을 꽤나 많이 먹는다. (라이젠 2600 기준으로 5%가량 먹는다는 보고가 있다.)

Pipewire 사용하기

Pipewire는 페도라와 같은 배포판에서는 기본으로 채용되었고, 다른 배포판들도 쉽게 적용할 수 있다. Pipewire는 기본적으로 Pulseaudio의 API와 호환되기 때문에 애플리케이션 부분에서는 따로 건드릴 필요가 없다는 점도 중요하게 작용한다.

배포판에 따라서 pipewire, pipewire-pulse 패키지를 깔게 되면 pulseaudio를 삭제하고 이것으로 대체될 것이다. 만약 기본 설정으로 쓴다면 건드릴 필요가 없겠지만, 우리가 원하는 결과를 얻기 위해서 몇 가지 설정을 바꿀 필요가 있다.

Pipewire는 유저별로 동작하기 때문에 ~/.config/pipewire 폴더에 설정파일들을 놓으면 되는데, 기본적으로는 Pipewire 위키를 참조하는 게 편하다. 여기서는 몇 가지 수정할 법한 부분들을 소개하겠다.

pipewire.conf

default.clock.rate          = 48000
## 기본 샘플링 레이트 설정이다. 48000hz가 기본값이다.
default.clock.allowed-rates = [ 44100 48000 96000 ]
## 대체 샘플링 레이트 설정이다. 기본적으로는 꺼져 있지만 설정을 바꿀 수 있는데, 자기가 사용하는 장치들의 공통분모를 뽑아내는 것을 권장한다. (기기별 설정을 이후에 바꿀 수는 있다.)
default.clock.quantum       = 1024
default.clock.min-quantum   = 16
default.clock.max-quantum   = 2048
default.clock.quantum-limit = 8192
## 레이턴시와 연관된 설정 값들이다. 기본적으로는 건드릴 필요가 없지만 소리가 끊기거나, 좀 더 적은 레이턴시를 원할 때 사용할 수 있다. 이것들은 기본적으로 몇 샘플들을 버퍼에 저장할지와 연관되어 있는데, 48000hz의 샘플링 레이트를 사용할 때 0.3ms에서 42ms까지 유동적으로 버퍼를 조정한다는 의미이다. 음악을 재생할 거라면 의미가 없지만 10ms정도의 레이턴시라면 아주 짧고, 5ms정도라면 실시간으로 연주하는 환경이라도 거의 감지할 수 없는 수준이다.

pipewire-pulse.conf

resample.quality      = 14
## 리샘플러 품질 설정이다. 기본값은 4로 설정되어 있고, 이게 문제가 있다고 생각한다면 10이나 14 정도로 올려서 쓰는 것도 좋다.

Wireplumber

Wireplumber는 pipewire를 위한 세션 관리자이다. Pipewire가 오디오 스트림을 관리한다면 이것은 장치를 관리하는데, 각각의 장치별로 pipewire의 설정을 조정할 수 있다. Lua기반 스크립팅을 사용하므로 간단한 설정 이외의 것을 하고자 한다면 Lua를 배울 필요가 있다.

이를테면 여기서 이야기했던 HUD100에 하드웨어 볼륨을 적용하고, 리샘플링 퀄리티를 높이고 샘플링 레이트를 조정하고자 한다면 udev를 수정하지 않고 alsa_monitor.rules을 아래와 같이 설정하면 된다.
  {
    matches = {
      {
        { "device.nick", "matches", "earstudio HUD100" },
      },
    },
    apply_properties = {
      ["device.profile-set"] = "radsone-hud100.conf",
      ["audio.allowed-rates"]    = "44100, 48000, 96000, 192000, 384000",
      ["audio.format"]           = "S32LE",
      ["api.alsa.use-ucm"]       = false,
      ["resample.quality"]       = 14,
    },
  },

모니터링하기

Pipewire는 몇 가지 툴을 제공하는데, 설정이 의도한 대로 잘 돌아가는지를 보고 싶으면 pw-cli ls를 사용해서 현재 설정값들을 볼 수 있다. 현재 재생 상태를 보고 싶으면 pw-top를 사용할 수 있다.

pw-top을 사용한 예

위 그림을 보면 파이어폭스에서 48000hz로 오디오를 출력하고 있고, 이것이 HUD100으로 나가고 있는 것을 볼 수 있다.

신고공유스크랩
idletalk idletalk님 포함 6명이 추천

댓글 12

댓글 쓰기
profile image

오... 리눅스에서의 음감! 좋은 글 감사합니다.

02:49
22.04.02.
profile image
아... 복잡해보이네요
그냥 윈도나 안드로이드에서 '비트퍼펙트' 활성화 하는것에
만족해야겠어요..

비트퍼펙트 활성화 유무에 따라 음질 차이 매우 크다는걸
모르는 분들이 거의 대부븐이고 방법도 모르는 경우가 많아
안타까워요 ㅠ
11:02
22.04.02.
profile image
zlzleking 작성자
newdawn
이게 좀 그렇습니다. 몇 가지 앱만 사용한다면 윈도우나 안드로이드도 비슷하게 사용하는 게 가능합니다. 하지만 브라우저나 게임과 같은 환경에서 리샘플링 없이 사용하는 것까지를 목표로 둔다면 좀 힘듭니다. (안드로이드는 기기에 따라서 비트퍼펙트란 게 원칙적으로 불가능하기도 합니다.) 문제는 해당 OS들의 오디오 서버의 리샘플링 품질은 꽤나 좋지 않기 때문이죠.

이를테면 윈도우에서 foobar나 aimp로 음악을 듣는 것 까지는 비트퍼펙트가 됩니다. 근데 유튜브를 본다거나 유튜브 뮤직을 쓴다거나, 스포티파이를 듣는다고 가정해 보면 좀 더 복잡해집니다.

뭐 가장 좋은 것은 해당 OS들이 리눅스 수준의 커스터마이징을 지원하는 것이겠지만 이것 또한 현실적인 이야기는 아닙니다.
11:19
22.04.02.
profile image
아...
말씀하신 오디오전용플그램 외의 믄제가 있네요..

간과했습니다 ㄷㄷ

덕분에 한번 더 복기하고 갑니다.
11:23
22.04.02.
profile image
좋은 글 감사합니다. Core Audio (macOS)도 이런걸 지원하는지 궁금하네요. 한번 찾아봐야겠습니다.

그래요 이런게 필요합니다. 대체 샘플링레이트 얼마나 깔끔합니까. Bgm이 깔리지 않은 상황에선 dac가 지원하는 아무 (폐급이 아닌) 샘플링레이트든지 비트퍼펙트로 보내줄 수 있어야지요. Bgm 섞이면 그대로 출력하고요.

비트퍼펙트로 보내주면 좋기야 하겠지만 간단히 생각해봤을때 bgm을 하드웨어 볼륨만 가지고 비트퍼펙트로 보내고 있는데 효과음이 섞여서 클리핑이 뜨면 또 어떻게 될지 궁금합니다. (저는 그냥 소프트웨어 볼륨으로도 충분하다 생각합니다)

Pulseaudio가 Speex Q1을 기본으로 사용하나요? Q1 사진 올려두셨길래요. Q14나 sox는 고주파 알아서 하이컷하는것같은데 맞을까요? 22050HZ 이후에 사인스윕이 아무 소리도 안 내는 것 같아서요
12:50
22.04.05.
profile image
트리거왕
Q1 그래프 신기하네요. 김도헌교수님 버즈프로 리뷰에서 12000hz가 나올때 10000만큼 뺀 2000hz가 나오는 aliasing frequency가 나온다고 해서 단점으로 꼽으셨는데, 어떻게 딱 10000만큼 낮은게 나오지?싶었거든요. Q1 그래프 보니까 대충 7000hz 낮은 주파수에 aliasing frequency가 생기는것같은데 진짜 이게 리샘플링 과정에서 생길 수 있는 문제구나 싶습니다. 맥이야 리샘플러가 괜찮겠지만 윈도우 리샘플러는 어떨지도 궁금하네요.

재미있는 글이었습니다.
12:56
22.04.05.
profile image
zlzleking 작성자
트리거왕

Coreaudio는 해당 기능을 지원하지 않습니다. 대신 리샘플러 품질이 pulse나 윈도우보다는 좀 더 좋습니다. 그리고 해당 기능을 사용했을 때도 소프트웨어 믹서 자체는 작동하기 때문에 섞이는 와중에는 비트퍼펙트가 아닌 게 맞습니다. (당연히 제 경우에는 32비트 정수 형식으로 변환하니까 하나만 출력하더라도 비트퍼펙트는 아닙니다. 그게 품질상 문제가 있는 것도 아니고요.) 그러라고 오디오 서버를 쓰는 거니까요. 그리고 MPD와 같은 일부 구현에서는 소프트웨어 볼륨의 품질이 좋지 않기 때문에 가능한 한 하드웨어 볼륨을 쓰게 만드는 게 좋긴 합니다.

pulse의 기본 세팅은 배포판마다 다를 수 있습니다마는 일단은 Q1-float가 기본설정입니다. 사유는 위에 적었듯이 Arm SBC와 같은 초저사양 기기들에도 대응하기 위해서입니다. 그리고 해당 그래프들은 96khz를 44.1khz로 "다운샘플링"한 테스트이기 때문에 22k 이상이 안 나오는 게 맞습니다. (어차피 제대로 설계한 DAC라면 가청 주파수 외의 성분을 롤오프해서 없애버릴 거라고 보긴 합니다.)

14:18
22.04.05.
profile image
zlzleking 작성자
zlzleking

Windows10.png

 
 해당 테스트에서 윈도우 10 리샘플러의 결과인데, 위에 나온 모든 것보다 좋지 않습니다. 
  
 Speex Q1이나 이것 정도는 문제점을 청음할 수 있다고 생각합니다. (저기서 보라색 점선이 -100db정도, 파란색이 -140db정도를 나타내므로 실질적인 청음 환경에서는 차이점이 없다고 봅니다만 주황색이나 노란색 정도가 있다면 이야기는 달라집니다.) 
  
 그건 그렇고 며칠 전에 Radsone에 엔드포인트 이름때문에 펌웨어를 좀 고쳐달라고 메일을 보냈는데, 아무 연락이 없는 걸 보니 물건너간 듯 합니다.

14:21
22.04.05.
profile image
zlzleking
어 저건 좀.... 심각하네요. 좋은 자료 감사합니다.

리샘플러를 어떻게 만들었길래 저런지 궁금할 지경이네요.
15:57
22.04.05.
profile image

리눅스는 94년부터 슬랙웨어를 가지고 있던 컴 한대에는 올려서 구경하곤했습니다.  
몇년간 집의 메인 컴에 사용하기도 하기요.  
근데 결국은 윈도우로 돌아서지 않을 수없더군요. 게임은 안하는데요.  
커뮤니티 기반의 오픈 시스템 한계상, 멀티미디어에서 윈도우와의 격차가 크더군요. 
특히 하드웨어 지원문제는.... 내가 시간들여서 할 수도 없고..... 
결국 포기하고 개인적으로 사용하는 컴에는 모두 윈도우를 쓰고 있습니다.  
실험용 컴에는 여전히 리눅스를 쓰고 있구요. 윈도우가 메세지 방식이라  
정확한 타이밍 제어같은 부분은 리눅스가 믿을만 해서요.   
  

01:33
23.04.14.
profile image
zlzleking 작성자
재인아빠
저도 음감이나 평소 환경은 리눅스(KDE)가 나은데, 플루이드 모션 같은 영상쪽 때문에 평소에는 윈도우를 쓰고 있습니다 ㅎㅎ...

하드웨어 쪽은 가능하면 표준화된 걸 쓰고, 부족한 건 config 잘 해서 해결하면 되는데 독점 드라이버가 필요한 것은 안 되더라고요
21:16
23.04.14.
profile image
zlzleking
아무래도 사용자가 얼마 안되니, 제조사들이 그냥 무시를 하게 되는 것 같아요.
22:26
23.04.14.
권한이 없습니다. 로그인
에디터 모드

신고

"님의 댓글"

이 댓글을 신고하시겠습니까?

댓글 삭제

"님의 댓글"

이 댓글을 삭제하시겠습니까?

공유

퍼머링크