2021년 2월 2일 화요일

[우분투의 사운드와 MIDI] PulseAudio 루프백(loopback)의 활용

  1. USB 마이크를 이용하여 내 목소리를 녹음하고 있다. 마이크에는 모니터링용 3.5 mm 스테레오 단자가 있어서 헤드폰을 연결할 수 있으나 녹음 중인 내 목소리는 들을 수가 없다. 
  2. USB 마이크를 이용하여 내 목소리를 녹음하고 있다. 유튜브에서 흘러나오는 음악을 배경으로 깔고 싶다면 어떻게 해야 하는가? 단, 음원에 대한 저작권 문제는 없다고 가정한다. 
  3. Behringer UCA200 오디오 인터페이스에 Alesis NanoPiano를 연결하여 녹음을 하면서 실시간으로 모니터링을 하고 싶다. 하지만 UCA200과 NanoPiano에는 헤드폰 출력 단자가 없다.
이러한 상황에서 PulseAudio의 module-loopback이 안성맞춤이다. 앞서 소개한 alsa_in과 alsa_out도 유사한 기능을 해 주지만, JACK client이기 때문에 반드시 JACK을 기동한 상태에서만 쓸 수 있다. 명령행 인터페이스(CLI)에서 arecord 명령을 사용하여 녹음하는 방법을 익히면서 실제로 이렇게 녹음을 할 일은 없을 것이라 생각했는데, 그게 그렇지가 않다. PulseAudio의 기능을 조금씩 익혀 나가면서 이를 CLI에서 잘 구사하면 리눅스의 사운드 재생과 녹음에 대한 기본 지식을 이해함은 물론 실무적으로도 매우 쓸모있는 기능을 익히게 된다.

PulseAudio에서는 매우 다양한 모듈을 로드하여 쓸 수 있다. 모듈을 로드하려면 'pactl load-module <module name> <parameters>' 명령어를 실행하면 된다. 현재 로드된 모듈이 어떤 것이 있는지를 확인하려면 'pacmd list-modules'를 입력한다. module-loopback이라는 모듈은 어느 소스의 오디오를 싱크로 되돌려 보내는 기능을 한다. 상세한 설명 및 파라미터 목록은 여기를 클릭해 보라.

2번 상황으로 돌아가 보자. 마이크에 대고 말을 하면서 녹음을 하다가 유튜브로 완전히 소스를 전환하고 싶다면, PulseAudio Volume Control에서 'Monitor of ...'를 선택하면 된다. 이렇게 하면 마이크에 대고 아무리 소리를 질러도 녹음이 되지 않는다. 그러나 내가 원하는 것은 유튜브에서 재생되는 음악을 배경으로 하여 나의 음성이 동시에 녹음되는 것이다. 

module-loopback을 로드하기에 앞서서 sink에 해당하는 오디오 기기를 결정해야 한다. 내 컴퓨터에는 어떤 sink가 있는가? 역시 CLI에서 확인해 보자. 내장 사운드 카드에 헤드폰을 연결한 상태에서 USB 마이크만 꽂았다.

$ pacmd list-sinks | grep -e 'name:' -e 'index:'
  * index: 0
	name: <alsa_output.pci-0000_00_1b.0.analog-stereo>
    index: 1
	name: <alsa_output.usb-Burr-Brown_from_TI_USB_audio_CODEC-00.analog-stereo>

별표로 시작하는 0번 인덱스 기기 바로 현재의 default sink이다.

$ pactl load-module module-loopback sink=alsa_output.pci-0000_00_1b.0.analog-stereo
24

일단 24번이라는 모듈 번호를 기억해 두라. 나중에 모듈을 내릴 때 필요하다. 실은 이 번호를 기억하지 못해도 'pacmd list-modules' 명령으로 알 수 있다. 웹브라우저를 작동시켜서 유튜브 동영상 재생을 시작한 다음, 명령행에서 녹음 명령(arecord)을 내린다.

