123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- ### ALSA virtual device which combines recording and playback loopback for AEC processing
- # https://github.com/sanebow/alsa-aec
- # sanebow@gmail.com
- # Version: 0.3 (20210506)
- defaults.pcm.aec.playback_hw.card defaults.pcm.card # playback hw card
- defaults.pcm.aec.playback_hw.rate 48000 # sample rate supported by the playback card
- defaults.pcm.aec.capture_hw.card defaults.pcm.card # capture hw card
- defaults.pcm.aec.capture_hw.rate 16000 # sample rate supported by the capture card
- ## you may also directly set some PCM device as playback and capture device
- defaults.pcm.aec.playback_pcm "playback_hw"
- defaults.pcm.aec.capture_pcm "capture_hw"
- defaults.pcm.aec.pre_loopidx 4 # loopback subdevice index for stream before aec processing
- defaults.pcm.aec.post_loopidx 5 # loopback subdevice index for stream after aec processing
- pcm.playback_hw {
- @args [ CARD RATE ]
- @args.CARD {
- type string
- default {
- @func refer
- name defaults.pcm.aec.playback_hw.card
- }
- }
- @args.RATE {
- type integer
- default {
- @func refer
- name defaults.pcm.aec.playback_hw.rate
- }
- }
- type plug
- slave.rate "unchanged"
- slave.pcm {
- type rate
- slave.rate $RATE
- slave.pcm {
- type dmix
- ipc_key 10009
- ipc_key_add_uid yes
- slave {
- pcm {@func concat strings [ "hw:" $CARD ] }
- }
- }
- }
- }
- pcm.capture_hw {
- @args [ CARD RATE ]
- @args.CARD {
- type string
- default {
- @func refer
- name defaults.pcm.aec.capture_hw.card
- }
- }
- @args.RATE {
- type integer
- default {
- @func refer
- name defaults.pcm.aec.capture_hw.rate
- }
- }
- type rate
- slave.rate $RATE
- slave.pcm {
- type dsnoop
- ipc_key 20009
- ipc_key_add_uid yes
- slave {
- pcm {@func concat strings [ "hw:" $CARD ] }
- rate $RATE
- }
- bindings.0 0
- }
- }
- pcm.loopback_out {
- @args [ SUBDEVICE ]
- @args.SUBDEVICE { type integer }
- type empty
- slave.pcm {
- type hw
- card "Loopback"
- device 0
- subdevice $SUBDEVICE
- channels 1
- rate 16000
- format S16_LE
- }
- }
- pcm.loopback_in {
- @args [ SUBDEVICE ]
- @args.SUBDEVICE { type integer }
- type empty
- slave.pcm {
- type hw
- card "Loopback"
- device 1
- subdevice $SUBDEVICE
- channels 1
- rate 16000
- format S16_LE
- }
- }
- # audio play to this device will be duplicated to hw (stereo) and loopback (mono)
- pcm.mloopplay {
- @args [ PCM LOOPIDX ]
- @args.PCM {
- type string
- default {
- @func refer
- name defaults.pcm.aec.playback_pcm
- }
- }
- @args.LOOPIDX {
- type integer
- default 4
- }
- type route
- slave.pcm {
- type multi
- slaves.a.pcm $PCM
- slaves.a.channels 2
- slaves.b.pcm { # loopback null sink
- @func concat
- strings [ "plug:loopback_out:" $LOOPIDX ]
- }
- slaves.b.channels 1
- bindings.0 { slave a channel 0 }
- bindings.1 { slave a channel 1 }
- bindings.2 { slave b channel 0 }
- }
- slave.channels 3
- ttable.0.0 1
- ttable.1.1 1
- ttable.0.2 0.5
- ttable.1.2 0.5
- }
- # combine mic (ch 0) and loopback (ch 1) to single recording
- pcm.mlooprec {
- @args [ PCM LOOPIDX ]
- @args.PCM {
- type string
- default {
- @func refer
- name defaults.pcm.aec.capture_pcm
- }
- }
- @args.LOOPIDX {
- type integer
- default 4
- }
- type multi
- slaves.a.pcm $PCM
- slaves.a.channels 1
- slaves.b.pcm { # loopback capturing interface
- type dsnoop # to align with capture_hw, avoid PortAudio error
- ipc_key 10099
- slave.pcm {
- @func concat
- strings [ "loopback_in:" $LOOPIDX ]
- }
- }
- slaves.b.channels 1
- bindings.0 { slave a channel 0 }
- bindings.1 { slave b channel 0 }
- }
- pcm.aec_internal {
- @args [ CAPPCM PRELOOPIDX POSTLOOPIDX ]
- @args.CAPPCM {
- type string
- default {
- @func refer
- name defaults.pcm.aec.capture_pcm
- }
- }
- @args.PRELOOPIDX {
- type integer
- default {
- @func refer
- name defaults.pcm.aec.pre_loopidx
- }
- }
- @args.POSTLOOPIDX {
- type integer
- default {
- @func refer
- name defaults.pcm.aec.post_loopidx
- }
- }
- type asym
- capture.pcm { # -i for aec script
- @func concat
- strings [ "mlooprec:" $CAPPCM "," $PRELOOPIDX ]
- }
- playback.pcm { # -o for aec script
- @func concat
- strings [ "loopback_out:" $POSTLOOPIDX ]
- }
- }
- pcm.aec {
- @args [ PLYPCM PRELOOPIDX POSTLOOPIDX ]
- @args.PLYPCM {
- type string
- default {
- @func refer
- name defaults.pcm.aec.playback_pcm
- }
- }
- @args.PRELOOPIDX {
- type integer
- default {
- @func refer
- name defaults.pcm.aec.pre_loopidx
- }
- }
- @args.POSTLOOPIDX {
- type integer
- default {
- @func refer
- name defaults.pcm.aec.post_loopidx
- }
- }
- type asym
- playback.pcm {
- @func concat
- strings [ "mloopplay:" $PLYPCM "," $PRELOOPIDX ]
- }
- capture.pcm {
- @func concat
- strings [ "loopback_in:" $POSTLOOPIDX ]
- }
- }
|