Ubuntu18.04 LTS でYoutubeやGoogle Play Musicやmp3の音楽再生で音飛びする問題


注意と問題

動画でも音楽ファイルからでも音飛びする問題が発生しています。
あれこれ尽くしたことを残しておきます。
ここで行ったことを試す場合は全て自己責任でお願いします。

結論

結果から言うと90%くらい解決。
Skypeでの音声チャットはそこそこ

環境

Windows10とUbuntu18.04でデュアルブートしています。
セキュアブートはオフにしています。

ECM-PCV80UのUSBオーディオボックスをスピーカーに繋いで再生しています。
https://www.sony.jp/microphone/products/ECM-PCV80U/

CPU: Intel64 Family 6 Model 60 Stepping 3 GenuineIntel ~3201 Mhz
MB: ASUS All Series H97-PRO
Memory: 16GB
Video: NVIDIA GeForce GT 640

参考

Ubuntu 18.04 LTS BetaでUSB DACの音飛びを直しました(改)
https://blog.goo.ne.jp/takuminews/e/00820ce12a4c98d0fdeb27c456edb253

まず試したのがここです。
USBポートを入れ差して10ポートあるのですが全ポート試しました。が!ダメ!

$ cat /proc/asound/modules
 0 snd_hda_intel
 1 snd_hda_intel
 2 snd_usb_audio

デフォルトだとこんな感じです。このsnd_usb_audioをオーディオデバイスのロード順位0にします。

以下のoptions3行をファイルの一番下に追加。

$ sudo vim /etc/modprobe.d/alsa-base.conf

~省略

options snd slots=snd_usb_audio,snd_hda_intel
options snd_usb_audio index=0
options snd_hda_intel index=1

反映させます。

$ pulseaudio -k
$ pulseaudio --start
$ cat /proc/asound/modules
 0 snd_usb_audio
 1 snd_hda_intel
 2 snd_hda_intel

優先順位は思い通りになりましたが直りませんでした。

Ubuntuの音声入出力

Ubuntuの音周りの知識がまったくないので少し調査してみることにしました。
まずはここをご参考ください

Linux の Audio 機能をコマンドラインで設定
https://qiita.com/propella/items/4699eda71cd742cba8d3

ALSA と PluseAudio

  • ALSA は色んなサウンドカードを統一的に操作出来るようにする仕組み。

    • アプリは直接 ALSA を操作しなくても良い。
    • あるアプリが ASLA 経由でサウンドカードを操作している間、他のアプリからそのサウンドカードを使えない。
    • とはいえ、直接 ALSA を使って音声入出力を行うアプリが存在する。
  • PluseAudio は複数のアプリが同時に同時にサウンドカードを使う仕組み。

    • お行儀の良いアプリは ALSA ではなく、PulseAudio 経由で音声入出力を行う。
    • とはいえ、直接 ASLA を使ってしまうアプリのために仮想サウンドカードの仕組みがある。

ALSAとPluseAudioが肝らしい

PluseAudioのデフォルトの入出力先を確認する

次のコマンドを叩きます。

$ pacmd list-sinks  | grep name:
    name: <alsa_output.usb-Sony_Corporation_UAB-80-00.iec958-stereo>
    name: <alsa_output.pci-0000_00_1b.0.iec958-stereo>

2つありますね。どっちがデフォルトなのでしょうか。

grep なしで叩きます。

indexの前に * がついているので alsa_output.usb-Sony_Corporation_UAB-80-00.iec958-stereo がデフォルトになっていることが分かりました。
自分のデバイスがデフォルトになっていない場合は先程の引用先サイトに書いてあるおまじないを行いコマンドを叩けば変わります。

pacmd list-sinks
2 sink(s) available.
  * index: 0
    name: <alsa_output.usb-Sony_Corporation_UAB-80-00.iec958-stereo>
    driver: <module-alsa-card.c>
    flags: HARDWARE DECIBEL_VOLUME LATENCY 
    state: RUNNING
    suspend cause: 
    priority: 9048
    volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
            balance 0.00
    base volume: 65536 / 100% / 0.00 dB
    volume steps: 65537
    muted: no
    current latency: 101.46 ms
    max request: 17 KiB
    max rewind: 17 KiB
    monitor source: 0
    sample spec: s16le 2ch 44100Hz
    channel map: front-left,front-right
