SVX日記

2004|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|

2020-04-21(Tue) PulseAudioでBGM付きリモート呑み会に

  リモートお茶会も、リモート呑み会も楽しく実行できたのだが、ひとつだけ物足りなかったことが、BGMを流せないことだった。Zoomにはサウンドの共有機能があるのだが、音声がブツブツと切れてしまう症状が、どちらの会でも出てしまい、音楽として楽しむことができないレベルであった。

  まぁ、別にBGMが必須というわけではないのだが、以前、アニソンのサビのメドレー動画を肴に酒を呑んだのが意外と楽しかったのだよな。それに、BGMは基本的に流しっぱなしにするので、会話の流れで「おっ。この曲さぁ…」みたいに会話が弾む材料になるのも期待できる。無理矢理やるなら、実際に部屋に曲を流し、マイクから入力するという方法もあろうが、やはりそれでは音質の低下は激しいであろう。

  しかし、よく考えれば、Linuxのデスクトップ環境では、ずいぶん前からPulseAudioというソフトウェアミキサが標準となっている。そいつを使えば、Zoomに渡す前のマイク音声にBGMをミキシングすることくらい、できそうなもんだ。しかし、そもそも自分はPCのサウンド機構に非常に疎い。ひとつ、これを機にガッツリと勉強してみるか。

  というわけで、ガッツリ勉強して、ガッツリ理解したつもりになった。なので、覚え書きも兼ねて、ガッツリと解説してみることにする。

  まず、ウチのメインマシンであるノートパソコンの起動時の状態を図示すると、以下のようになる。ThinkPadA285をドッキングステーションに載せ、デスクトップ化した状態だ。

  画像の説明

  この状態だと2系統のサウンド入出力ハードウェアが存在することが読み取れる。ひとつは上側のドッキングステーションの機構だ。出入口はステレオ出力+マイク入力の4極の3.5mmジャックである。「ドック output monitor」というのが気になるが、それを無視すれば、非常に単純明快である。

  もうひとつが下側のノートPC本体の機構だ。出入口は同じくステレオ出力+マイク入力の4極の3.5mmジャックであるが、そこに挿入していない場合、ビルトインのスピーカと、ビルトインのマイクが有効になるのだ。やはり「本体output monitor」を無視すれば、非常によくある構図である。

  このように2系統のサウンドが存在していても、通常はどこか1箇所から入出力すればいいわけで、そのためにデフォルト入力と、デフォルト出力というものが設定できる。必ずしも、どちらかの系統に統一する必要はないが、現状、入出力とも本体側に設定してあり、ふたつの★はそれを示している。

  この状態は、PulseAudioのpacmdコマンドにより、以下のように確認することができる。

$ pacmd list-sources | grep -E "index:|name:|description"
    index: 0
	name: <alsa_output.usb-Generic_ThinkPad_Dock_USB_Audio-00.analog-stereo.monitor>
		device.description = "Monitor of ThinkPad Dock USB Audio アナログステレオ"
    index: 1
	name: <alsa_input.usb-Generic_ThinkPad_Dock_USB_Audio-00.analog-stereo>
		device.description = "ThinkPad Dock USB Audio アナログステレオ"
    index: 2
	name: <alsa_output.pci-0000_04_00.6.analog-stereo.monitor>
		device.description = "Monitor of Family 17h (Models 10h-1fh) HD Audio Controller アナログステレオ"
  * index: 3
	name: <alsa_input.pci-0000_04_00.6.analog-stereo>
		device.description = "Family 17h (Models 10h-1fh) HD Audio Controller アナログステレオ"
$ pacmd list-sinks   | grep -E "index:|name:|description"
    index: 0
	name: <alsa_output.usb-Generic_ThinkPad_Dock_USB_Audio-00.analog-stereo>
		device.description = "ThinkPad Dock USB Audio アナログステレオ"
  * index: 1
	name: <alsa_output.pci-0000_04_00.6.analog-stereo>
		device.description = "Family 17h (Models 10h-1fh) HD Audio Controller アナログステレオ"

  さて、ここで録音アプリケーションや、再生アプリケーションを実行すると、以下のようになる。

  画像の説明

  録音アプリケーションは、デフォルト入力からの音声をファイルに記録する。再生アプリケーション、いわゆるメディアプレーヤは、mp3ファイルなどの楽曲をデフォルト出力で演奏するわけだ。

  そして、昨今よくあるリモート会議ソフトウェアを実行すると、以下のようになる。

  画像の説明

  一般にウェブカメラを接続するのが常であり、それには音声入力用のマイクも備わっている場合が多いが、通常はそれでなく、ヘッドセットを使うことだろう。今回は、本体のジャックにヘッドセットをつないだ想定である。リモート会議ソフトウェアによってはソフト側で、入出力ポートを選ぶこともできるだろうが、通常はデフォルト入力と、デフォルト出力が選択され、その両方を同時に使うことになる。自分の発言はヘッドセットのマイクを通じてネットの向こうの相手へ、相手の発言はネットからヘッドセットを通じて耳へ、というわけである。

  さて、問題はここからなのだが、それに先立って、普段、歌の練習に使っているPCMレコーダ「DR-05X」をUSB接続してみる。先代の「DR-05」との違いのひとつが、この「PCとつなぐとサウンドデバイスになる」という点なのであった。一体、どんな時に使うのかと思っていたのだが、こういう時に使うのである。で、接続すると以下のようになる。

  画像の説明

  図のスペースの問題で、本体の機構はカットしたが、ちょうど入れ替わる形になった。つまり、USB接続をしているのものの、機構上は同じものということである。

  その上で何をしたいかというと、自分の発言にメディアプレーヤの出力するBGMを混ぜ、ネットの向こうの相手へ送りたいわけだ。シンプルに考えると、図のようになるわけだが、このようなことはできない。ではどうするか。ヌルデバイスの登場である。

  一番下にあるのがヌルデバイス。この追加は、何らかの物理的なデバイスを接続するわけではなく、以下のようなコマンドひとつでできる。

