#!/bin/sh
#
# wf2wav - convert W.F. file from runfile waveform into RIFF WAVE (.wav) file
# wf2mp3 - convert W.F. file from runfile waveform into MPEG layer 3 (.mp3) file
# wf2dsp - convert W.F. file from runfile waveform into DSP sound output
#
# Usage:  wf2wav [-V] [-v vol] [-r rate] [-t st,en] runname.wnn [sopt] [outfile]
#	  wf2mp3 [-V] [-v vol] [-t st,en] runname.wnn [sopt] [outfile]
#	  wf2dsp [-V] [-v vol] [-t st,en] runname.wnn [sopt]
# where:  -V		sets verbose output for sox
#	  -v vol	sets output gain factor for signal volume (default auto)
#	  -r rate	sets output sample rate in Hertz (default 11025)
#			(output rate fixed at 16 KHz/24 kbps for .mp3, or
#			automatically set for DSP playback)
#	  -t st,en	specifies the start and end of the range to convert,
#			in seconds (default is 0 to max)
#	  sopt		sox options for output format or effects
# If no sox options or outfile is specified, the default is to output a .wav
# (or .mp3) file on standard output.  If outfile is specified, it must have
# the correct file name extension (.wav or .mp3).
#
# Makes use of sox (Sound eXchange) program on Linux to do conversion.
# Typical usage of sox for this is...
# sox -V -c 1 -r 5000 -t .sw -x dwf0404.w14 -r 11025 -v 128 w14.wav
# See sox(1) for details.
# Encodes MP3 with notlame (http://users.rsise.anu.edu.au/~conrad/not_lame/).
# wf2dsp plays audio using /dev/dsp on Linux systems.
#
# Copyright (c) 2002-6, Gilles Detillieux, Spinal Cord Research Centre,
# University of Manitoba.  All Rights Reserved.
#

NEURODIR=${NEURODIR:-/usr/neuro}
ddopts=
verbose=
volume=auto
rate=11025
range=
while :
do
	case "$1" in
	-\?|-help|--help)	sed -n '3,/^# Univ/s/^#/ /p' "$0"; exit ;;
	-V)	verbose="$1"; shift ;;
	-v)	shift; volume="$1"; shift ;;
	-r)	shift; rate="$1"; shift ;;
	-t)	shift; range="$1"; shift ;;
	*)	break ;;
	esac
done

case "$1" in
*.w[0-9][0-9])	infile="$1"; shift ;;
*)	echo "Usage:  $0 [-V] [-v volume] [-r rate] [-t st,en] runname.wnn [sox-options] [outfile]
	or $0 --help	for detailed usage information" >&2
	exit 1 ;;
esac

runname=`expr "$infile" : '\(.*\)\.w..'`
wfn=`expr "$infile" : '.*\.w0*\([0-9][0-9]*\)'`

if [ ! -r "$infile" ]
then
	echo "$0: Can't open '$infile'" >&2; exit 2
fi
if [ ! -r "$runname.frm" ]
then
	echo "$0: Can't open '$runname.frm'" >&2; exit 2
fi

case "$verbose" in
-V)	echo "Checking effective sample rate of W.F. $wfn in '$runname'..." >&2 ;;
esac
freq=`dumprun "$runname" | awk '/^Sampling rate:/{f=$3}; /^WF/{w=1}; w==1 && /^ *'"$wfn"' / {print f/$3}'`
case "$verbose" in
-V)	echo "Got '$freq'." >&2 ;;
esac
case "$freq" in
[0-9]*)	;;
*)	echo "$0: Can't determine effective rate of W.F. $wfn in '$runname'" >&2
	exit 1 ;;
esac

range=`echo "$range" | tr -d ' '`
case "$range" in
""|[Aa][Ll][Ll])
	;;
[0-9]*\,[0-9]* | [0-9]*\,[Mm][Aa][Xx])
	ddopts="$ddopts bs=2"
	start=`echo "$range" | sed 's/^\([-0-9.e+]*\),.*/\1/'`
	end=`echo "$range" | sed 's/^[^,]*, *\([-0-9.e+MmAaXx]*\) *$/\1/'`
	case "$start,$end" in
	[0-9]*\,[0-9Mm]*)	;;
	*)	echo "$0: Invalid range specified: -t $range" >&2
		exit 1
		;;
	esac
	case "$start" in
	0)	;;
	[0-9]*)	start=`echo "$start" | awk '{print int($1 * '"$freq"')}'`
		ddopts="$ddopts skip=$start" ;;
	*)	echo "$o: Unknown start value '$start', assuming 0" >&2
		start=0 ;;
	esac
	case "$end" in
	[0-9]*)	end=`echo "$end" | awk '{print int($1 * '"$freq"' - '"$start"')}'`
		ddopts="$ddopts count=$end" ;;
	*)	case "$end" in
		[Mm][Aa][Xx])	;;
		*)	echo "$0: Unknown end value '$end', assuming maximum" >&2 ;;
		esac
		;;
	esac
	;;
*)	echo "$0: Invalid time range specified: -t $range" >&2
	exit 1
	;;
esac

case "$verbose" in
-V)	echo "Got '`$NEURODIR/src/util/byteorder 2>/dev/null`' for byte order." >&2 ;;
esac
case "`$NEURODIR/src/util/byteorder 2>/dev/null`" in
[1|3])	;;
*)	ddopts="$ddopts conv=swab" ;;
esac

case "$volume" in
auto)	
	case "$verbose" in
	-V)	echo "Automatic volume check for W.F. $wfn..." >&2 ;;
	esac
	volume=`dd $ddopts if="$infile" 2>/dev/null | sox -c 1 -r "$freq" -t .sw - -e stat -v 2>&1`
	case "$verbose" in
	-V)	echo "Got '$volume'." >&2 ;;
	esac
	;;
esac

case "$0" in
*mp3)
	krate=16
	rate="${krate}000"
	soxopt="-x -t .sw"
	outfile=
	for arg
	do
		soxopt="$soxopt $outfile"
		outfile="$arg"
		case "$verbose" in
		-V)	echo "Output arg: $arg" >&2 ;;
		esac
	done
	case "$outfile" in
	*.[Mm][Pp]3)	;;
	'')		outfile=- ;;
	*)		soxopt="$soxopt $outfile"; outfile=- ;;
	esac
	case "$verbose" in
	-V)	echo >&2 "Running sox through notlame...
	 " \
dd $ddopts if="$infile" \| sox $verbose -c 1 -r "$freq" -t .sw - -r "$rate" -v "$volume" $soxopt - \| notlame -r -m m -b 24 -s "$krate" - "$outfile"
		dd $ddopts if="$infile" | sox $verbose -c 1 -r "$freq" -t .sw - -r "$rate" -v "$volume" $soxopt - | notlame -r -m m -b 24 -s "$krate" - "$outfile"
		;;
	*)
		dd $ddopts if="$infile" 2>/dev/null | sox $verbose -c 1 -r "$freq" -t .sw - -r "$rate" -v "$volume" $soxopt - | notlame -r -m m -b 24 -s "$krate" - "$outfile" 2>/dev/null
		;;
	esac

	exit
	;;
*dsp)
	set -- ${@+"$@"} -t ossdsp -s -w /dev/dsp
	rate=`echo "$freq" | awk '$1<4000 {print 4000}; $1>=4000 {print $1}'`
	;;
esac

case "$#" in
0)	set -- -t .wav - ;;
esac

case "$verbose" in
-V)	echo >&2 "Running sox...
 " \
dd $ddopts if="$infile" \| sox $verbose -c 1 -r "$freq" -t .sw - -r "$rate" -v "$volume" ${@+"$@"}
	dd $ddopts if="$infile"
	;;
*)	dd $ddopts if="$infile" 2>/dev/null
esac |
    sox $verbose -c 1 -r "$freq" -t .sw - -r "$rate" -v "$volume" ${@+"$@"}