$ arecord -f cd -d 300 test.mp3

300초, 즉 5분 동안 녹음을 하므로 PulseAudio Volume Control에서 설정을 조절할 시간은 충분히 있다. 먼저 Input Devices 탭에서 'Monitor of 내장 오디오 아날로그 스테레오'와 'PCM2912A Audio Codec 아날로그 모노'(USB 마이크 종류에 따라 표시가 다를 것임)의 입력이 전부 활성화되어 있는지, 신호 입력에 따라 레벨이 움직이고 있는지를 확인한다. 전자는 컴퓨터 내부에서 발생하는 소리, 즉 유튜브 소리를 입력하게 하는 매우 중요한 요소이다.

그 다음으로는 PulseAudio Volume Control의 Recording 탭을 선택하여 다음과 같이 되어 있는지 확인한다. arecord 명령을 실행하지 않았다면 위의 것만 보일 것이다.

상단의 'Loopback to 내장 오디오'에는 무엇을 선택하여야 할까? 고를 수 있는 것은 다음 중 하나이다.

 

정답은 두 번째인 'PCM2912A Audio Codec 아날로그 모노'이다. 이렇게 연결하면 마이크로 입력되는 음성이 default sink로 선언한 내장 오디오로 들어가게 된다. 녹음 프로그램인 arecord의 실행 여부와 상관없이 마이크에 대고 말한 것이 음성이 내장 오디오(헤드폰)를 통해 나올 것이다. 

module-loopback을 로드할 때 아예 source를 지정해도 된다. 'pacmd list-source' 명령어를 이용하여 source의 정확한 명칭을 알아낸 뒤 'pactl load-module' 명령에서 'source=NAME' 처럼 파라미터로 제공한다. 아래 사례에서는 sink가 정확히 작동하는 것을 알고 있기에 따로 지정하지 않았다.

$ pacmd list-sources | grep -e 'name:' -e 'index:'
    index: 0
	name: <alsa_output.usb-Burr-Brown_from_TI_USB_audio_CODEC-00.analog-stereo.monitor>
  * index: 1
	name: <alsa_input.usb-Burr-Brown_from_TI_USB_audio_CODEC-00.analog-mono>
    index: 2
	name: <alsa_output.pci-0000_00_1b.0.analog-stereo.monitor>
    index: 3
	name: <alsa_input.pci-0000_00_1b.0.analog-stereo>
$ pactl load-module module-loopback source=alsa_input.usb-Burr-Brown_from_TI_USB_audio_CODEC-00.analog-mono
22

하단의 'ALSA plugin [aplay]: Alsa Capture from'을 연결하기 위해 선택 사항도 이와 동일한 네 가지이다. 2번과 3번을 고르면 마이크 음성 입력을 잘 받아들여 녹음이 된다. 그러나 유튜브에서 재생하는 음악 소리를 같이 녹음하려면 3번의 'Monitor of 내장 오디오 아날로그 스테레오'를 선택해야 한다.

눈치가 빠른 사람은 녹음 중에 조금 부자연스러운 것을 느꼈을 것이다. 스피커에서 나오는 내 음성이 조금 뒤늦게 나온다는 것을. 이는 module-loopback을 로드할 때 'latency_msec=5' 정도의 파라미터를 주면 된다. 기본값은 200(단위는 msec)이니 평균적인 청력을 지닌 사람이라면 레이턴시를 느낄 수 있다. 파라미터를 바꾸어서 모듈을 다시 로드하려면 'pulseaudio -k' 명령을 입력하여 PulseAudio를 완전히 재시작하거나, 다음의 명령을 입력하여 방금 올렸던 모듈을 내린 다음 다시 pactl load-module 명령어를 원하는 파라미터와 함께 실행한다. 24라는 모듈 번호는 실제 상황에 맞게 입력해야 한다.

$ pactl unload-module 24

