ec - Echo Canceller の試行錯誤
エコーキャンセルプログラムのコンパイル
sudo apt-get update
sudo apt-get install -y \
libasound2-dev \
libwebrtc-audio-processing-dev \
libspeexdsp-dev
git clone https://github.com/voice-engine/ec.git
cd ec
git checkout abef2fcfeee895c77cfe913c6ef9fca8ab4b236a
make
マイクのデバイス一覧の確認
arecord -l
スピーカーのデバイス一覧の確認
aplay -l
マイクの対応サンプリングレートを確認
例えば、
card 3: Microphone [USB Microphone], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
のとき
arecord -D hw:3,0 --dump-hw-params
で
ACCESS: MMAP_INTERLEAVED RW_INTERLEAVED
FORMAT: S16_LE
SUBFORMAT: STD
SAMPLE_BITS: 16
FRAME_BITS: 32
CHANNELS: 2
RATE: [8000 48000]
PERIOD_TIME: [1000 1000000]
PERIOD_SIZE: [16 48000]
PERIOD_BYTES: [64 192000]
PERIODS: [2 1024]
BUFFER_TIME: (666 2000000]
BUFFER_SIZE: [32 96000]
BUFFER_BYTES: [128 384000]
TICK_TIME: ALL
対応サンプリングレート 8000〜48000 の範囲、サンプルビットレート 16bit のみ
スピーカーの対応サンプリングレートを確認
例えば、
card 4: M3 [EMEET OfficeCore M3], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
のとき
aplay -D hw:4,0 --dump-hw-params /usr/share/sounds/alsa/Front_Center.wav
で
ACCESS: MMAP_INTERLEAVED RW_INTERLEAVED
FORMAT: S16_LE
SUBFORMAT: STD
SAMPLE_BITS: 16
FRAME_BITS: 32
CHANNELS: 2
RATE: 48000
PERIOD_TIME: [1000 1000000]
PERIOD_SIZE: [48 48000]
PERIOD_BYTES: [192 192000]
PERIODS: [2 1024]
BUFFER_TIME: [2000 2000000]
BUFFER_SIZE: [96 96000]
BUFFER_BYTES: [384 384000]
TICK_TIME: ALL
対応サンプリングレート 48000 のみ、サンプルビットレート 16bit のみ
ノイズ音声の生成 16bit 音声じゃないとダメ
sox -n -r 48000 -c 2 -b 16 noise.wav synth 10 whitenoise vol 0.01
ノイズ音声の再生テスト
aplay -D plughw:4,0 noise.wav
マイクとスピーカーのハードウェア情報を確認した結果、マイクとスピーカーの両方が 48kHz のサンプリングレートをサポートしていることが分かりました。次に、ec
コマンドを使用してエコーキャンセルを正しく行うために、必要な設定と流れを整理します。
全体の流れ
-
マイクとスピーカーのサンプリングレートの確認
- マイクは
8000Hz から 48000Hz
までの範囲のサンプリングレートをサポート。 - スピーカーは
48000Hz
固定でサポート。 - したがって、エコーキャンセルの処理では 48kHz (48000Hz) のサンプリングレートを使用する必要があります。
- マイクは
-
.asoundrc の設定
ALSA でマイクとスピーカーを多重利用するため、dmix
とdsnoop
の設定を.asoundrc
ファイルに追加します。次のようにサンプリングレートを48000
に設定します。~/.asoundrc ファイルの内容:
pcm.dmix_output { type dmix ipc_key 1024 slave { pcm "hw:4,0" # スピーカーのデバイス rate 48000 # サンプリングレート 48kHz } } pcm.dsnoop_input { type dsnoop ipc_key 1025 slave { pcm "hw:3,0" # マイクのデバイス rate 48000 # サンプリングレート 48kHz } } pcm.!default { type asym playback.pcm "dmix_output" capture.pcm "dsnoop_input" }
-
dmix_output
: スピーカー(hw:4,0
)に対する出力デバイスの設定。サンプリングレートは48000Hz
。 -
dsnoop_input
: マイク(hw:3,0
)に対する入力デバイスの設定。サンプリングレートは48000Hz
。
-
-
サウンド設定の再読み込み
.asoundrc
ファイルの変更を反映させるために、次のコマンドを実行して ALSA の設定を再読み込みします。sudo alsactl nrestore
-
スピーカーのテスト
スピーカーから正しく音声が出力されるかをテストします。次のコマンドで、システム内のテストサウンドを再生して、スピーカーの動作確認を行います。aplay -D plughw:4,0 /usr/share/sounds/alsa/Front_Center.wav
もしこれで音声が出力されれば、スピーカーは正常に動作しています。
-
エコーキャンセルの設定
ec
コマンドを使用して、マイクの音声をスピーカーからの出力音声からエコーキャンセルします。以下のコマンドを使用してエコーキャンセルを実行します。./ec -i dsnoop_input -o dmix_output -r 48000 -c 2 -s
-
-i dsnoop_input
: マイク(dsnoop_input
)から音声を入力。 -
-o dmix_output
: スピーカー(dmix_output
)に音声を出力。 -
-r 48000
: サンプリングレートは48000Hz
。 -
-c 2
: ステレオ(2チャンネル)設定。 -
-s
: システムモードで実行。
-
-
動作確認
- スピーカーからノイズ音声や音楽などを再生しつつ、マイクで音声を入力し、エコーキャンセルが正しく動作しているかを確認します。
スピーカーでノイズを再生するためには、次のようにステレオのノイズ音声を作成し、再生します。
sox -n -r 48000 -c 2 noise.wav synth 10 whitenoise vol 0.01 aplay -D plughw:4,0 noise.wav
この設定で、スピーカーとマイクのサンプリングレートを 48kHz に揃えてエコーキャンセルが実行されるはずです。
まとめ
- マイクとスピーカーは両方とも 48kHz をサポートしているため、サンプリングレートを 48kHz に揃える必要があります。
-
.asoundrc
ファイルでdmix
とdsnoop
を設定してデバイスの多重利用を可能にし、ec
コマンドでエコーキャンセルを実行します。 - スピーカーでノイズを再生しながら、マイクで音声を入力し、正しくエコーキャンセルが行われているか確認します。
この流れに従ってエコーキャンセルを設定・確認すれば、問題なく動作するはずです。
エラーメッセージ「src/audio.c:85: set_params: Assertion 'err >= 0' failed
」は、ec
プログラムがオーディオデバイスのパラメータ設定に失敗したことを示しています。これは主に、オーディオデバイスのサンプリングレートやチャンネル数がサポートされていないか、ALSA 設定に何か競合がある可能性があります。
次に、問題を解決するために考えられる対処法をいくつか示します。
plughw
を使って再試行
1. ALSA の plug
プラグインを使うことで、サンプリングレートやフォーマットの自動変換が行われるため、エラーを回避できる場合があります。
次のように、plughw
デバイスを指定して ec
を実行してみてください。
./ec -i plughw:3,0 -o plughw:4,0 -r 48000 -c 2 -s
これで、サンプリングレートやチャンネルのフォーマットが自動的に調整され、エラーが解消されるかを確認します。
2. .asoundrc 設定の見直し
.asoundrc
の設定で、dsnoop
や dmix
の設定が正しくされているか再度確認してみましょう。特に rate
の設定が正しく行われているか確認してください。
pcm.dmix_output {
type plug
slave {
pcm "hw:4,0"
rate 48000
}
}
pcm.dsnoop_input {
type plug
slave {
pcm "hw:3,0"
rate 48000
}
}
pcm.!default {
type asym
playback.pcm "dmix_output"
capture.pcm "dsnoop_input"
}
ここで、type plug
を設定することで、自動的にサンプリングレート変換が行われ、互換性の問題を軽減できます。これを設定した後、alsactl nrestore
で ALSA 設定を再読み込みします。
3. PulseAudio の停止
PulseAudio が ALサウンド設定と競合している場合、これが原因で ec
の実行に失敗していることがあります。次のコマンドで PulseAudio を一時停止してから、再度 ec
を実行してみてください。
pulseaudio --kill
./ec -i dsnoop_input -o dmix_output -r 48000 -c 2 -s
これにより、PulseAudio が ALSA デバイスの管理を行わず、直接 ALSA がデバイスを管理する形になります。
4. ALSA デバイスの利用状況確認
ALSA デバイスが他のプロセスによって占有されている場合も、設定がうまくいかないことがあります。次のコマンドで、デバイスを使用しているプロセスを確認し、該当するプロセスがあれば終了させてください。
fuser -v /dev/snd/*
競合しているプロセスを特定したら、kill
コマンドで終了させます。
5. 他のサンプリングレートでテスト
マイクやスピーカーが 48kHz をサポートしていても、特定の条件で問題が発生する場合があります。次に、他のサンプリングレート(44.1kHz)で試してみます。
./ec -i dsnoop_input -o dmix_output -r 44100 -c 2 -s
これで 44.1kHz のサンプリングレートでエコーキャンセルが動作するか確認してください。
6. デバッグログの確認
もし上記の手順でも問題が解決しない場合、dmesg
コマンドを使って ALSA デバイスに関連するエラーメッセージを確認し、さらなる情報を得ることができます。
dmesg | grep -i snd
このログでデバイスのエラーメッセージや警告を確認し、必要に応じて対処します。
まとめ
-
plughw
を指定して自動変換を試す。 -
.asoundrc
の設定を見直し、plug
プラグインを使用する。 - PulseAudio を一時停止して ALSA のみにする。
- 他のプロセスがデバイスを占有していないか確認。
- 44.1kHz のサンプリングレートで試す。
-
dmesg
でログを確認。
これらの手順を順に試して、エラーが解消されるか確認してみてください。
方向性をいったん見直す。ALSAでループバックデバイスを作る。
aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: ALC892 Analog [ALC892 Analog]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 1: ALC892 Digital [ALC892 Digital]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: Microphone [USB Microphone], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 2: NVidia [HDA NVidia], device 3: HDMI 0 [HDMI 0]
Subdevices: 0/1
Subdevice #0: subdevice #0
card 2: NVidia [HDA NVidia], device 7: HDMI 1 [HDMI 1]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 2: NVidia [HDA NVidia], device 8: HDMI 2 [HDMI 2]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 2: NVidia [HDA NVidia], device 9: HDMI 3 [HDMI 3]
Subdevices: 1/1
Subdevice #0: subdevice #0
sudo modprobe snd-aloop
aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: ALC892 Analog [ALC892 Analog]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 1: ALC892 Digital [ALC892 Digital]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: Microphone [USB Microphone], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 2: NVidia [HDA NVidia], device 3: HDMI 0 [HDMI 0]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 2: NVidia [HDA NVidia], device 7: HDMI 1 [HDMI 1]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 2: NVidia [HDA NVidia], device 8: HDMI 2 [HDMI 2]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 2: NVidia [HDA NVidia], device 9: HDMI 3 [HDMI 3]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 4: Loopback [Loopback], device 0: Loopback PCM [Loopback PCM]
Subdevices: 7/8
Subdevice #0: subdevice #0
Subdevice #1: subdevice #1
Subdevice #2: subdevice #2
Subdevice #3: subdevice #3
Subdevice #4: subdevice #4
Subdevice #5: subdevice #5
Subdevice #6: subdevice #6
Subdevice #7: subdevice #7
card 4: Loopback [Loopback], device 1: Loopback PCM [Loopback PCM]
Subdevices: 8/8
Subdevice #0: subdevice #0
Subdevice #1: subdevice #1
Subdevice #2: subdevice #2
Subdevice #3: subdevice #3
Subdevice #4: subdevice #4
Subdevice #5: subdevice #5
Subdevice #6: subdevice #6
Subdevice #7: subdevice #7
aplay -L
hw:CARD=Loopback,DEV=0
Loopback, Loopback PCM
Direct hardware device without any conversions
hw:CARD=Loopback,DEV=1
Loopback, Loopback PCM
Direct hardware device without any conversions
plughw:CARD=Loopback,DEV=0
Loopback, Loopback PCM
Hardware device with all software conversions
plughw:CARD=Loopback,DEV=1
Loopback, Loopback PCM
Hardware device with all software conversions
- skypeで音楽を流すには
# マイク入力のsource名
pacmd list-sources | grep -E 'index:|name:'
index: 2
name: <alsa_output.pci-0000_00_1f.3.iec958-stereo.monitor>
* index: 7
name: <alsa_input.usb-AONI_ELECTRONIC_CO._Full_HD_webcam_AN202007180003-02.mono-fallback>
index: 8
name: <alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1.monitor>
# スピーカーのsink名
pacmd list-sinks | grep -E 'index:|name:'
index: 1
name: <alsa_output.pci-0000_00_1f.3.iec958-stereo>
* index: 4
name: <alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1>
alsa_input.usb-AONI_ELECTRONIC_CO._Full_HD_webcam_AN202007180003-02.mono-fallback
から取得する音声(マイク入力=source)を、alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1
(スピーカー出力=sink) に loopback するモジュールを有効にする。この設定でマイクから入力された音声がスピーカーの音声に混じって出力される。しかし、このまま使うと、スピーカーから出力される合成済み音声を再びマイクから拾ってしまうのですぐにハウリングする。
pacmd load-module module-loopback \
source='alsa_input.usb-AONI_ELECTRONIC_CO._Full_HD_webcam_AN202007180003-02.mono-fallback' \
sink='alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1'
ループバックモジュールのアンロード方法
pacmd list-modules | grep -E 'index:|module-loopback'
index: 0
index: 1
index: 2
index: 3
:
index: 28
index: 29
name: <module-loopback>
pacmd unload-module 29
# null-sink モジュールの追加ロード
pacmd load-module module-null-sink
# 使用可能な sink の確認、* は現在デフォルト、null.monitor が使用したいsink
pacmd list-sources | grep -E 'index:|name:'
index: 2
name: <alsa_output.pci-0000_00_1f.3.iec958-stereo.monitor>
* index: 21
name: <alsa_output.pci-0000_01_00.1.hdmi-stereo-extra1.monitor>
index: 24
name: <null.monitor>
# ロード済みのモジュールの確認
pacmd list-modules | grep -E 'index:|name:'
index: 0
name: <module-device-restore>
index: 1
name: <module-stream-restore>
index: 2
name: <module-card-restore>
index: 3
name: <module-augment-properties>
index: 4
name: <module-switch-on-port-available>
index: 5
name: <module-switch-on-connect>
index: 6
name: <module-udev-detect>
index: 7
name: <module-alsa-card>
index: 9
name: <module-alsa-card>
index: 10
name: <module-bluetooth-policy>
index: 11
name: <module-bluetooth-discover>
index: 12
name: <module-bluez5-discover>
index: 13
name: <module-native-protocol-unix>
index: 14
name: <module-default-device-restore>
index: 15
name: <module-always-sink>
index: 16
name: <module-intended-roles>
index: 17
name: <module-suspend-on-idle>
index: 18
name: <module-systemd-login>
index: 19
name: <module-position-event-sounds>
index: 20
name: <module-role-cork>
index: 21
name: <module-snap-policy>
index: 22
name: <module-filter-heuristics>
index: 23
name: <module-filter-apply>
index: 24
name: <module-native-protocol-tcp>
index: 25
name: <module-cli-protocol-unix>
index: 35
name: <module-null-sink>
# null-sink モジュールのアンロード
pacmd unload-module 35
pacmd list-sources | grep -E 'index:|name:'
pacmd list-sinks | grep -E 'index:|name:'
pacmd list-modules | grep -E 'index:|Virtual|module-loopback'