Skip to content

Instantly share code, notes, and snippets.

@jason-costello
Forked from oleq/_README.md
Created August 5, 2017 02:19
Show Gist options
  • Select an option

  • Save jason-costello/c8c936ddb2b537d3d9b6cbba1d48d260 to your computer and use it in GitHub Desktop.

Select an option

Save jason-costello/c8c936ddb2b537d3d9b6cbba1d48d260 to your computer and use it in GitHub Desktop.
A2DP audio streaming using Raspberry PI (Raspbian Jessie)
#!/bin/bash
PA_SINK="alsa_output.0.analog-stereo"
LOG_FILE=/var/log/a2dp-autoconnect
MAC=$(echo "$NAME" | sed 's/:/_/g' | sed 's/\"//g')
BT_USER=pi
function log {
echo "[$(date)]: $*" >> $LOG_FILE
}
function checkSource {
# Get the current sources
local _sources=$(sudo -u "$BT_USER" pactl list sources short)
# Check if any sources are currently running
# and that our new device is valid.
if [[ ! "$_sources" =~ RUNIING ]] && [[ "$_sources" =~ "$1" ]] ; then
log "Validated new source: $1"
log "$1"
fi
}
function setVolume {
# Set our volume to max
sudo -u "$BT_USER" pacmd set-sink-volume 0 65537
sudo -u "$BT_USER" amixer set Master 100%
}
function connect {
# Connect source to sink
sudo -u "$BT_USER" pactl load-module module-loopback \
source="$1" sink="$PA_SINK" rate=44100 adjust_time=0
}
log "Change for device $MAC detected, running $ACTION"
if [ "$ACTION" = "add" ]
then
incoming=bluez_source."$MAC"
if [ ! -z $(checkSource "$incoming") ] ; then
connect "$incoming"
setVolume
else
log "Source $incoming invalid or some source already running."
fi
fi

Initial setup

Raspberry PI running Raspbian Jessie.

Make sure PI is up–to–date:

sudo apt-get update
sudo apt-get upgrade

Install required packages:

http://www.instructables.com/id/Enhance-your-Raspberry-Pi-media-center-with-Blueto/?ALLSTEPS

sudo apt-get install alsa-utils bluez bluez-tools pulseaudio-module-bluetooth python-gobject python-gobject-2

Not quite sure it's really needed (?):

sudo usermod -a -G lp pi

I used external USB audio interface Creative Sound Blaster Play. The on–board audio produces low–quality, noisy output, so I decided to use something better.

As for Bluetooth dongle, I used Digitus Tiny USB-Adapter, which is discovered as Cambridge Silicon Radio, Ltd Bluetooth Dongle.

Note: I used another dongle (different manufacturer), which was also discovered as Cambridge Silicon Radio... but unable to stream audio. So it's not only about the chip itself but about manufacturers.

See RPi USB Bluetooth adapters for buying ideas. Trial and error is another option, most devices costs below $10.

pi@raspberrypi:~ $ lsusb
...
Bus 001 Device 008: ID 041e:30d3 Creative Technology, Ltd Sound Blaster Play!
...
Bus 001 Device 012: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
...

Setup Bluetooth

pi@raspberrypi:~ $ cat /etc/bluetooth/audio.conf
[General]
Class = 0x20041C
Enable = Source,Sink,Media,Socket
sudo reboot
bluetoothctl
[bluetooth]# list
Controller 00:1A:7D:DA:71:06 raspberrypi [default]
[bluetooth]# agent on
[bluetooth]# default-agent
[bluetooth]# discoverable on
[bluetooth]# scan on

For each device

pair XX:XX:XX:XX:XX:XX
trust XX:XX:XX:XX:XX:XX

Setup PulseAudio

http://www.crazy-audio.com/2014/09/pulseaudio-on-the-raspbery-pi/

pi@raspberrypi:~ $ cat /etc/pulse/daemon.conf
...
enable-remixing = no
enable-lfe-remixing = no
default-sample-format = s32le
default-sample-rate = 192000
alternate-sample-rate = 176000
default-sample-channels = 2
exit-idle-time = -1
...

Configure Sound Blaster Live USB

http://raspberrypi.stackexchange.com/questions/40831/how-do-i-configure-my-sound-for-jasper-on-raspbian-jessie

pi@raspberrypi:~ $ cat /proc/asound/modules
 0 snd_bcm2835
 1 snd_usb_audio
pi@raspberrypi:~ $ cat /etc/modprobe.d/alsa-base.conf
# This sets the index value of the cards but doesn't reorder.
options snd_usb_audio index=0
options snd_bcm2835 index=1

# Does the reordering.
options snd slots=snd-usb-audio,snd-bcm2835
sudo reboot
pi@raspberrypi:~ $ cat /proc/asound/modules
 0 snd_usb_audio
 1 snd_bcm2835

Setup auto connecting

The trick is to redirect a source (like iPhone) to sink (ALSA):

pi@raspberrypi:~ $ pactl list sources short
0   alsa_output.0.analog-stereo.monitor module-alsa-card.c  s16le 2ch 48000Hz   IDLE
1   alsa_input.0.analog-mono    module-alsa-card.c  s16le 1ch 48000Hz   IDLE
4   bluez_source.A8_88_08_11_AB_4B  module-bluez5-device.c  s16le 2ch 44100Hz   RUNNING

pi@raspberrypi:~ $ pactl list sinks short
0   alsa_output.0.analog-stereo module-alsa-card.c  s16le 2ch 48000Hz   RUNNING

Add udev rule which executes a2dp-autoconnect script each time a bluetooth device is connected

pi@raspberrypi:~ $ sudo cat /etc/udev/rules.d/99-input.rules
KERNEL=="input[0-9]*", RUN+="/home/pi/a2dp-autoconnect"

The script is an extended version of http://blog.mrverrall.co.uk/2013/01/raspberry-pi-a2dp-bluetooth-audio.html. It redirects a new bluetooth device to the right sink and sets the right volume level.

I located it in /home/pi/a2dp-autoconnect then set it executable:

pi@raspberrypi:~ $ chmod +x a2dp-autoconnect

to observe connection log "live":

pi@raspberrypi:~ $ tail -f /var/log/a2dp-autoconnect
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment