UAC GadgetでNintendo Switchの音声出力をRaspberry Piに取り込む

UAC GadgetでNintendo Switchの音声出力をRaspberry Piに取り込む

前回の記事でHDMI映像入力をRaspberry Piで扱う方法を紹介し、その最後に音声の取り込みについて、まだ課題が残っていると書きました。 HDMI入力からの音声取り込みといった、本質的な課題の解決を試みているものの、なかなかに難しい問題に直面しているので、対象を限定して部分的解決に挑みます。

主に今HDMI入力の対象として使おうと思っているデバイスは、Nintendo Switchです。 なので、Nintendo Switchの音声出力に限定して、それをRaspberry Piで取り込むことだけを目的とし、音声が取り込めていない問題を解決していきます。

目次

Open 目次

  1. Nintendo Switchの音声出力
    1. スピーカー
    2. 3.5mmイヤホンジャック
    3. HDMI
    4. USB
  2. UAC (USB Audio Device Class)
  3. USB Gadget API
  4. UACデバイスシミュレート
    1. Pro Controller + UAC
  5. 音声取り込み
  6. 映像と音声をWebRTC
  7. まとめ

Nintendo Switchの音声出力

Nintendo Switchには、4つの音声出力方法があります。これらのいずれかから音声を取り込む必要があります。

スピーカー

body-switch01-front

引用元: Nintendo Switch|任天堂

主にテーブルモードや、携帯モードでプレイする時に音声が出力されます。本体前面に搭載されたステレオスピーカーから音声が出力されますが、これを取り込むにはマイクを用いる必要があり、 遅延の発生とノイズが乗るので現実的ではありません。

3.5mmイヤホンジャック

スピーカーからではなく、本体上部のヘッドホンマイク端子から音声を出力することもできます。スピーカー出力の音声をマイクを使って取り込むよりも、イヤホンジャックの出力を取り込んだ方がノイズは少ないですが、アナログ・デジタル変換が必要なので、やや手間がかかります。

HDMI

TVモードで映像を出力しているとき、スピーカーの代わりにHDMIケーブルを通して音声がテレビから出力されます。信号がデジタルなのと、サラウンドに対応しているため高音質ですが、機器に取り込む方法が限定されるため、障壁が高いです。

USB

body-switch02-front

引用元: Nintendo Switch|任天堂

本体底面のUSB Type-C端子や、Nintendo SwitchドックのUSB端子に接続しているUSBサウンドデバイスから、音声を出力する方法です。Sound Blaster G3などの製品を接続して、イヤホンジャックからの出力より高品位な音声を楽しむことができるそうです。 通信はUAC(後述)というプロトコルを通して、音声出力をデジタル信号でやり取りしています。UACで取り込みたい機器と通信ができれば、最もこれが手軽かつノイズの少ない出力が得られます。

UAC (USB Audio Device Class)

USB Audio Devices Rev. 3.0 and Adopters Agreement | USB-IF

USB接続のサウンドカードや、USB Type-C接続のイヤホンなどが採用しているUSB経由で音声を転送するプロトコルです。 マイクなどの入力装置と、スピーカーなどの出力装置とのどちらとも、このプロトコルで転送できます。 USB Audio Device Classには大きく分けて、Class 1(UAC1)、Class 2(UAC2)、Class 3(UAC3)の3つの実装レベルの異なったクラスが定義されています。 WindowsやmacOS、LinuxやAndroid含め、ほとんどのOSに標準でUAC1とUAC2のドライバが導入されています。

USB Gadget API

聞き覚えがありますね。スマホでNintendo Switchを操作する手法を紹介したの記事で登場しています。 聞いたことない人はそちらをチラッとみていただくとして、そこに挙げたドキュメント記載の例に**sound subsystem (for audio gadgets)**があり、USB Audio Device Classのシミュレートもできるのです。 これでRaspberry PiをUACデバイスとして振舞うようにできれば、Nintendo SwitchのUSBサウンド出力を取り込めるかもしれません。

