Jack
Installation
Install jack2 package. For raspberry pi you need a special version compiled without --dbus, this allow jackd running without X11.
wget -q -O - http://rpi.autostatic.com/autostatic.gpg.key | sudo apt-key add -
sudo wget -q -O /etc/apt/sources.list.d/autostatic-audio-raspbian.list http://rpi.autostatic.com/autostatic-audio-raspbian.list
sudo apt-get update
Here are the packages ((without dbus/X11 requirement)) if they are no more availables: libjack-jackd2 jackd2
Notes: jckd2 is dependent of libjack, so first install libjack. You could have some trouble for downgrade tour current version, in this case when you uninstall on your device your current jack, you take the risk of break program dependant of jack ((i had the problem with wireshark, gstreamer, espeak, and smplayer who depends of libjack)).
Configuration
Jack run on your current user ((for security reason)). But jack ask some privileges on memory, and priority ((to have sound on real time)).
/etc/security/limits.conf
#<domain> <type> <item> <value>
@audio - rtprio 99
@audio - memlock unlimited
Note: Give privilege for audio group. You need to logout/login to take effects.
Jack Client
Better than pulseaudio for network.
Send data through network
Native method
Disdvantage: The sender is like a server. So the client need to know ip/port of the daemon who run. See zita as alternative.
jackd -R -d netone
Note:
-
Replace netone by net if you use jack1
-
It's possible to specify a port with -I option
-
-r specify sample rate, useful when you've got some problem ((44100 for cd quality, or 48000)). If you specify this, specify also on other side((server)).
-
To start automatically at startup, add this command in
.jackdrc
file in home directory. Seems to be only before Debian Jessie.
Zita
Zita are going to use ~300ko/sec((2.17Mbit/s)). On website they said 50ko/sec, so i think it's possible to optimize if you need this constraint please update configuration and how to use.
Package: zita-njbridge
Advantage: Compare to native method, you could use through internet, and you can set the sender of sound as a client TCP and receiver as server.
Run
zita-j2n server_ip server_port
Require jackd running ((run it with netone driver, if you take alsa instead of netone, you're going to create yourself the jack_connect. With netone, the jack_connect are done automatically when you start an application. I don't know why !? need to ask on IRC)).
Note: j2n mean "jack to network".
Run pulseaudio on jack
Lot of OS have pulseaudio by default. This mean that all sound from different application (mplayer, vlc, mpg...) going directly on pulseaudio, and no on jack. So the sound not going to be played on network peripherals. To resolve this, you can say to pulseaudio to use jack.
Installation
Install pulseaudio-module-jack
package.
Configure
~/.pulse/default.pa
load-module module-native-protocol-unix
load-module module-jack-sink channels=2
load-module module-jack-source channels=2
load-module module-null-sink
load-module module-stream-restore
load-module module-rescue-streams
load-module module-always-sink
load-module module-suspend-on-idle
set-default-sink jack_out
set-default-source jack_in
Note: Could also use /etc/pulse/default.pa
file.
~/.pulse/daemon.conf
default-sample-format = float32le
default-sample-rate = 48000
realtime-scheduling = yes
exit-idle-time = -1
Note: Could also use /etc/pulse/daemon.conf
file.
See other solution for pulseaudio : http://jackaudio.org/faq/pulseaudio_and_jack.html
Jack Server
Run jackd
jackd -d alsa
Note: On raspberry pi, due to unknown reason, you need specific options. See below.
Raspberry pi
jackd -p16 -d alsa -n 4
Note: -n 3 minimum((buffer bigger than 2 by default)). You also need -p16 to avoid bus error and memory allocation problem.
You can also optimize by remove some unused services:
#!/bin/bash
## Stop the ntp service
sudo service ntp stop
## Stop the triggerhappy service
sudo service triggerhappy stop
## Stop the dbus service. Warning: this can cause unpredictable behaviour when running a desktop environment on the RPi
sudo service dbus stop
## Stop the console-kit-daemon service. Warning: this can cause unpredictable behaviour when running a desktop environment on the RPi
sudo killall console-kit-daemon
## Stop the polkitd service. Warning: this can cause unpredictable behaviour when running a desktop environment on the RPi
sudo killall polkitd
## Only needed when Jack2 is compiled with D-Bus support (Jack2 in the AutoStatic RPi audio repo is compiled without D-Bus support)
#export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket
## Remount /dev/shm to prevent memory allocation errors
sudo mount -o remount,size=128M /dev/shm
## Kill the usespace gnome virtual filesystem daemon. Warning: this can cause unpredictable behaviour when running a desktop environment on the RPi
killall gvfsd
## Kill the userspace D-Bus daemon. Warning: this can cause unpredictable behaviour when running a desktop environment on the RPi
killall dbus-daemon
## Kill the userspace dbus-launch daemon. Warning: this can cause unpredictable behaviour when running a desktop environment on the RPi
killall dbus-launch
## Uncomment if you'd like to disable the network adapter completely
#echo -n “1-1.1:1.0” | sudo tee /sys/bus/usb/drivers/smsc95xx/unbind
## In case the above line doesn't work try the following
#echo -n “1-1.1” | sudo tee /sys/bus/usb/drivers/usb/unbind
## Set the CPU scaling governor to performance # WARNING: can cause audible glitches
#echo -n performance | sudo tee /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
## And finally start JACK (here -dhw is for USB output)
jackd -P70 -p16 -t2000 -d alsa -dhw:UA25 -p 128 -n 3 -r 44100 -s &
exit
Script init
jackd-network-rp
#!/bin/bash
### BEGIN INIT INFO
# Provides: jackd-network-rp
# Required-Start: $local_fs $remote_fs $network $syslog $named
# Required-Stop: $local_fs $remote_fs $network $syslog $named
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/stop jack daemon with network zita and connect speaker
### END INIT INFO
NAME=jackd-network-rp
SCRIPTNAME=/etc/init.d/$NAME
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Permet d'afficher un message plus visible (en vert)
# @param $1 Le message
function successMsg(){
echo -e "\033[32m${1}\033[0m"
}
# Permet d'afficher un message plus visible (en orange)
# @param $1 Le message
function warningMsg(){
echo -e "\033[33m${1}\033[0m"
}
# Permet d'afficher un message plus visible (en rouge)
# Remarque : Cette fonction provoque l'arret du script
# @param $1 Le message
function errorMsg(){
echo -e "\033[31m${1}\033[0m"
exit 1
}
# Permet d'afficher un message plus visible (bleu)
function boldMsg(){
echo -e "\033[34m${1}\033[0m"
}
# Permet un message a gauche avec un label a droite (vert)
# @param $1 Le message
# @param $2 (optionel) le label
function labelSuccessMsg() {
local msg="$1"
local label="$2"
local color=$(tput setaf 2)
local normal=$(tput sgr0)
local supp=""
local cold=0
if [ -n "$msg" ]
then
let cold=-1
supp="${color}|${normal}"
fi
if [ -z "$label" ]
then
label="ok"
fi
let cold=$(tput cols)-${#msg}+${#color}+${#normal}+${cold}
printf "%s%${cold}s" "${supp}${msg}" "[${color} ${label} ${normal}]"
}
# Permet un message a gauche avec un label a droite (rouge)
# Remarque : arret du script
# @param $1 Le message
# @param $2 (optionel) le label
function labelErrorMsg() {
local msg="$1"
local label="$2"
local color=$(tput setaf 1)
local normal=$(tput sgr0)
local supp=""
local cold=0
if [ -n "$msg" ]
then
let cold=-1
supp="${color}|${normal}"
fi
if [ -z "$label" ]
then
label="fail"
fi
let cold=$(tput cols)-${#msg}+${#color}+${#normal}+${cold}
printf "%s%${cold}s" "${supp}${msg}" "[${color} ${label} ${normal}]"
exit 1
}
# Permet un message a gauche avec un label a droite (orange)
# @param $1 Le message
# @param $2 (optionel) le label
function labelWarningMsg() {
local msg="$1"
local label="$2"
local color=$(tput setaf 3)
local normal=$(tput sgr0)
local supp=""
local cold=0
if [ -n "$msg" ]
then
let cold=-1
supp="${color}|${normal}"
fi
if [ -z "$label" ]
then
label="warn"
fi
let cold=$(tput cols)-${#msg}+${#color}+${#normal}+${cold}
printf "%s%${cold}s" "${supp}${msg}" "[${color} ${label} ${normal}]"
}
# Permet un message a gauche avec un label a droite (orange)
# @param $1 Le message
# @param $2 (optionel) le label
function labelBoldMsg() {
local msg="$1"
local label="$2"
local color=$(tput setaf 6)
local normal=$(tput sgr0)
local supp=""
local cold=0
if [ -n "$msg" ]
then
let cold=-1
supp="${color}|${normal}"
fi
if [ -z "$label" ]
then
label="info"
fi
let cold=$(tput cols)-${#msg}+${#color}+${#normal}+${cold}
printf "%s%${cold}s" "${supp}${msg}" "[${color} ${label} ${normal}]"
}
case $1 in
start)
echo "Starting jackd with driver netone "
jackd -p 16 -d alsa -n 4 -s & # FIXME & is not the best way, see rtorrent
sleep 4s # FIXME in future try another solution, zita need jackd running
zita-n2j 192.168.2.30 1234 & # FIXME & is not the best way, see rtorrent
sleep 4s # FIXME in future try another solution, jack_connect need zita
jack_connect zita-n2j:out_1 system:playback_1
jack_connect zita-n2j:out_2 system:playback_2
# TODO check everthing has worked
;;
stop)
if [ "$(ps aux | grep -e 'zita-n2j' | grep -v grep -c)" != 0 ]
then
echo "Shutting down zita-n2j... "
killall -r "zita-n2j"
if [ $? == 0 ]
then
labelSuccessMsg "Shutdown zita-n2j" "down"
else
labelErrorMsg "Shutdown zita-n2j" "failed"
fi
fi
if [ "$(ps aux | grep -e 'jackd' | grep -v grep -c)" != 0 ]
then
echo "Shutting down jackd... "
killall -r "jackd"
if [ $? == 0 ]
then
labelSuccessMsg "Shutdown jackd" "down"
else
labelErrorMsg "Shutdown jackd" "failed"
fi
else
labelBoldMsg "jackd is not running"
fi
;;
status)
if [ "$(ps aux | grep -e 'zita-n2j' | grep -v grep -c)" != 0 ]
then
labelSuccessMsg "zita-n2j running" "running"
else
labelBoldMsg "zita-n2j seems down"
fi
if [ "$(ps aux | grep -e 'jackd' | grep -v grep -c)" != 0 ] # FIXME don't seem to work
then
labelSuccessMsg "jackd running" "running"
else
labelBoldMsg "jackd doesnt running" "shutdown"
fi
;;
* )
echo "Usage: $SCRIPTNAME {start|stop|status}" >&2
exit 2
;;
esac
FIXME: currently not working, just jackd start, but no zinta, you need to connect on ssh to re-start.
chmod +x /etc/init.d/jackd-network-rp
update-rc.d jackd-network-rp defaults 99
Receive data from network
With netjack
Disadvantage: need to access on ip/port of sender((sounds weird, but the "server"<=>
receiver connect to the "client"<=>
sender)). See zita as alternative.
jack_netsource -H 192.168.2.30
Require: jackd running.
Note: You could specify a port with -p option.
With zita
zita-n2j 192.168.2.30 1234
Require: jackd running and ''zita-njbridge'' package.
Don't forget to connect what come from zita((out)), to speaker((playback))
jack_connect zita-n2j:out_1 system:playback_1
jack_connect zita-n2j:out_2 system:playback_2
Note: n2j mean "network 2 jack".
See jack_lsp to know what are input and output port availables.
root@rp-master:~# jack_lsp
system:playback_1
system:playback_2
zita-n2j:out_1
zita-n2j:out_2