~ 省略

    index: 3117
    name: <alsa_output.pci-0000_00_1b.0.iec958-stereo>
    driver: <module-alsa-card.c>
    flags: HARDWARE HW_MUTE_CTRL DECIBEL_VOLUME LATENCY 
    state: IDLE
    suspend cause: 
    priority: 9038
    volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
            balance 0.00
    base volume: 65536 / 100% / 0.00 dB
    volume steps: 65537
    muted: no
    current latency: 100.83 ms
    max request: 17 KiB
    max rewind: 17 KiB
    monitor source: 3119
    sample spec: s16le 2ch 44100Hz
    channel map: front-left,front-right
~ 省略

私は利用したいデバイスがデフォルトだったので特に直ったとかそいういうのは無かったです。

Ubuntuコミュニティで似た人を探す

たくさんいました。その中で新しめなものをチョイス

Audio stuttering in Ubuntu 18.04
https://askubuntu.com/questions/1044552/audio-stuttering-in-ubuntu-18-04

色々漁っていたら以下のおまじないを書くことによって解決した人もいるらしいです。
snd-hda-intelじゃなくて snd-usb-audioを使ってるんだけど意味あるのかなぁなんて思いつつ

$ sudo vim /etc/modprobe.d/alsa-base.conf
~省略~
# 以下を追記
options snd-hda-intel position_fix=1

気になったのがアンダーバーではなくてハイフン何ですよね。
優先順位の設定のときはアンダーバーだったのに。
どっちでも良いのか、優先順位の場合はアンダーバーじゃないとダメなのか良く分からないです。

もう一つ

$ sudo vim /etc/pulse/default.pa
~省略~
# 以下の行を変更する
load-module module-udev-detect

# 変更後
load-module module-udev-detect tsched=0

こちらはPulseAudioのタイマーベースのスケジューリングという機能をオフにしています。
こいつが動いているといくつかの ALSA ドライバーで問題を発生する可能性が出てくるらしい。
ONじゃないとダメなケースもあるので、うまくいかない場合はtsched=1にしていましょう

早速反映させましょう。

$ pulseaudio -k
$ pulseaudio --start

どうでしょうか?私は上記のパターンを色々試しましたがダメでした。

alsa-base.confのオプションをいじる

enableとmodelがあるっぽいです。こちらも複数のパターン試しました。
ダメでした。

options snd-hda-intel position_fix=1 enable=1 model=ideapad
options snd-hda-intel position_fix=1 enable=1 model=auto

https://github.com/spotify/linux/blob/master/Documentation/sound/alsa/ALSA-Configuration.txt
によると
position_fix は Fix DMA pointer のことらしいです。
(0 = auto, 1 = use LPIB, 2 = POSBUF)
LPIB = Link position in buffer
POSBUF = Position buffer
autoの場合POSBUFが失敗したらLPIBになるらしい

Nvidiaグラフィックドライバを入れる

UbuntuのデフォルトのグラフィックドライバがNouveauというものらしいんですよ。
私のビデオカードはNvidiaなのでNvidiaのドライバをいれたいじゃないですか。
Ubuntuコミュニティのログを漁ってるとひょんなことから直るケースってのがあったりするので私もそれにあやかろうと試してみました。

18.04になって簡単になったそうです。

開発メモ その114 Ubuntu 18.04でNvidia Driverをインストールする
https://taktak.jp/2018/05/01/2974

まずビデオカードを調べます。

$ ubuntu-drivers devices
== /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0 ==
modalias : pci:v000010DEd00000FC1sv000010DEsd0000093Cbc03sc00i00
vendor   : NVIDIA Corporation
model    : GK107 [GeForce GT 640]
driver   : nvidia-340 - distro non-free
driver   : nvidia-driver-390 - distro non-free recommended
driver   : xserver-xorg-video-nouveau - distro free builtin
#入っていないことを確認。何やらエラーっぽいのがでます。
$ nvidia-smi
~省略~

# 自動でインストール 自分で探したりしなくて良いのは助かる!
$ sudo ubuntu-drivers autoinstall

このままrebootしてもよいのですが、競合して面倒になったら発狂ものなので、こちらを参考にNouveauドライバの無効化をします

Ubuntu 16 / 18 に GTX 1080Ti / RTX2080 の ドライバとCUDAのインストール
https://qiita.com/sasayabaku/items/2323a2c501e58c0621b6

# nouveauがあるか確認
$ lsmod | grep -i nouveau
# 以下のファイルを作ってNOUVEAUをブラックリストに入れてモジュールを停止させる
$ sudo vim /etc/modprobe.d/blacklist-nouveau.conf

blacklist nouveau
options nouveau modeset=0
# カーネルモジュールの再読込
$ sudo update-initramfs -u