UACデバイスシミュレート

物は試しということで、早速Nintendo SwitchとRaspberry Piを接続してconfigfsでUAC1デバイスを作ってみます。 手法を紹介したの記事と同様、/boot/config.txtと/etc/modulesに追記を済ませておく必要があります。 接続はシンプルに、それぞれのUSB Type-CポートにUSB 2.0 Type-Cケーブルを接続するだけです。

root権限でこれを実行すると、Nintendo SwitchがRaspberry Pi 4をUSBサウンドデバイスとして認識しました。

usb audio device detected

uac1.0の部分をuac2.0に書き換えることで、UAC2 Gadgetもシミュレートできますが、試したところNintendo SwitchのUSBサウンドデバイスは、USB GadgetにおいてはUAC1の出力装置のみを認識していました。 また、sudo modprobe g_audioでもUAC Gadgetは作成できますが、こちらもUAC2なので認識しませんでした。

Pro Controller + UAC

Nintendo SwitchはPro Controllerのシミュレートに関しては、製品ID(idProduct)と製造元ID(idVendor)を純正のものと同一にする必要がありました。 しかしUSBサウンドデバイスに関しては、なんでもいいみたいです。純正品やライセンス商品が販売されていないからでしょうか。

そして、なんと、Pro Controllerを模したUSB GadgetにUACの機能を追加しても、認識しちゃうのです!

この状態で、1.3inch LCD HATでの入力を試してみると、ちゃんとUSBサウンドデバイスとPro Controllerとして認識されています。

pro controller and audio device

音声取り込み

UAC1 Gadgetとして振る舞っている間、ALSAにはUAC1Gadgetという名前のサウンドカードとして認識されます。

pi@raspberrypi:~ $ lsmod | grep uac
usb_f_uac1             16384  2
u_audio                20480  1 usb_f_uac1
libcomposite           57344  11 u_audio,usb_f_uac1
udc_core               53248  4 dwc2,u_audio,libcomposite,usb_f_uac1
pi@raspberrypi:~ $ cat /proc/asound/cards
 0 [ALSA           ]: bcm2835_alsa - bcm2835 ALSA
                      bcm2835 ALSA
 1 [UAC1Gadget     ]: UAC1_Gadget - UAC1_Gadget
                      UAC1_Gadget 0
pi@raspberrypi:~ $ arecord -l
**** List of CAPTURE Hardware Devices ****
card 1: UAC1Gadget [UAC1_Gadget], device 0: UAC1_PCM [UAC1_PCM]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

以下のコマンドでUAC1ガジェットから、ステレオ2チャンネル、サンプリング周波数48000Hz、量子化ビット数 符号付き16ビット、VUメーターステレオ表示しつつ、/tmp/rec.wavに音声ファイルを保存できます。

arecord -v -D hw:UAC1Gadget -c2 -r 48000 -f S16_LE -t wav -V stereo /tmp/rec.wav

ちゃんと動きました。

arecord recording

映像と音声をWebRTC

前回の記事でも扱った映像のWebRTC配信に、音声も乗っけてみます。

HDMI出力はUSB Type-C端子からは取り出せないので、Nintendo Switchドックに接続する必要があります。 そして、Raspberry Pi 4とNintendo Switchドックは裏面のUSB 3.0ポートに、以下のようなUSB Type-A to USB Type−C 3.0ケーブルを使って接続します。 消費電力の関係で、USB 2.0ポートやUSB 2.0ケーブルを使うと電力不足でRaspberry Piが落ちます。 また、Nintendo SwitchをDockから抜き差しするとRaspberry Piへの給電が止まるので、間にセルフパワーのUSBハブを噛ませた方がいいです。 以下は実際に使ってるUSBケーブルとUSBハブです。

