A small shell script to grab audio from a CD and encode/compress it.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

375 lines
9.8 KiB

#!/bin/bash
# === some global setting & configurations for the script ===
umask 000 # create files with all right for anyone
shopt -s nullglob # expand patterns which match no file to a null string
shopt -s extdebug
# --------------------------------------------------------------
# das Verzeichnis in dem dieses script liegt herausfinden
scriptDir=${0%/*}
scriptDir="${scriptDir/#\./${PWD}}"
case "${scriptDir}" in /*);; *) scriptDir="${PWD}/${scriptDir}";; esac
# --------------------------------------------------------------
# include helpers
. ${scriptDir}/shellUtils.sh
# --------------------------------------------------------------
# string definitions
usage=$"usage: $0 [-t {m|f|o}] [-p path] [-e encoder] [-c cddb-entry] [-h|-?]
[-I interface] [-D device] [-v[v]]
\t-t: you can specify either m for encoding to mp3
\t using lame, or f for making lossless encoding using flac,
\t or o for making ogg/vorbis, or w for uncompressed wav.
\t Omitting this results in encoding to flac.
\t mp3s will be placed under a subfolder mp3 and flacs
\t under a subfolder flac
\t-p: specifies the path to save the encoded data.
\t Defaults to the users home directory.
\t-e: specifies the mp3 encoder to use.
\t valid encoders are actually: lame,bladeenc
\t Defaults to lame.
\t-c: specifies the CDDB-Entry to use.
\t sometimes there is more than 1 entry for a cd in cddb.
\t Then you can specify wich one to use by this option.
\t You can checkout all entries using cddb.pl.
\t-I: specifies cdda2wav interface to use.
\t Valid interfaces are generic_scsi and cooked_ioctl.
\t Please note that cooked_ioctl is not available on all systems.
\t Defaults to generic_scsi
\t-D: specifies device to use with cdda2wav.
\t Defaults to /dev/cdrom
\t-v: make the script more verbose. The verbosity level defaults
\t to 1. When -v is given the level is 2 and -vv increases the
\t level to 3, what means give debug output.
\t-q: make the script silent. Equivalent to -v0
\t-h|
\t-?: Shows this help."
ready=$"done"
# level 1 messages
getCDInfoMsg=$"getting cd info..."
outputDirMsg=$"output to: \$encodingDir"
createXmlMsg=$"create xml file..."
startRipMsg1=$"start ripping cd audio data..."
# level 2 messages
encodeMp3Msg=$"Encode to mp3"
encodeFlacMsg=$"Encode to flac"
encodeOggMsg=$"Encode to ogg"
encodeWavMsg=$"Encode to wav"
startRipMsg2=$"start ripping cd audio data:"
cdInfoMsg=$"DISK:
=====
Tracks: \$dTracks
Length: \$dLength
Index: \$dIndex
Artist: \$dArtist
Title: \$dTitle
Year: \$dYear
Genre: \$dGenre
CDDB: \$cddbId
Text: \$dText
Extra: \$dExtra
TRACKS:
======="
# --------------------------------------------------------------
taOrder="t"
encodingDir=$HOME
encodingType="f"
encoder="lame"
cddbEntry=1
cddaIf="generic_scsi"
cddaDev="/dev/cdrom"
verbose=1
# ----------------------------------------------------------------
# get commandline options
while getopts qvt:p:he:c:I:D: option
do
case $option in
t)
if [ "${OPTARG}" != "m" -a "${OPTARG}" != "f" -a \
"${OPTARG}" != "o" -a "${OPTARG}" != "w" ]
then
echo -e "$usage"
exit 1
fi
encodingType=$OPTARG
;;
p)
if [ ! \( -d ${OPTARG} \) ]
then
echo -e "$usage"
exit 1
fi
encodingDir=$OPTARG
;;
e)
if [ -z ${OPTARG} ]
then
echo -e "$usage"
exit 1
fi
encoder=$OPTARG
;;
c)
if [ ${OPTARG} -lt 1 ]
then
echo -e "$usage"
exit 1
fi
cddbEntry=$OPTARG
;;
v)
if [ "${OPTARG}" -a "${OPTARG}" != "0" -a "${OPTARG}" != "v" ]
then
echo -e "$usage"
exit 1
fi
test -z "${OPTARG}" && verbose=2
test "${OPTARG}" = "0" && verbose=0
test "${OPTARG}" = "v" && verbose=3
;;
q)
verbose=0
;;
I)
if [ "${OPTARG}" != "generic_scsi" -a \
"${OPTARG}" != "cooked_ioctl" ]
then
echo -e "$usage"
exit 1
fi
cddaIf=$OPTARG
;;
D)
if [ ${OPTARG} -lt 1 ]
then
echo -e "$usage"
exit 1
fi
cddaDev=$OPTARG
;;
[h\?])
echo -e "$usage"
exit 1
;;
esac
done
# ----------------------------------------------------------------
echo "verbose: $verbose"
# ----------------------------------------------------------------
# set encodingDir for used encodingType
case ${encodingType} in
m)
encodingDir="$encodingDir/mp3"
test ${verbose} -ge 2 && echo ${encodeMp3Msg}
;;
f)
encodingDir="$encodingDir/flac"
test ${verbose} -ge 2 && echo ${encodeFlacMsg}
;;
o)
encodingDir="$encodingDir/ogg"
test ${verbose} -ge 2 && echo ${encodeOggMsg}
;;
w)
encodingDir="$encodingDir/wav"
test ${verbose} -ge 2 && echo ${encodeWavMsg}
;;
esac
# ----------------------------------------------------------------
test ${verbose} -ge 1 && echo -n ${getCDInfoMsg}
getCDInfo # gets all info about the CD. Look in shellUtils for more info.
test ${verbose} -ge 1 && echo ${ready}
if [ ${verbose} -ge 2 ]
then
cat <<-EOF
$cdInfoMsg
EOF
i=0
while [ $i -lt ${#tTitle[@]} ]
do
echo -n "${tArtist[$i]} - ${tTitle[$i]} "
echo "([${tStartSec[$i]}-${tEndSec[$i]}] ${tLength[$i]})"
i=$((i+1))
done
fi
encodingDir="${encodingDir}/${dArtist}/${dTitle}"
mkdir -p "${encodingDir}"
test ${verbose} -ge 1 && eval "echo ${outputDirMsg}"
# ----------------------------------------------------------------
# fill xml file with data
test ${verbose} -ge 1 && echo -n "${createXmlMsg}"
xmlFile="${encodingDir}/cdinfo.xml"
xml_dText="`echo "${dText}" | recode utf8..h0`"
xml_dExtra="`echo "${dExtra}" | recode utf8..h0`"
xml_dArtist="`echo "${dArtist}" | recode utf8..h0`"
xml_dTitle="`echo "${dTitle}" | recode utf8..h0`"
cat >"${xmlFile}" <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cdInfo SYSTEM \"cdInfo.dtd\">
<cdinfo>
<cdindex>${dIndex}</cdindex>
<cddb>${cddbId}</cddb>
<cd-text>${xml_dText}</cd-text>
<cd-extra>${xml_dExtra}</cd-extra>
<cd-artist>${xml_dArtist}</cd-artist>
<cd-title>${xml_dTitle}</cd-title>
<cd-year>${dYear}</cd-year>
<cd-genre>${dGenre}</cd-genre>
<cd-time>${dLength}</cd-time>
<cd-tracks>${dTracks}</cd-tracks>
<cd-comment></cd-comment>
EOF
i=0
while [ $i -lt ${#tTitle[@]} ]
do
trackNr="`printf %02d $((i+1))`"
xml_tTitle="`echo ${tTitle[$i]} | recode utf8..h0`"
xml_tArtist="`echo ${tArtist[$i]} | recode utf8..h0`"
trackEnd=${tEndSec[$i]}
trackStart=${tStartSec[$i]}
trackLen=$((trackEnd-$trackStart))
cat >>"${xmlFile}" <<EOF
<track>
<track-number>$trackNr</track-number>
<track-time>${tLength[$i]}</track-time>
<track-start-sector>${tStartSec[$i]}</track-start-sector>
<track-length>${trackLen}</track-length>
<track-artist>$xml_tArtist</track-artist>
<track-title>$xml_tTitle</track-title>
<track-comment></track-comment>
</track>
EOF
i=$((i+1))
done
echo "</cdinfo>" >>"${xmlFile}"
test ${verbose} -ge 1 && echo "${ready}"
# ----------------------------------------------------------------
# ----------------------------------------------------------------
# now do the ripping
test ${verbose} -eq 1 && echo -n "${startRipMsg1}"
test ${verbose} -ge 2 && echo "${startRipMsg2}"
i=0
while [ $i -lt ${#tTitle[@]} ]
do
trackNr=$((i+1))
# now that i don't forget it again. I use tr to translate \r to \n
# because sed does't recognise a line with only \r at its end as a line.
# Therefor sed reads until output of cdda2wav ends and does all the
# processing at once, so the percentage is not shown correctly
if [ ${verbose} -ge 2 ]
then
outCmd="tr '\r' '\n' |
sed '/^ [0-9]/!d;s/^.* \([0-9]*%\).*$/\r'\"\${outStr}\"'\1/' |
tr -d '\n'"
else
outCmd="cat >/dev/null"
fi
case ${encodingType} in
f)
outFile="`printf %02d ${trackNr}`-${tTitle[$i]}.flac"
outStr="track-$trackNr => ${outFile}: "
(
exec 2>&1
cdda2wav -H -D/dev/cdrom -I${cddaIf} -t${trackNr} - |\
flac -c -f \
-T artist="${tArtist[$i]}" -T album="${dTitle}" \
-T genre="${dGenre}" -T title="${tTitle[$i]}" \
-T tracknumber="${trackNr}" -T tracknum="${trackNr}" \
-T date="${dYear}" -T comment="" \
-o "${encodingDir}/${outFile}" - 2>/dev/null
) | $outCmd
;;
m)
outFile="`printf %02d ${trackNr}`-${tTitle[$i]}.mp3"
outStr="track-$trackNr => ${outFile}: "
case ${encoder} in
lame)
(
exec 2>&1
cdda2wav -H -D/dev/cdrom -I${cddaIf} -t${trackNr} - |\
lame -V2 \
--ta "${tArtist[$i]}" --tl "${dTitle}" \
--tg "${dGenre}" --tt "${tTitle[$i]}" \
--tn "${trackNr}" --ty "${dYear}" \
--tc "" \
- "${encodingDir}/${outFile}" 2>/dev/null
) | tr '\r' '\n' |\
sed '/^ [0-9]/!d;s/^.* \([0-9]*%\).*$/\r'"${outStr}"'\1/' |\
tr -d '\n'
;;
bladeenc)
(
exec 2>&1
cdda2wav -H -D/dev/cdrom -I${cddaIf} -t${trackNr} - |\
bladeenc -progress=0 STDIN \
"${encodingDir}/${outFile}" 2>/dev/null
) | tr '\r' '\n' |\
sed '/^ [0-9]/!d;s/^.* \([0-9]*%\).*$/\r'"${outStr}"'\1/' |\
tr -d '\n'
;;
esac
;;
o)
outFile="`printf %02d ${trackNr}`-${tTitle[$i]}.ogg"
outStr="track-$trackNr => ${outFile}: "
(
exec 2>&1
cdda2wav -H -D/dev/cdrom -I${cddaIf} -t${trackNr} - |\
oggenc -a "${tArtist[$i]}" -l "${dTitle}" \
-G "${dGenre}" -t "${tTitle[$i]}" \
-N "${trackNr}" -d "${dYear}" \
-c "" \
-o "${encodingDir}/${outFile}" - 2>/dev/null
) | tr '\r' '\n' |\
sed '/^ [0-9]/!d;s/^.* \([0-9]*%\).*$/\r'"${outStr}"'\1/' |\
tr -d '\n'
;;
w)
outFile="`printf %02d ${trackNr}`-${tTitle[$i]}.wav"
outStr="track-$trackNr => ${outFile}: "
(
exec 2>&1
cdda2wav -H -D/dev/cdrom -I${cddaIf} -t${trackNr} - >\
"${encodingDir}/${outFile}"
) | tr '\r' '\n' |\
sed '/^ [0-9]/!d;s/^.* \([0-9]*%\).*$/\r'"${outStr}"'\1/' |\
tr -d '\n'
;;
esac
echo # do a newline after each file
i=$((i+1))
done
test ${verbose} -eq 1 && echo "${ready}"
# ----------------------------------------------------------------