# 再起動
$ sudo reboot

挙動確認

$ nvidia-smi
Wed Jun 19 21:56:03 2019       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 390.116                Driver Version: 390.116                   |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  GeForce GT 640      Off  | 00000000:01:00.0 N/A |                  N/A |
| 70%   73C    P0    N/A /  N/A |    636MiB /   978MiB |     N/A      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|    0                    Not Supported                                       |
+-----------------------------------------------------------------------------+

何か音飛びが少なくなった\(^o^)/

もっと音飛びを無くすために

下記の「Pulseaudio におけるデフォルトのフラグメント・バッファサイズを設定する」を参考にしました。

PulseAudio/トラブルシューティング
https://wiki.archlinux.jp/index.php/PulseAudio/%E3%83%88%E3%83%A9%E3%83%96%E3%83%AB%E3%82%B7%E3%83%A5%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0

以下を試しました。
タイマーによるスケジューリングを無効化 (0/4)
オーディオデバイスのパラメータを調べる (1/4)
ミリ秒のフラグメントサイズとフラグメントの数を計算する (2/4)
Pulseaudio の設定ファイルを修正する (3/4)
Pulseaudio デーモンを再起動する (4/4)

$ pactl list sinks
Sink #0
    State: RUNNING
    Name: alsa_output.usb-Sony_Corporation_UAB-80-00.iec958-stereo
    Description: UAB-80 デジタルステレオ (IEC958)
    Driver: module-alsa-card.c
    Sample Specification: s16le 2ch 44100Hz
    Channel Map: front-left,front-right
    Owner Module: 8
    Mute: no
    Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
            balance 0.00
    Base Volume: 65536 / 100% / 0.00 dB
    Monitor Source: alsa_output.usb-Sony_Corporation_UAB-80-00.iec958-stereo.monitor
    Latency: 108777 usec, configured 99954 usec
    Flags: HARDWARE DECIBEL_VOLUME LATENCY SET_FORMATS 
    Properties:
        alsa.resolution_bits = "16"
        device.api = "alsa"
        device.class = "sound"
        alsa.class = "generic"
        alsa.subclass = "generic-mix"
        alsa.name = "USB Audio"
        alsa.id = "USB Audio"
        alsa.subdevice = "0"
        alsa.subdevice_name = "subdevice #0"
        alsa.device = "0"
        alsa.card = "0"
        alsa.card_name = "UAB-80"
        alsa.long_card_name = "Sony Corporation UAB-80 at usb-0000:00:14.0-10, full speed"
        alsa.driver_name = "snd_usb_audio"
        device.bus_path = "pci-0000:00:14.0-usb-0:10:1.0"
        sysfs.path = "/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.0/sound/card0"
        udev.id = "usb-Sony_Corporation_UAB-80-00"
        device.bus = "usb"
        device.vendor.id = "054c"
        device.vendor.name = "Sony Corp."
        device.product.id = "0686"
        device.product.name = "UAB-80"
        device.serial = "Sony_Corporation_UAB-80"
        device.string = "iec958:0"
        device.buffering.buffer_size = "17632"
        device.buffering.fragment_size = "4408"
        device.access_mode = "mmap"
        device.profile.name = "iec958-stereo"
        device.profile.description = "デジタルステレオ (IEC958)"
        device.description = "UAB-80 デジタルステレオ (IEC958)"
        alsa.mixer_name = "USB Mixer"
        alsa.components = "USB054c:0686"
        module-udev-detect.discovered = "1"
        device.icon_name = "audio-card-usb"
    ポート:
        iec958-stereo-output: デジタル出力 (S/PDIF) (priority: 0)
    活動中ポート: iec958-stereo-output
    形式:
        pcm

Sink #711
    State: IDLE
    Name: alsa_output.pci-0000_00_1b.0.iec958-stereo
    Description: 内部オーディオ デジタルステレオ (IEC958)
    Driver: module-alsa-card.c
    Sample Specification: s16le 2ch 44100Hz
    Channel Map: front-left,front-right Owner Module: 9
    Mute: no
    Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
            balance 0.00
    Base Volume: 65536 / 100% / 0.00 dB
    Monitor Source: alsa_output.pci-0000_00_1b.0.iec958-stereo.monitor
    Latency: 100758 usec, configured 99954 usec
    Flags: HARDWARE HW_MUTE_CTRL DECIBEL_VOLUME LATENCY SET_FORMATS 
    Properties:
        alsa.resolution_bits = "16"
        device.api = "alsa"
        device.class = "sound"
        alsa.class = "generic"
        alsa.subclass = "generic-mix"
        alsa.name = "ALC892 Digital"
        alsa.id = "ALC892 Digital"
        alsa.subdevice = "0"
        alsa.subdevice_name = "subdevice #0"
        alsa.device = "1"
        alsa.card = "1"
        alsa.card_name = "HDA Intel PCH"
        alsa.long_card_name = "HDA Intel PCH at 0xf7130000 irq 28"
        alsa.driver_name = "snd_hda_intel"
        device.bus_path = "pci-0000:00:1b.0"
        sysfs.path = "/devices/pci0000:00/0000:00:1b.0/sound/card1"
        device.bus = "pci"
        device.vendor.id = "8086"
        device.vendor.name = "Intel Corporation"
        device.product.id = "8ca0"
        device.product.name = "9 Series Chipset Family HD Audio Controller"
        device.form_factor = "internal"
        device.string = "iec958:1"
        device.buffering.buffer_size = "17632"
        device.buffering.fragment_size = "4408"
        device.access_mode = "mmap"
        device.profile.name = "iec958-stereo"
        device.profile.description = "デジタルステレオ (IEC958)"
        device.description = "内部オーディオ デジタルステレオ (IEC958)"
        alsa.mixer_name = "Realtek ALC892"
        alsa.components = "HDA:10ec0892,10438613,00100302"
        module-udev-detect.discovered = "1"
        device.icon_name = "audio-card-pci"
    ポート:
        iec958-stereo-output: デジタル出力 (S/PDIF) (priority: 0)
    活動中ポート: iec958-stereo-output
    形式:
        pcm

device.buffering.buffer_size = "17632"
device.buffering.fragment_size = "4408"

ここで気づいたのですがバッファーサイズが少ないんじゃね?

とりあえずサイトの書いてあるとおりの計算方法を試してみることに
44100*16 = 705600 ビット毎秒。ステレオなら 1411200 bps
17632/1411200 = 0.0125
4408 /1411200 = 0.0031
0.0125/0.0031 = 4

大体デフォルトと同じになっちゃいましたね

/etc/pulse/daemon.confのファイルを見る

; default-fragments = 4
; default-fragment-size-msec = 25

どこかのサイトでdefault-fragmentsを上げれば音飛び解決するって書いてあったので言われたとおりにしてみます。

$ sudo vim /etc/pulse/daemon.conf
default-fragments = 8
default-fragment-size-msec = 50
$ pulseaudio -k
$ pulseaudio --start

ダメでした。

いっそ、トラブルシューティングのサイトを同じfragment-size-msecにしてやるかと思い下の数値に

default-fragments = 4
default-fragment-size-msec = 125

良くなった気がするけどまだ飛ぶ

最終的にこんな感じになりました

default-fragments = 8
default-fragment-size-msec = 125

125じゃなくても100でも結構良かったです。Google Play Musicでは音飛びは無しに!

マイクの話

ノイズが乗るのでエコー除去・ノイズキャンセルを有効にする

同じくトラブルシューティングより

PulseAudio/トラブルシューティング
https://wiki.archlinux.jp/index.php/PulseAudio/%E3%83%88%E3%83%A9%E3%83%96%E3%83%AB%E3%82%B7%E3%83%A5%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0

$ sudo vim /etc/pulse/default.pa
# Echo/Noise-Cancelationのモジュールを有効にします
load-module module-echo-cancel

音飛び解決方法まとめ

  • USBならポートを変えてみる
  • /etc/modprobe.d/alsa-base.confでオーディオデバイスの優先順位を変更する
  • /etc/modprobe.d/alsa-base.conf で次を追記
    • options snd-hda-intel position_fix=1 enable=1 model=auto
    • options snd-usb-audio position_fix=1 enable=1 model=auto
  • /etc/pulse/default.pa の タイマーベースのスケジューリングをオフにする。またはオンにする
    • load-module module-udev-detect tsched=0
  • 設定の反映は次の2つのコマンド
    • pulseaudio -k
    • pulseaudio --start
  • ビデオカードのドライバを適切にインストールする
  • デフォルトのnouveauはブラックリストに入れる
  • /etc/pulse/daemon.confの次の項目の数値を高くする
    • default-fragments
    • default-fragment-size-msec
  • ラップトップで無線LANがある場合は何かバグがあるらしい
  • 何かのパッチを当てて直った人もいるがかなり古いバージョンの話
  • そういえばswapファイルを無駄に作ったりしたけど書き忘れた。効果無かったからいいよね。