Amazon.co.jp: Anker USB Type C ケーブル PowerLine USB-C & USB-A 3.0 ケーブル Xperia / Samsung Galaxy / LG / iPad Pro MacBook その他 Android Oculus Quest 等 USB-C機器対応 1.8m ブラック: 家電・カメラ

Amazon | オリコ ORICO 4ポート USB3.0ハブ アルミ製 セルフパワー 12V/2A電源 ブラック A3H4-BK | オリコ(ORICO) | USBハブ 通販

ソフトウェアは今回も動作確認できればいいので、デモコードを用います。

前回はgstwebrtc-demosのコードを用いてV4L2デバイスをそのまま扱ったところ、再接続してから映像が取得できなくなるという問題を抱えていました。 これはMMAL(Multi-Media Abstraction Layer API)の手続きを正しく実行することで解決できます。そして、それをやってくれるGstreamerのelement(プラグイン)が、前回少し登場したgst-rpicamsrcです。

thaytan/gst-rpicamsrc: GStreamer element for the Raspberry Pi camera module

これをv4l2srcの代わりに用いることで、再接続しても映像の取得が正しく行えるようになります。 加えて、このリポジトリのexamplesにWebRTCのデモがあるので、それをちょっと編集して音声を乗っけていきます。

gst-rpicamsrc/webrtc-unidirectional-h264.c at 79860a0b2a0f3beef6ccfab0cf7d531e55e3b06c · thaytan/gst-rpicamsrc

diff --git a/examples/webrtc-unidirectional-h264.c b/examples/webrtc-unidirectional-h264.c
index b8a716d..b9674b3 100644
--- a/examples/webrtc-unidirectional-h264.c
+++ b/examples/webrtc-unidirectional-h264.c
@@ -185,10 +185,12 @@ create_receiver_entry (SoupWebsocketConnection * connection)
 
   error = NULL;
   receiver_entry->pipeline = gst_parse_launch ("webrtcbin name=webrtcbin stun-server=stun://" STUN_SERVER " "
-      "rpicamsrc bitrate=600000 annotation-mode=12 preview=false ! video/x-h264,profile=constrained-baseline,width=640,height=360,level=3.0 ! queue max-size-time=100000000 ! h264parse ! "
-      "rtph264pay config-interval=-1 name=payloader ! "
-      "application/x-rtp,media=video,encoding-name=H264,payload="
-      RTP_PAYLOAD_TYPE " ! webrtcbin. ", &error);
+      "rpicamsrc preview=false ! video/x-h264,profile=constrained-baseline,width=1280,height=720,level=3.1 ! queue max-size-time=100000000 ! h264parse ! "
+      "rtph264pay config-interval=-1 ! "
+      "application/x-rtp,media=video,encoding-name=H264,payload=96 ! webrtcbin. "
+      "alsasrc device=hw:UAC1Gadget ! audioconvert ! audioresample ! queue ! opusenc ! "
+      "rtpopuspay ! queue ! "
+      "application/x-rtp,media=audio,encoding-name=OPUS,payload=97 ! webrtcbin. ", &error);
   if (error != NULL) {
     g_error ("Could not create WebRTC pipeline: %s\n", error->message);
     g_error_free (error);

上記パッチを当て、Readmeに従ってsudo make installまでできていると、**examples/**にWebRTCデモの実行ファイルができているはずです。

ビルド前の依存パッケージの導入と実行時の注意は、前回の記事を参考にしてください。 また、追加でsudo apt install gstreamer1.0-alsaをしてALSAのプラグインも導入しておく必要があります。

OPENSSL_CONF= ./examples/webrtc-unidirectional-h264で実行し、Chromeでみてみると、音声もWebRTCで転送できていることが確認できます。

まとめ

とりあえずNintendo Switchの音声出力が取れました。

前々回はNintendo Switch Pro ControllerのWeb対応。 前回はNintendo Switchゲーム画面のWeb対応。 今回はNintendo Switchゲーム音声のWeb対応。

何を作ろうとしてるか、だんだんワクワクしてきましたね?

Related Posts

KVMでQSVするためIntel HD Graphicsパススルーするー

この記事は Linux Advent Calendar 2014 12日目の記事です。12月も中頃となり寒い日が続きますね。みなさん体調はいかがでしょうか。先日の こたつを温める実験 で十分な...

read more

Intel QSVのH.264エンコードをLinuxで!

前回の記事 から1ヶ月以上空いてしまいました。遅ればせながらで申し訳ありません。続編です。 Intel QSVは高速にある程度の画質のエンコードできてよいです。とても。今回はKVMでIntel H...

read more

LinuxでQSVとH.264のエンコード対決

先日の記事、でLinuxでH.264の動画をエンコードできることを紹介しました。 そのベンチマークをとってみました。QSVでのエンコードとlibx264を用いたエンコードの比較となります。今回エン...

read more
Raspberry Pi2にOSMC入れてKodi(旧:XBMC)日本語化するまで

Raspberry Pi2にOSMC入れてKodi(旧:XBMC)日本語化するまで

今月頭の発表で一気に盛り上がりを見せた Raspberry Pi 2 Model B 。もちろん発売日に購入しました。 手元にはRaspberry Pi BとGalileo Gen2の2つのLinux...

read more
KodiとChinachuで地デジLive視聴 on Raspberry Pi2 w/ OSMC

KodiとChinachuで地デジLive視聴 on Raspberry Pi2 w/ OSMC

どうも、Raspberry Pi2で遊ぶ毎日が続いております。 Raspberry Pi model B(2ではない)にRaspbmcを入れて昨年の夏頃からChinachu経由で地上デジタル放送を視聴...

read more
KodiでChinachuの録画を観るAdd-on作った

KodiでChinachuの録画を観るAdd-on作った

Raspberry Pi2でKodi(旧:XBMC)が快適に動き、地デジのLIVE視聴環境として優れているので、 Chinachuの本領である録画した動画の視聴したみが高まってきました。Kodiに...

read more
Kodi Chinachu PVRアドオンでRasPi2/Android TVをテレビに

Kodi Chinachu PVRアドオンでRasPi2/Android TVをテレビに

暑い日が続きますね。こういう日はエアコンの効いた部屋でだらだらとテレビを見たいものです。 しかしテレビをもっておりません。27インチのモニタを持っているのみです。ただ、今年2月に記事にしたように、...

read more
クリスマスなのでLinuxでQSVエンコードする

クリスマスなのでLinuxでQSVエンコードする

こちらは DTV Advent Calendar 21日目の記事です。みなさん録画データの管理はどうしていますか? 視聴したら消す人もいれば、視聴しても残しておく人、視聴してない詰みTSがたくさん...

read more
Harekaze for Kodi (pvr.chinachu) 4.0.0 リリース

Harekaze for Kodi (pvr.chinachu) 4.0.0 リリース

KodiとChinachuがシームレスに連携し、快適に地デジが視聴できるアドオン Harekaze for Kodi(pvr.chinachu) をKodi 17 Krypton に対応したバージョン...

read more
HDMI入力をRaspberry Piで駆使する

HDMI入力をRaspberry Piで駆使する

昨今の衰えることのない技術トレンドに追従すべく、映像配信とかやりたいなーと思っていた2019年。 めっきり時間がなく何もできず、気付けば2020年になっていました。今年も時間がないだろうなぁと思っ...

read more
Raspberry PiでHDMIディスプレイを調査する[EDID/CEC]

Raspberry PiでHDMIディスプレイを調査する[EDID/CEC]

みなさん、テレビやディスプレイに備わるHDMIの情報を確認する必要に迫られることはありませんか? 1年に一度くらいはありますよね。映像がうまく映らなかったり、操作がうまくいかなかったり。 そんな時にパ...

read more
LibreELECで地デジを楽しむためにMirakurunとEPGStationを一発で動かす

LibreELECで地デジを楽しむためにMirakurunとEPGStationを一発で動かす

地上デジタル放送をRaspberry Piで視聴する定番の組み合わせを、ノーコード・コマンドライン操作なしに、すなわち一発でセットアップできるようにした。...

read more
SIRUI 35mm/F1.8 1.33xアナモルフィックレンズで夜景を撮る

SIRUI 35mm/F1.8 1.33xアナモルフィックレンズで夜景を撮る

ずっと欲しかったアナモルフィックレンズを手に入れた。SIRUI 35MM /F1.8 1.33X ANAMORPHIC LENS最近カメラを手にする人が増えているようなので、どうせならとレンズ...

read more
Raspberry Pi CM4とCSI-2接続HDMI入力基板で音も取る

Raspberry Pi CM4とCSI-2接続HDMI入力基板で音も取る

2年前に投稿した HDMI入力をRaspberry Piで取り込む記事 では映像しか取得していませんでしたが、このHDMI入力基板には音声も取り込めるチップ TC358743 が搭載されています。 取...

read more
無印良品で買えるRaspberry Pi2にぴったりのケース

無印良品で買えるRaspberry Pi2にぴったりのケース

Raspberry Pi2を発売日に2つ注文したものの、ケースを準備していなかったので手軽に買えるRaspberry Piにぴったりの入れ物はないかと 近所のショッピングモールを回ったところ、無印良品...

read more
NanoPi NEO2とhomebridgeとSiriで照明操作

NanoPi NEO2とhomebridgeとSiriで照明操作

この3連休に部屋を見渡していたところ、今夏に大陸から届いた荷物を開封することなく放置していたことに気づいたので開封してみました。 中からはNanoPi NEO2が6個出てきました。すごい。せっかく...

read more
スマホでNintendo Switchを操作する 〜 USB GadgetでPro Controllerをシミュレート 〜

スマホでNintendo Switchを操作する 〜 USB GadgetでPro Controllerをシミュレート 〜

あつまれ どうぶつの森の配信が開始されましたね。いくつか積みゲーが増え始めたNintendo Switchも、また新たにゲームが増えて稼働時間が伸びる一方です。物をよくなくす身として、ゲームがした...

read more
スマホでNintendo Switchのゲームをする

スマホでNintendo Switchのゲームをする

前々回 はNintendo Switch Pro ControllerのWeb対応。 前回 はNintendo Switchゲーム画面のWeb対応。 今回 はNintendo Switchゲーム音声の...

read more
ブラウザでNintendo SwitchのJoy-Conの色を変える

ブラウザでNintendo SwitchのJoy-Conの色を変える

昨今、入手困難となっているNintendo Switchは、3年前のスプラトゥーン2セットモデルが発売された時も激戦でした。 各種通販サイトを廻り、運良く発売日に手に入れられた喜びは今でも鮮明に覚えて...

read more
Firefly Station P2を買ったのでとりあえず動かした

Firefly Station P2を買ったのでとりあえず動かした

『半導体不足で欲しいものが欲しい時に手に入らなくなるかもしれない。』 そんな危機感を覚えたので、今すぐ必要ではないが後で欲しくなった時に買えないと悔しい思いをするのを避けるようになった。 気になったも...

read more
ShapewaysでreTerminal用の電子基板ケースを3Dプリントした

ShapewaysでreTerminal用の電子基板ケースを3Dプリントした

reTerminal がSeeedから発表されたのは2021年の4月のこと。 Raspberry Pi CM4にディスプレイを搭載し、立派なケースに収められてすぐに使えるように作られているとても魅力あ...

read more
中華10GbEスイッチNetcore GS6を運用して1ヶ月たったレビュー

中華10GbEスイッチNetcore GS6を運用して1ヶ月たったレビュー

春に新居に越してからベストエフォートで10Gbpsのインターネット回線を引き込み利用している。 リビングに光コンセントを設置し、ONUに自作ルーターにNASやら母艦やらを集中してリビングに設置していた...

read more