pacmd load-module module-null-sink sink_name=null.music

  今回は、BGMを流すのに使うということで「null.music」という名前を付けたが、ヌルデバイスがどんなものかというと、出力側の「null.music」に出力した音声が、入力側の「null.music.monitor」から出てくるので、それを入力に利用できる、というものである。そう。先ほどから気になっていた「xxxx.monitor」というのは、いずれも対応する出力先のデバイスに出力した音声を入力に利用できる、モニタデバイスというものなのだ。つまり、YouTubeを再生しながら、その音声をデジタル録音したりすることに使えるわけだ。

  しかし、それを使うためには、もうひとつ重要な概念がある。ループバックだ。ループバックとは、入力を出力に結びつけるものだ。ヌルデバイスには、出力がないので、ループバックで入力を別の出力に結びつける以外の使いみちはない。そして、結びつける際、ひとつの入力を複数の出力に結びつけてもいいし、複数の入力をひとつの出力に結びつけてもいい、というルールがある。そうだ、これだ、欲しかったのは。

  そして、一気に状況は加速する。さらに「null.mic_music」というヌルデバイスを追加し、ループバックでマイクの入力とメディアプレーヤの入力を、同じヌルデバイスに結びつけてやる。その上で、そのヌルデバイスのモニタデバイスの出力をリモート会議ソフトウェアに送ってやるのだ。つまり、以下のようになる。

  画像の説明

  これで一応の完成だ。各デバイスは、すべて音量調整が可能なので、発言とBGMの音量は、お好みに調整可能である。

  これを行うためのコマンドが以下。

# 「null.music」「null.mic_music」というヌルデバイスを追加する
pacmd load-module module-null-sink sink_name=null.music     sink_properties=device.description='Null_Music_Output'
pacmd load-module module-null-sink sink_name=null.mic_music sink_properties=device.description='Null_Mic_Music_Output'
# sourceとsinkの名前を知るために一覧を出力
pacmd list-sources | grep -E "index:|name:|description"
pacmd list-sinks   | grep -E "index:|name:|description"
# PCMレコーダからの音声とメディアプレーヤからのBGMを「null.mic_music」にミキシング
pacmd load-module module-loopback source=alsa_input.usb-TEAC_Corporation_TASCAM_DR_Series-00.analog-stereo sink=null.mic_music
pacmd load-module module-loopback source=null.music.monitor                                                sink=null.mic_music
# メディアプレーヤの出力は「null.music」へ、Zoomへの入力は「null.mic_music.monitor」から
pacmd set-default-sink   null.music
pacmd set-default-source null.mic_music.monitor

  しかし、もうひとつ問題がある。肝心の自分が音楽を聴けないことだ。Zoomは自分の発声をフィードバックしない。だから、音楽は自分用にもミキシングしてやる必要がある。

  最後はオマケだが、相手が聴いている音がどんなものなのかを、モニタできるようにもしてみる。そしてそれは、通常Zoomで使うヘッドホンではなく、別のヘッドホンから出力させる。最終的には、以下のようになる。

  画像の説明

  これを行うためのコマンドが以下。

pacmd load-module module-loopback source=null.music.monitor     sink=alsa_output.usb-TEAC_Corporation_TASCAM_DR_Series-00.analog-stereo
pacmd load-module module-loopback source=null.mic_music.monitor sink=alsa_output.usb-Generic_ThinkPad_Dock_USB_Audio-00.analog-stereo

  PulseAudioについて勉強するまでは、こんな複雑なことが実現できるなんて、予想にもしなかった。しかも、非常に単純なルールの組み合わせによって、である。確かに、この概念を理解するのはちょっと大変ではあるが、この概念を考えついたやつは頭いいなぁ。