Home of the Squeezebox™ & Transporter® network music players.
Results 1 to 5 of 5
  1. #1
    Senior Member
    Join Date
    Apr 2008
    Location
    Paris, France
    Posts
    2,109

    A door chime system for Squeezebox players with PCP 3.22. Or something.

    I thought I'd share my recipe for overlaying music playing on pCP machines with audio jingles. This is a simplified version of a working setup with multiple emitters, multiple sounds, multiple players.

    It uses multicast over UDP to let many devices receive the order to do something (generally: play a sound.) Each device can elect to execute or discard the order, according to its local configuration. So you can arbitrary link one event from one emitter to one receiver to one output.
    What gets sent via multicast is a simple ASCII string, not audio itself. In the case of pCP players they select a local wav file corresponding to the string, but non-audio receivers are possible too. The payload is extremely small so network load is minimal.
    Local processing is fast enough to ensure the delay between sending (pressing a button) and executing (hearing a sound) feels ok. I've elected to let socat do the multicast magic, as it is ported to many platforms.
    When multiple audio receivers play a jingle, there is no sync mechanism but in effect with pCP you get all receivers to play at the same instant.

    The system works as long as there is one emitter and one receiver active on the network, so it's independent from LMS. To overlay an incoming audio jingle over possibly playing music, I've determined a double ramp works best: music volume goes down gradually while the jingle volume goes up gradually, and back.
    With the JustBoom amp HAT I've used -and all i2s devices?- there is no hardware mixer so a software mixer is defined with ALSA with 2 sources and 2 volume controls.
    The script that manipulates volume controls is very basic, it works with jingles that are 4 or 5 seconds long. YMMV.

    This is how to play a jingle on pCP 3.22 (normal kernel version) with an add-on amp on a Pi 3 wired via ethernet:
    1. Setup pCP via the web interface, at http://<address-of-picoreplayer>:
      • Install the socat extension. Select Main Page, Beta (bottom of page), then Extensions. On that new page, make sure you're using the Official piCore repository (default), then in "Available extensions in the Official piCore repository" select socat.tcz and press Load.
      • Select your add-on DAC or amp. Select Squeezelite Settings, then pick your add-on model under "Choose Audio output". Click Save. Reboot if needed, come back here, click Audio card control, and disable the onboard soundcard.
      • Setup Squeezelite to use an ALSA audio mixer. Select Squeezelite Settings, then in field "Output setting" enter the value "music" (without quotes). Press Save. If you restart Squeezelite as prompted it will now fail, that's ok.
      • Set pCP to run a script at boot. Select Tweaks, then under "User commands", enter user command "/home/tc/gong.sh" (no quotes) and press Save.
    2. Locate a wav jingle file and copy it under the name "action1.wav" to pCP, e.g. "scp jingle.wav tc@<address-of-picoreplayer>:~/action1.wav". The setup is known to work with audio files ~ 4-5 secs. in duration, format "Signed 16 bit Little Endian, Rate 44100 Hz, Mono"
    3. Customize pCP via the shell, at ssh tc@<address-of-picoreplayer>:
      • Replace the stock /etc/asound.conf file with this:
        Code:
        ## Onboard audio disabled in /boot/config.txt
        ## Otherwise volume sliders that use "control.card X"
        ## could attach to the wrong card at boot in pCP 3.2.0.
        ##
        ## Alsaequal removed from this file. Some issues controlling
        ## softvols with equal in pCP 3.2.0. Add it back if you want.  
        ##
        ## Make sure hardware volume control "Digital" is set to
        ## a safe value, you probably don't want a jingle to play
        ## at full power by accident
        ##
        
        ## A) Devices available to applications 
        ##
        # Squeezelite is set to use this device
        # This softvol allows to ramp down-up music when an application
        # plays another sound.
        # Nominal state is: 100%
        pcm.music {
        	type softvol
        	slave.pcm plug:dmixer
        	control.name musicvol
        	control.card 0
        }
        
        # Same story here: ramp up-down sounds sent by other applications
        # Nominal state is: 0%
        pcm.gong {
        	type softvol
        	slave.pcm plug:dmixer 
        	control.name gongvol
        	control.card 0
        }
        
        ## B) Audio output device. Here: Justboom amp HAT
        ##
        # Shared access to our audio card
        pcm.dmixer {
        	type dmix
        	ipc_key 1234
        	ipc_key_add_uid true # Needed ?
        	ipc_perm 0666
        	slave {
        		pcm "hw:CARD=sndrpijustboomd,DEV=0"
        	}
        }
        
        # Whatever ctl magic thing
        ctl.dmixer {
        	type hw
        	card 0
        }
        #EOF
        E.g. from the shell session on pCP, run "cp /etc/asound.conf ~/asound.conf.orig", then copy the code above, run "cat > /etc/asound.conf", paste clipboard contents in the window, and hit ctrl-d.
      • Install the gong.sh script:
        Code:
        #!/bin/sh
        # Receive events via socat and play audio jingles
        
        ##
        ## vars
        ##
        APLAY="/usr/local/bin/aplay"
        AMIXER="/usr/local/bin/amixer"
        APLAY_OPTS_GONG='-q -N -D gong'
        AMIXER_OPTS_MUSIC="-D hw:CARD=sndrpijustboomd -q"
        AMIXER_OPTS_GONG="-D hw:CARD=sndrpijustboomd -q"
        AMIXER_VOLCTL_MUSIC='musicvol'
        AMIXER_VOLCTL_GONG='gongvol'
        RAMP_STEP_MUSIC='1.5%'
        RAMP_SPEED_MUSIC='100000'
        RAMP_LENGTH_MUSIC=20
        RAMP_STEP_GONG='2.3%'
        RAMP_SPEED_GONG='100000'
        RAMP_LENGTH_GONG=10
        BASE_GONG_VOL="10%" # Use only a % string or 0-255 int
        SOCAT="/usr/local/bin/socat"
        SOCAT_ADDR="UDP4-RECVFROM:12345"
        SOCAT_OPTS="ip-add-membership=239.123.123.123:eth0"
        # Accepted clients
        CLIENTS='clt1 clt2'
        # Actions sounds
        SND_action1='/home/tc/action1.wav'
        SND_action2='is-missing'
        
        ##
        ## functions
        ##
        checkInstall(){
            for EXE in "${AMIXER}" "${APLAY}" "${SOCAT}"
            do
        	if [ ! -x "$EXE" ]; then
        	    echo "Executable [$EXE] not found or executable. Exit"
        	    exit
        	fi
            done
        }
        
        InitializeAlsa() {
        # pCP 3.2.0: used to block if Alsa equal was in use.
        # Workaround: spawn then kill the aplay process
        # echo "Opening ALSA to initialize controls."
        ${APLAY} $APLAY_OPTS_GONG /dev/null >/dev/null 2>&1
        }
        
        checkAction() {
        	unset PASS
        	CLT="${1}"
        	ACT="${2}"
        	for T in ${CLIENTS}
        	do
        		if [ "$T" == "$CLT" ]; then
        			eval "FILE=\$SND_${ACT}"
        			if [ -f "$FILE" ]; then
        				PASS=1
        				echo "Client [$T], requested sound [$FILE]"
        			fi
        			break
        		fi
        	done
        }
        
        doAction() {
        		ACTION="${1}"
        		# BACKGROUNDED Ramp music down then up
        		(
        		rampVolume 'music' 'down'
        		# NB usleep 1.000.000 = 1 sec.
        		SHIM='500000'
        		usleep $SHIM
        		rampVolume 'music' 'up'
        		)&
        		# BACKGROUNDED Ramp gong up then down
        		(
        		resetGongVol "${BASE_GONG_VOL}"
        		rampVolume 'gong' 'up'
        		SHIM='1500000'
        		usleep $SHIM
        		rampVolume 'gong' 'down'
        		)&
        		# BACKGROUNDED Play gong
        		( playGong )&
        }
        
        playGong() {
        	eval "GONG=\$SND_${ACTION}"
        	"${APLAY}" ${APLAY_OPTS_GONG} "${GONG}" >/dev/null 2>&1
        }
        
        rampVolume() {
        	# accepts args up or down
        	CONTROL='MUSIC'
        	[ "${1}" == "gong" ] && CONTROL='GONG'
        	UPDOWN='\-'
        	[ "${2}" == "up" ] && UPDOWN='+'
        	eval "STEP=\$RAMP_STEP_${CONTROL}${UPDOWN}"
        	eval "VOLCTL=\$AMIXER_VOLCTL_${CONTROL}"
        	eval "LENGTH=\$RAMP_LENGTH_${CONTROL}"
        	eval "SPEED=\$RAMP_SPEED_${CONTROL}"
        	eval "OPTS=\$AMIXER_OPTS_${CONTROL}"
        	i=0
        	while [ "$i" -lt ${LENGTH} ]
        	do
        		"${AMIXER}" ${OPTS} sset "${VOLCTL}" "${STEP}" >/dev/null 2>&1
        		usleep ${SPEED}
        		i=`expr $((i)) + 1`
        	done
        }
        
        resetGongVol() {
        	LVL="$1"
        	"${AMIXER}" ${AMIXER_OPTS_GONG} sset "${AMIXER_VOLCTL_GONG}" "${LVL}" >/dev/null 2>&1
        }
        
        # Start here
        checkInstall
        InitializeAlsa
        resetGongVol 0
        
        # We listen continuously. Socat quits after receiving one frame
        # echo "Now listening via ${SOCAT} ${SOCAT_ADDR},${SOCAT_OPTS}"
        while true
        do
            LINE=`"${SOCAT}" "${SOCAT_ADDR}",${SOCAT_OPTS} -`
            set -- ${LINE}
            checkAction ${1} ${2}
            # PASS is defined if client is known 
            # and action sound is found
            [ "$PASS" ] && doAction ${2}
        done
        #EOF
        E.g. copy the code above, then from the shell session on pCP, run "cat > /home/tc/gong.sh", paste clipboard contents in the window, and hit ctrl-d. Then run "chmod +x /home/tc/gong.sh" to make the script executable.
      • Save your setup with "pcp bu" on the command line. If you see "your backup is a little large", that's ok. Now reboot with "pcp rb"

      I suggest you start playing music on that player after reboot to make sure all went well. Make sure Squeezelite now uses the "music" output device.


    You can now use any machine on the network to send the order to play your jingle, as long as the thing can run socat (I've used socat v 1.7). If you need to install socat, I'll let you find how on linux, for windows I've used this binary and for OS X I've installed it via Brew.
    Now, enter "echo clt1 action1 | socat - UDP4-DATAGRAM:239.123.123.123:12345,reuseaddr" from your client and you should hear your jingle fade in and out of the music. If you "echo foo bar ..." instead you'll hear nothing as the script receives but disregards the call. And if you shutdown the LMS server the jingle will still play.

    You will certainly want to modify the script, I won't mind... You should also define your own multicast address in the 239.0.0.0/8 network, and pick your own UDP port. If you want to use wifi, pay attention to SOCAT_OPTS in the script.

    HTH
    3 SB 3 • Libratone Loop, Zipp Mini • iPeng (iPhone + iPad) • LMS 7.9 (linux) with plugins: CD Player, WaveInput, Triode's BBC iPlayer by bpa • IRBlaster by Gwendesign (Felix) • Server Power Control by Gordon Harris • Smart Mix, Music Walk With Me, What Was That Tune? by Michael Herger • PowerSave by Jason Holtzapple • Song Info, Song Lyrics by Erland Isaksson • AirPlay Bridge by philippe_44 • WeatherTime by Martin Rehfeld • Auto Dim Display, SaverSwitcher, ContextMenu by Peter Watkins.

  2. #2
    Senior Member Julf's Avatar
    Join Date
    Dec 2010
    Posts
    2,451
    Great! Will be very useful for me, as I need the door bell (IP-enabled, of course) to interrupt my music.
    "To try to judge the real from the false will always be hard. In this fast-growing art of 'high fidelity' the quackery will bear a solid gilt edge that will fool many people" - Paul W Klipsch, 1953

  3. #3
    Senior Member
    Join Date
    Apr 2013
    Location
    UK
    Posts
    1,005
    Nice. How about sending a URL to a web server with a audio jingle file on it..?


    Transcoded from Matt's brain by Tapatalk
    --
    Hardware: 3x Touch, 1x Radio, 2x Receivers, 1 HP Microserver NAS with Debian+LMS 7.9.0
    Music: ~1300 CDs, as 450 GB of 16/44k FLACs. No less than 3x 24/44k albums..

  4. #4
    Senior Member
    Join Date
    Apr 2008
    Location
    Paris, France
    Posts
    2,109
    Quote Originally Posted by drmatt View Post
    Nice. How about sending a URL to a web server with a audio jingle file on it..?


    Transcoded from Matt's brain by Tapatalk
    Sure, why not. Latency would take a hit, though. And if the url points to a huge file, if would fear issues with network bandwidth and local storage. Plus the server needs to be up.
    I see 2 limitations with the system as shown here: 1) use of dmix; this is really sad and, 2) local and awkward configuration through the script for audio receivers; although while configuring the ramps and volumes is a pain, I don’t think you need to change it very often once done.

    In the real application this isn’t used as a door chime, it is used for service calls in a public place, for use by employees or the public. You can ring from windows PCs equipped with touchscreens or from EnOcean wireless-battery less buttons. One of the receivers is a firewall: it logs and dates each call.
    Multicast makes the thing both robust and flexible IMHO.
    Last edited by epoch1970; 2017-10-06 at 15:37.
    3 SB 3 • Libratone Loop, Zipp Mini • iPeng (iPhone + iPad) • LMS 7.9 (linux) with plugins: CD Player, WaveInput, Triode's BBC iPlayer by bpa • IRBlaster by Gwendesign (Felix) • Server Power Control by Gordon Harris • Smart Mix, Music Walk With Me, What Was That Tune? by Michael Herger • PowerSave by Jason Holtzapple • Song Info, Song Lyrics by Erland Isaksson • AirPlay Bridge by philippe_44 • WeatherTime by Martin Rehfeld • Auto Dim Display, SaverSwitcher, ContextMenu by Peter Watkins.

  5. #5
    Senior Member
    Join Date
    Apr 2013
    Location
    UK
    Posts
    1,005
    Indeed. Lots of ways to extend an idea like this for all sorts of use cases.


    Transcoded from Matt's brain by Tapatalk
    --
    Hardware: 3x Touch, 1x Radio, 2x Receivers, 1 HP Microserver NAS with Debian+LMS 7.9.0
    Music: ~1300 CDs, as 450 GB of 16/44k FLACs. No less than 3x 24/44k albums..

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •