diff --git a/buildroot-external/configs/rpi3_64_defconfig b/buildroot-external/configs/rpi3_64_defconfig index d8ac6bdc..1c3b9ff9 100644 --- a/buildroot-external/configs/rpi3_64_defconfig +++ b/buildroot-external/configs/rpi3_64_defconfig @@ -56,7 +56,6 @@ BR2_PACKAGE_ALSA_UTILS_ASEQNET=y BR2_PACKAGE_ALSA_UTILS_BAT=y BR2_PACKAGE_ALSA_UTILS_IECSET=y BR2_PACKAGE_ALSA_UTILS_SPEAKER_TEST=y -BR2_PACKAGE_FFMPEG=y BR2_PACKAGE_FFMPEG_GPL=y BR2_PACKAGE_FFMPEG_NONFREE=y BR2_PACKAGE_FFMPEG_FFPLAY=y @@ -147,7 +146,6 @@ BR2_PACKAGE_OPUS=y BR2_PACKAGE_PORTAUDIO=y BR2_PACKAGE_SBC=y BR2_PACKAGE_SBC_TOOLS=y -BR2_PACKAGE_SPEEXDSP=y BR2_PACKAGE_WEBRTC_AUDIO_PROCESSING=y BR2_PACKAGE_LIBARCHIVE=y BR2_PACKAGE_LIBDEFLATE=y @@ -309,6 +307,8 @@ BR2_PACKAGE_OVOS_CONTAINERS=y BR2_PACKAGE_OVOS_CONTAINERS_ARCH="arm64" BR2_PACKAGE_OVOS_SPLASH=y BR2_PACKAGE_RESPEAKER=y +BR2_PACKAGE_RNNNOISE_LADSPA=y +BR2_PACKAGE_ROC_TOOLKIT=y BR2_PACKAGE_RPI_EEPROM=y BR2_PACKAGE_USERLAND_TOOLS=y BR2_PACKAGE_VOCALFUSION=y diff --git a/buildroot-external/configs/rpi4_64_defconfig b/buildroot-external/configs/rpi4_64_defconfig index 02f17ba3..03ece68c 100644 --- a/buildroot-external/configs/rpi4_64_defconfig +++ b/buildroot-external/configs/rpi4_64_defconfig @@ -57,7 +57,6 @@ BR2_PACKAGE_ALSA_UTILS_ASEQNET=y BR2_PACKAGE_ALSA_UTILS_BAT=y BR2_PACKAGE_ALSA_UTILS_IECSET=y BR2_PACKAGE_ALSA_UTILS_SPEAKER_TEST=y -BR2_PACKAGE_FFMPEG=y BR2_PACKAGE_FFMPEG_GPL=y BR2_PACKAGE_FFMPEG_NONFREE=y BR2_PACKAGE_FFMPEG_FFPLAY=y @@ -146,7 +145,6 @@ BR2_PACKAGE_OPUS=y BR2_PACKAGE_PORTAUDIO=y BR2_PACKAGE_SBC=y BR2_PACKAGE_SBC_TOOLS=y -BR2_PACKAGE_SPEEXDSP=y BR2_PACKAGE_WEBRTC_AUDIO_PROCESSING=y BR2_PACKAGE_LIBARCHIVE=y BR2_PACKAGE_LIBDEFLATE=y @@ -309,6 +307,8 @@ BR2_PACKAGE_OVOS_CONTAINERS_ARCH="arm64" BR2_PACKAGE_OVOS_CONTAINERS_GUI=y BR2_PACKAGE_OVOS_SPLASH=y BR2_PACKAGE_RESPEAKER=y +BR2_PACKAGE_RNNNOISE_LADSPA=y +BR2_PACKAGE_ROC_TOOLKIT=y BR2_PACKAGE_RPI_EEPROM=y BR2_PACKAGE_USERLAND_TOOLS=y BR2_PACKAGE_VOCALFUSION=y diff --git a/buildroot-external/package/roc-toolkit/Config.in b/buildroot-external/package/roc-toolkit/Config.in index 2cd13955..52f91858 100644 --- a/buildroot-external/package/roc-toolkit/Config.in +++ b/buildroot-external/package/roc-toolkit/Config.in @@ -4,6 +4,8 @@ config BR2_PACKAGE_ROC_TOOLKIT select BR2_PACKAGE_LIBUNWIND select BR2_PACKAGE_OPENFEC select BR2_PACKAGE_SPEEXDSP + select BR2_PACKAGE_SOX + select BR2_PACKAGE_LIBUV help Roc is a toolkit for real-time audio streaming over the network. diff --git a/buildroot-external/package/roc-toolkit/roc-toolkit.mk b/buildroot-external/package/roc-toolkit/roc-toolkit.mk index 37ea8dbd..761ce659 100644 --- a/buildroot-external/package/roc-toolkit/roc-toolkit.mk +++ b/buildroot-external/package/roc-toolkit/roc-toolkit.mk @@ -20,7 +20,8 @@ ROC_TOOLKIT_DEPENDENCIES = \ openfec \ speexdsp \ sox \ - pulseaudio + pulseaudio \ + libuv define ROC_TOOLKIT_BUILD_CMDS (cd $(@D); \ diff --git a/buildroot-external/rootfs-overlay/etc/pipewire/pipewire-pulse.conf b/buildroot-external/rootfs-overlay/etc/pipewire/pipewire-pulse.conf index 0e5206bc..e4a505ee 100644 --- a/buildroot-external/rootfs-overlay/etc/pipewire/pipewire-pulse.conf +++ b/buildroot-external/rootfs-overlay/etc/pipewire/pipewire-pulse.conf @@ -26,8 +26,8 @@ context.spa-libs = { context.modules = [ { name = libpipewire-module-rt args = { - nice.level = -11 - #rt.prio = 88 + nice.level = -19 + rt.prio = 95 #rt.time.soft = -1 #rt.time.hard = -1 } @@ -42,6 +42,16 @@ context.modules = [ args = { # contents of pulse.properties can also be placed here # to have config per server. + pulse.min.req = "256/48000" + pulse.default.req = "256/48000" + pulse.max.req = "256/48000" + pulse.min.quantum = "256/48000" + pulse.max.quantum = "256/48000" + pulse.min.req = "256/48000" + pulse.default.req = "256/48000" + pulse.max.req = "256/48000" + pulse.min.quantum = "256/48000" + pulse.max.quantum = "256/48000" } } ] @@ -65,7 +75,7 @@ pulse.cmd = [ ] stream.properties = { - #node.latency = 1024/48000 + node.latency = 256/48000 #node.autoconnect = true #resample.quality = 4 #channelmix.normalize = false diff --git a/buildroot-external/rootfs-overlay/etc/pipewire/pipewire.conf b/buildroot-external/rootfs-overlay/etc/pipewire/pipewire.conf index a5182dda..3c23e519 100644 --- a/buildroot-external/rootfs-overlay/etc/pipewire/pipewire.conf +++ b/buildroot-external/rootfs-overlay/etc/pipewire/pipewire.conf @@ -28,9 +28,9 @@ context.properties = { ## Properties for the DSP configuration. #default.clock.rate = 48000 #default.clock.allowed-rates = [ 48000 ] - #default.clock.quantum = 1024 - #default.clock.min-quantum = 32 - #default.clock.max-quantum = 2048 + default.clock.quantum = 256 + default.clock.min-quantum = 64 + default.clock.max-quantum = 512 #default.clock.quantum-limit = 8192 #default.video.width = 640 #default.video.height = 480 @@ -91,8 +91,8 @@ context.modules = [ # scheduling. { name = libpipewire-module-rt args = { - nice.level = -11 - #rt.prio = 88 + nice.level = -19 + rt.prio = 95 #rt.time.soft = -1 #rt.time.hard = -1 } diff --git a/buildroot-external/rootfs-overlay/etc/security/limits.conf b/buildroot-external/rootfs-overlay/etc/security/limits.conf index dddf1e32..fa31659f 100644 --- a/buildroot-external/rootfs-overlay/etc/security/limits.conf +++ b/buildroot-external/rootfs-overlay/etc/security/limits.conf @@ -1,2 +1,3 @@ -@audio - rtprio 90 # maximum realtime priority -@audio - memlock unlimited # maximum locked-in-memory address space (KB) +@pipewire - rtprio 95 +@pipewire - nice -19 +@pipewire - memlock 4194304 diff --git a/buildroot-external/rootfs-overlay/etc/wireplumber/main.lua.d/50-alsa-config.lua b/buildroot-external/rootfs-overlay/etc/wireplumber/main.lua.d/50-alsa-config.lua new file mode 100644 index 00000000..315cd1bf --- /dev/null +++ b/buildroot-external/rootfs-overlay/etc/wireplumber/main.lua.d/50-alsa-config.lua @@ -0,0 +1,157 @@ +alsa_monitor.enabled = true + +alsa_monitor.properties = { + -- Create a JACK device. This is not enabled by default because + -- it requires that the PipeWire JACK replacement libraries are + -- not used by the session manager, in order to be able to + -- connect to the real JACK server. + --["alsa.jack-device"] = false, + + -- Reserve devices via org.freedesktop.ReserveDevice1 on D-Bus + -- Disable if you are running a system-wide instance, which + -- doesn't have access to the D-Bus user session + ["alsa.reserve"] = true, + --["alsa.reserve.priority"] = -20, + --["alsa.reserve.application-name"] = "WirePlumber", + + -- Enables MIDI functionality + ["alsa.midi"] = true, + + -- Enables monitoring of alsa MIDI devices + ["alsa.midi.monitoring"] = true, + + -- MIDI bridge node properties + ["alsa.midi.node-properties"] = { + -- Name set for the node with ALSA MIDI ports + ["node.name"] = "Midi-Bridge", + -- Removes longname/number from MIDI port names + --["api.alsa.disable-longname"] = true, + ["priority.session"] = 100, + ["priority.driver"] = 1, + }, + + -- These properties override node defaults when running in a virtual machine. + -- The rules below still override those. + ["vm.node.defaults"] = { + ["api.alsa.period-size"] = 1024, + ["api.alsa.headroom"] = 8192, + }, +} + +alsa_monitor.rules = { + -- An array of matches/actions to evaluate. + -- + -- If you want to disable some devices or nodes, you can apply properties per device as the following example. + -- The name can be found by running pw-cli ls Device, or pw-cli dump Device + --{ + -- matches = { + -- { + -- { "device.name", "matches", "name_of_some_disabled_card" }, + -- }, + -- }, + -- apply_properties = { + -- ["device.disabled"] = true, + -- }, + --} + { + -- Rules for matching a device or node. It is an array of + -- properties that all need to match the regexp. If any of the + -- matches work, the actions are executed for the object. + matches = { + { + -- This matches all cards. + { "device.name", "matches", "alsa_card.*" }, + }, + }, + -- Apply properties on the matched object. + apply_properties = { + -- Use ALSA-Card-Profile devices. They use UCM or the profile + -- configuration to configure the device and mixer settings. + ["api.alsa.use-acp"] = true, + + -- Use UCM instead of profile when available. Can be + -- disabled to skip trying to use the UCM profile. + --["api.alsa.use-ucm"] = true, + + -- Don't use the hardware mixer for volume control. It + -- will only use software volume. The mixer is still used + -- to mute unused paths based on the selected port. + --["api.alsa.soft-mixer"] = false, + + -- Ignore decibel settings of the driver. Can be used to + -- work around buggy drivers that report wrong values. + --["api.alsa.ignore-dB"] = false, + + -- The profile set to use for the device. Usually this is + -- "default.conf" but can be changed with a udev rule or here. + --["device.profile-set"] = "profileset-name", + + -- The default active profile. Is by default set to "Off". + --["device.profile"] = "default profile name", + + -- Automatically select the best profile. This is the + -- highest priority available profile. This is disabled + -- here and instead implemented in the session manager + -- where it can save and load previous preferences. + ["api.acp.auto-profile"] = false, + + -- Automatically switch to the highest priority available port. + -- This is disabled here and implemented in the session manager instead. + ["api.acp.auto-port"] = false, + + -- Other properties can be set here. + --["device.nick"] = "My Device", + }, + }, + { + matches = { + { + -- Matches all sources. + { "node.name", "matches", "alsa_input.*" }, + }, + { + -- Matches all sinks. + { "node.name", "matches", "alsa_output.*" }, + }, + }, + apply_properties = { + --["node.nick"] = "My Node", + --["node.description"] = "My Node Description", + --["priority.driver"] = 100, + --["priority.session"] = 100, + --["node.pause-on-idle"] = false, + --["monitor.channel-volumes"] = false + --["resample.quality"] = 4, + --["resample.disable"] = false, + --["channelmix.normalize"] = false, + --["channelmix.mix-lfe"] = false, + --["channelmix.upmix"] = true, + --["channelmix.upmix-method"] = "psd", -- "none" or "simple" + --["channelmix.lfe-cutoff"] = 150, + --["channelmix.fc-cutoff"] = 12000, + --["channelmix.rear-delay"] = 12.0, + --["channelmix.stereo-widen"] = 0.0, + --["channelmix.hilbert-taps"] = 0, + --["channelmix.disable"] = false, + --["dither.noise"] = 0, + --["dither.method"] = "none", -- "rectangular", "triangular" or "shaped5" + --["audio.channels"] = 2, + --["audio.format"] = "S16LE", + --["audio.rate"] = 44100, + --["audio.allowed-rates"] = "32000,96000", + --["audio.position"] = "FL,FR", + ["api.alsa.period-size"] = 256, + ["api.alsa.period-num"] = 3, + --["api.alsa.headroom"] = 0, + --["api.alsa.start-delay"] = 0, + --["api.alsa.disable-mmap"] = false, + --["api.alsa.disable-batch"] = false, + --["api.alsa.use-chmap"] = false, + --["api.alsa.multirate"] = true, + --["latency.internal.rate"] = 0 + --["latency.internal.ns"] = 0 + --["clock.name"] = "api.alsa.0" + ["session.suspend-timeout-seconds"] = 0, -- 0 disables suspend + }, + }, +} diff --git a/buildroot-external/rootfs-overlay/home/ovos/.config/pipewire/pipewire.conf.d/90-input-denoising.conf b/buildroot-external/rootfs-overlay/home/ovos/.config/pipewire/pipewire.conf.d/90-input-denoising.conf new file mode 100644 index 00000000..e5419630 --- /dev/null +++ b/buildroot-external/rootfs-overlay/home/ovos/.config/pipewire/pipewire.conf.d/90-input-denoising.conf @@ -0,0 +1,30 @@ +context.modules = [ + { name = libpipewire-module-filter-chain + args = { + node.name = "denoised_source" + node.description = "Noise Canceling source" + media.name = "Noise Canceling source" + filter.graph = { + nodes = [ + { + type = ladspa + name = rnnoise + plugin = /usr/lib/ladspa/librnnoise_ladspa.so + label = noise_suppressor_mono + control = { + "VAD Threshold (%)" 50.0 + "VAD Grace Period (ms)" = 200 + "Retroactive VAD Grace (ms)" = 0 + } + } + ] + } + capture.props = { + node.passive = true + } + playback.props = { + media.class = Audio/Source + } + } + } +] diff --git a/buildroot-external/user_table.txt b/buildroot-external/user_table.txt index 96ee24fe..52817ce4 100644 --- a/buildroot-external/user_table.txt +++ b/buildroot-external/user_table.txt @@ -1 +1 @@ -ovos -2 ovos -2 =ovos /home/ovos /bin/sh input,i2c,spi,tty,gpio,adm,wheel,audio,video,lp,adm,network,systemd-journal,systemd-timesync Ovos user +ovos -2 ovos -2 =ovos /home/ovos /bin/sh input,i2c,spi,tty,gpio,adm,wheel,audio,video,lp,adm,network,systemd-journal,systemd-timesync,pipewire,dialout Ovos user