이상과 같이 PulseAudio의 루프백 기능을 쓰면 어렵지 않게 두 개(혹은 그 이상?)의 오디오 디바이스를 연결할 수 있게 된다. 좀 더 고급 기능을 맛보려면 가상 싱크(혹은 소스)를 사용하면 된다는데 아직 그 필요성을 느끼지 못하고 있다. 다음의 웹사이트를 숙독하면 많은 발전이 있을 것이다!

Emma Joe Anderson - PulseAudio Loopback

여기에서 설명하는 주요 개념만 간략하게 소개해 보겠다. 보편적으로 쓰이는 정의와는 약간 다를 수도 있다. 디바이스는 마이크, 스피커, 헤드폰과 같은 물리적 오디오 장치이다(USB 오디오 인터페이스는 디바이스가 아니다. 흠...). Virtual sink는 virtual device이다. PulseAudio는 근본적으로 디바이스(non-device)와 디바이스를 정확히 1:1로만 연결한다. 두 개의 디바이스를 연결하려면 virtual sink가 필요하고, 두 개의 디바이스를 연결하려면 loopback을 써야 한다. 루프백은 정확히 하나씩의 입력과 출력을 갖지만, 디바이스는 원하는 수만큼의 루프백을 가질 수 있다.

주요 개념을 이해할 수는 있는데 Anderson의 웹사이트에서 그래프를 그려 설명하는 방식은 아직 어렵다. Virtual device가 필요한 상황은 무엇이 있을까?  좀 더 쉬운 사례를 찾아야 할 듯.

출처: Emma J. Anderson, PulseAudio Loopback. 뭔 말인지 아직 잘 모르겠다. Dig는 구글 행아웃에서 돌아가는 애플리케이션인 모양이다. V1-V3은 virtual sink이다. 


업데이트 - 쉬운 일을 어렵게 하기?

StackOverflow 사이트에 게시된 질문과 답 중에 이런 것이 있다.


내가 하고 싶은 일과 다를 것이 없다. 유튜브에서 나오는 소리와 마이크로 입력되는 소리를 한꺼번에 녹음하려는 것. 그리고 녹음되는 소리를 직접 듣고 싶은 것. 다른 점이 있다면 Audacity를 쓰느냐 혹은 명령행에서 arecord를 쓰느냐의 차이 뿐이다. 그런데 이 웹사이트에 올라온 답변에서는 virtual sink를 사용한 상당히 복잡한 방법을 쓰도록 하였다.


인용한 그림에서 빨간색 선은 loopback, 네모는 virtual sink이다. module-null-sink 2개와 module-loopback 3개를 로드하는 것은 그렇다 치더라도, PulseAudio Volume Control에서 서로를 정확히 연결하는 방법이 너무 복잡하다. 이 과정을 이해할 수 있다면 PulseAudio로 못할 것이 없겠네! 답변을 제시한 Dodgyrabbit이 남겨놓은 참고 사이트를 소개한다. 전부 한 번씩은 방문한 적이 있던 곳이다.

차라리 Ask Ubuntu의 Re-directing applications to virtual sinks가 조금 더 이해하기 쉽다. 안, 어쩌면 StackExchange의 How to create a virtual audio output and route it in Ubuntu-based distro가 virtual sink 및 loopback을 이해하기에 더 좋은 자료라고 생각된다. 질문자가 요구하는 사항은 이러하다.

  • 게임을 하는 화면 및 사운드를 OBS로 녹화한다.
  • 게임을 하는 동시에 음성 채팅을 하는데, 이 소리는 OBS로 녹화되지 않게 하고 싶다.
OBS는 특정 디바이스로 들어오는 소리를 전부 다 녹음을 할 뿐이지, 특정 애플리케이션의 오디오만을 택하지는 못한다. game_sink라는 virtual sink를 만들고(module-null-sink), 이것의 모니터 출력(game_sink.monitor)를 헤드폰으로 루프백하는 것이 핵심이다. 음... 이건 좀 이해가 갈 것 같다.

 

댓글 없음: