Skip to content

Instantly share code, notes, and snippets.

@Minoru
Created March 18, 2013 04:49
Show Gist options
  • Save Minoru/5185160 to your computer and use it in GitHub Desktop.
Save Minoru/5185160 to your computer and use it in GitHub Desktop.
Bash (sorry!) script that implements idea from here: https://bnw.im/p/QBRE4F In short: it plays an audio file, pausing periodically to check if user is asleep already. If user doesn't respond (by making some noise), the script remembers current position in the file and quits. Next time script is run on the same file, playback is resumed from the…
#!/bin/bash
# I hereby place this script into public domain.
# database is CSV file containing position (in seconds) and filename, separated by a comma
db="$HOME/.mama.db"
# timeout is number of seconds to wait between checks if user is asleep
# default is 10 minutes
timeout="600"
# how much seconds to rewind when pausing to ask user if he's asleep
rewind_on_pause="5"
# turn filename into canonical one
input_file="`readlink -f \"$1\"`"
# check if there's a database of played tracks
if [ ! -f "$db" ]; then
touch "$db"
seekpoint="0"
else
# we only care about the first record found, thus max-count
seekpoint="`grep --max-count 1 \"$input_file\" \"$db\" | cut -f1 -d','`"
fi
# create temporary directory to hold FIFO pipes
tmp="`mktemp -d --tmpdir 'mama.XXX'`"
# create pipes that would be used to control MPlayer
mplayer_control="$tmp/mplayer_control"
mkfifo "$mplayer_control"
mplayer_output="$tmp/mplayer_output"
mkfifo "$mplayer_output"
# spawn mplayer
mplayer -slave -input file="$mplayer_control" "$input_file" 2>/dev/null | grep --line-buffered -i ans_time_position > "$mplayer_output" &
disown %
# seek to absolute position specified in seconds
echo "seek $seekpoint 2" > "$mplayer_control"
while true; do
sleep "$timeout"
echo "pause" > "$mplayer_control"
# rewind the file a bit so user won't loose track of what's going on
# because of pause
echo "seek -$rewind_on_pause" > "$mplayer_control"
# Basic idea of the following few lines: we can listen to the background
# noise and then ask user to say something. We then calculate how much we
# can amplify each file without making it clip (audio term for overflow).
# Those numbers are called "volume adjustment". The bigger the adjustment,
# the quiter is the file. We set an empirical limit: if adjustments differ
# by more than 1.5 times, we say that user said something.
# recording background noise to check how much we can amplify it without
# clipping
echo "Please be silent for a few seconds..." | festival --tts
noise_adjustment="`rec -q -c 1 -n trim 0 3 stat 2>&1 | grep -i adjustment | cut -f 2 -d':' | sed 's/ //g'`"
# now the same but for signal
echo "If you're not asleep, please say so" | festival --tts
signal_adjustment="`rec -q -c 1 -n trim 0 3 stat 2>&1 | grep -i adjustment | cut -f 2 -d':' | sed 's/ //g'`"
result="`echo 1.2*$signal_adjustment \< $noise_adjustment | bc`"
if [ $result -eq 1 ] ; then
# continue playback
echo "pause" > "$mplayer_control"
else
echo "Good night!" | festival --tts
# remove previous record about the file
escaped_input_file="`echo \"$input_file\" | sed 's#/#\\\\/#g'`"
sed -i "/$seekpoint,$escaped_input_file/d" "$db"
# save position and quit
echo "get_time_pos" > "$mplayer_control"
seekpoint="`head -1 \"$mplayer_output\" | sed 's/ANS_TIME_POSITION=//'`"
echo "$seekpoint,$input_file" >> "$db"
echo "quit" > "$mplayer_control"
break
fi
done
rm -rf "$tmp"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment