#! /bin/bash
# ▗▄▖
#▗▛▀▜
#▐▙ ▟██▖▐▙█▙ ▟█▙
# ▜█▙ ▘▄▟▌▐▛ ▜▌▐▛ ▜▌
# ▜▌▗█▀▜▌▐▌ ▐▌▐▌ ▐▌
#▐▄▄▟▘▐▙▄█▌▐█▄█▘▝█▄█▘
# ▀▀▘ ▀▀▝▘▐▌▀▘ ▝▀▘
# ▐▌
# a tts bash script by Christos Angelopoulos, February 2022
#converts txt to wav
#using the all powerful https://github.com/coqui-ai/TTS
FILE="$(yad --file-selection --filename=Desktop --height='400' --width='800' --title='Sapo - Select File to Read' --window-icon=$HOME/git/sapo/sapo.png --hscroll-policy=never --vscroll-policy=never)"
case $? in
0)
;;
1) exit
;;
esac
DIRECTORY=${FILE%/*}/
NAME=${FILE##*/}
echo "FILE : ""$FILE"
echo "DIRECTORY : " "$DIRECTORY"
echo "NAME : ""$NAME"
mkdir "$DIRECTORY""Sapo_""$NAME"/
##text delimitation to setences
echo $(cat "$FILE")>"$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt # get rid of new lines
##sapofonetix: abbreviation, mispronunciation & alphabet substitutions
sed -i -f $HOME/git/sapo/sapofonetix.sed "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt
#done < "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt
sed -i 's/\.\.\./\.\n/g' "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt # get rid of ...
sed -i "s/\’/\'/g" "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt # get rid of ’
sed -i 's/[\.\!\?\:\;]/\.\n/g' "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt # delimit to .
sed -i 's/\…/\,/g' "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt # get rid of …
sed -i 's/‘//g' "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt # get rid of ‘
sed -i 's/(/\,(/g' "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt # delimit to (
sed -i 's/)/),/g' "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt # delimit to )
sed -i 's/^ *//g' "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt # delete space at beginning of line
sed -i 's/^\;$//g' "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt # get rid of just ; lines
sed -i 's/^\.$//g' "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt # get rid of just . lines
sed -i "s/^'//g" "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt #get rid of ' at start of line
sed -i 's/^Ey /A /g' "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt # A's at line start are usually articles, not capitals
#sed -i 's/\,/\n/3' "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt # delimit to 3rd occurence of ,
#sed -i "s/—/ — /g" "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt # put spaces around —, to not interfere with pronunciation
sed -i "s/—/\,/g" "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt # convert — to ,
##################extra delimit to comma and space ###################################
DELIM=$(cat "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt|wc -l)
while [ $DELIM -ge 1 ]
do
CUR_DELIM_LINE=$(cat "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt|head -$DELIM|tail +$DELIM)
CHAR_COUNT=$(echo "$CUR_DELIM_LINE"|wc -m)
while [ $CHAR_COUNT -gt 290 ]
do
echo "character count : "$CHAR_COUNT
echo "characters > 290"
COMMA_COUNT=$(echo "$CUR_DELIM_LINE"| sed -e 's/\(.\)/\1\n/g' | grep "," | wc -l)
echo "comma count : "$COMMA_COUNT
if [ $COMMA_COUNT -gt 2 ]
then
echo "commas > 2"
echo $DELIM"s/\,/\n/"$(($COMMA_COUNT - 2))>"$DIRECTORY""Sapo_""$NAME"/script.sed
sed -i -f "$DIRECTORY""Sapo_""$NAME"/script.sed "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt
fi
if [ $COMMA_COUNT -le 2 ]
then
echo "No commas to delimit to, proceed delimiting with spaces(limit 30)"
SPACE_COUNT=$(echo "$CUR_DELIM_LINE"| sed -e 's/\(.\)/\1\n/g' | grep " " | wc -l)
echo "Space count : "$SPACE_COUNT
echo $DELIM"s/\ /\n/"$(($SPACE_COUNT - 30))>"$DIRECTORY""Sapo_""$NAME"/script.sed
sed -i -f "$DIRECTORY""Sapo_""$NAME"/script.sed "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt
fi
CUR_DELIM_LINE=$(cat "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt|head -$DELIM|tail +$DELIM)
CHAR_COUNT=$(echo "$CUR_DELIM_LINE"|wc -m)
done
echo "Task completed for line "$DELIM
((DELIM--))
done
yad --image "$HOME/git/sapo/sapo.png" --height=40 --width=400 --title="${NAME} - Sapo" --button=gtk-cancel:1 --button=gtk-open:2 --button=gtk-ok:0 --text="The text is prepared, Press:
1. Open to edit the new file
2. OK to proceed to speech conversion." --window-icon=$HOME/git/sapo/sapo.png
case $? in
0)
;;
1) exit
;;
2) xed "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt & yad --image "$HOME/git/sapo/sapo.png" --height=40 --width=400 --title="${NAME} - Sapo" --button=gtk-cancel:1 --button=gtk-ok:0 --text="If you are done editing $NAME\sentenced.txt, press OK to continue!" --window-icon=$HOME/git/sapo/sapo.png
case $? in
0)
;;
1) exit
;;
esac
esac
TOTALLINES=$(cat "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt|wc -l)
LINE=1
(
while [ $LINE -le $TOTALLINES ]
do
CURRENTLINE=$(head -$LINE "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt|tail +$LINE)
FORMLINE="$(printf "%.6d" $LINE)"
tts --text "$CURRENTLINE" --out_path "$DIRECTORY""Sapo_""$NAME"/$FORMLINE.wav
####error detection routine######
CURRENTLINE_LENGTH=$(echo $CURRENTLINE|wc -m)
WAV_LENGTH=$(jq -n $(sox "$DIRECTORY""Sapo_""$NAME"/$FORMLINE.wav -n stat 2>&1 |sed -n 's#^Length (seconds):[^0-9]*\([0-9.]*\)$#\1#p')-0.660)
RATIO=$(jq -n $CURRENTLINE_LENGTH/$WAV_LENGTH|sed 's/\..*$//')
if [ $RATIO -le 8 ]
then
echo $LINE $FORMLINE.wav $CURRENTLINE_LENGTH $WAV_LENGTH $RATIO>>"$DIRECTORY""Sapo_""$NAME"/errors.tsv
fi
###################################
LINE100=$(( $LINE * 100 ))
PERCENTAGE=$(( $LINE100 / $TOTALLINES))
###Estimating Estimated time of arrival
LINESLEFT=$(( $TOTALLINES - $LINE ))
SECONDS=$(( $LINESLEFT * 8 ))
HOURS=$(( SECONDS / 3600 ))
SECHLEFT=$(( $SECONDS - $((HOURS * 3600 )) ))
MINUTES=$(( $SECHLEFT / 60 ))
SECMLEFT=$(( $SECHLEFT - $((MINUTES * 60 )) ))
HOURSTRING="$HOURS"" hrs"
MINUTESTRING="$MINUTES"" mins"
## if hours / minutes left are 0 , they are not mentioned
if [ $HOURS -eq 0 ]
then
HOURSTRING=""
fi
if [ $MINUTES -eq 0 ]
then
MINUTESTRING=""
fi
#echo line starting with #, updated in the yad progress bar window
echo "# Reading line $(( $LINE + 1)) of $TOTALLINES from "$NAME" ($PERCENTAGE%). Roughly remaining : "$HOURSTRING" "$MINUTESTRING" " $SECMLEFT" secs"
echo "$PERCENTAGE"
((LINE++))
done
) |
yad --progress --height="40" \
--title="Sapo - Reading . . . ${NAME}" \
--percentage=0 \
--height=40 \
--width="500" \
--window-icon=$HOME/git/sapo/sapo.png \
--image "$HOME/git/sapo/sapo_progress.png" \
--auto-close
#--text="Preparing to read..." \
case $? in
0)
;;
1) exit
;;
esac
##### Error correction routine ######
(
TOTAL_ERRORS=$(cat "$DIRECTORY""Sapo_""$NAME"/errors.tsv|wc -l)
ERROR_LINE=1
while [ $ERROR_LINE -le $TOTAL_ERRORS ]
do
CURRENT_ERROR_LINE=$(cat "$DIRECTORY""Sapo_""$NAME"/errors.tsv|head -$ERROR_LINE|tail +$ERROR_LINE)
ERROR_TEXT_LINE=$(echo $CURRENT_ERROR_LINE|awk '{print $1}')
ERROR_WAV=$(echo $CURRENT_ERROR_LINE|awk '{print $2}')
echo "#Attempting to fix error $ERROR_LINE of $TOTAL_ERRORS, line $ERROR_TEXT_LINE from $NAME.sentenced.txt"
###################################
ERROR_LINE100=$(( $ERROR_LINE * 100 ))
ERROR_PERCENTAGE=$(( $ERROR_LINE100 / $TOTAL_ERRORS))
echo "$ERROR_PERCENTAGE"
tts --text "$(cat "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt|head -$ERROR_TEXT_LINE|tail +$ERROR_TEXT_LINE)" --out_path "$DIRECTORY""Sapo_""$NAME"/$ERROR_WAV
((ERROR_LINE++))
done
)|
yad --progress --height="40" \
--title="Sapo - Fixing Errors . . . ${NAME}" \
--percentage=0 \
--height=40 \
--width="500" \
--window-icon=$HOME/git/sapo/sapo.png \
--image "$HOME/git/sapo/sapo_progress.png" \
--auto-close
####### FIXING ERRORS ONE BY ONE ############
TOTAL_ERRORS=$(cat "$DIRECTORY""Sapo_""$NAME"/errors.tsv|wc -l)
ERROR_LINE=1
while [ $ERROR_LINE -le $TOTAL_ERRORS ]
do
CURRENT_ERROR_LINE=$(cat "$DIRECTORY""Sapo_""$NAME"/errors.tsv|head -$ERROR_LINE|tail +$ERROR_LINE)
ERROR_TEXT_LINE=$(echo $CURRENT_ERROR_LINE|awk '{print $1}')
ERROR_WAV=$(echo $CURRENT_ERROR_LINE|awk '{print $2}')
TEXT_TO_CORRECT="$(cat "$DIRECTORY""Sapo_""$NAME"/"$NAME"sentenced.txt|head -$ERROR_TEXT_LINE|tail +$ERROR_TEXT_LINE)"
GO=false
while [[ $GO == false ]]
do
yad --image "$HOME/git/sapo/sapo.png" \
--title="Line $ERROR_TEXT_LINE - $NAME" \
--button=gtk-cancel:1 \
--button='▶️ Play Audio':2 \
--button='🔃 Re-Render':3 \
--button='✂️ Trim Clutter':4 \
--button='🗡 Split-Render':5 \
--button='🎵 Edit audio':7 \
--button='❌ Remove audio':6 \
--button='😃 Keep/Next':0 \
--text="Text of line $ERROR_TEXT_LINE :
$TEXT_TO_CORRECT
What would you like to do?" \
--window-icon=$HOME/git/sapo/sapo.png
case $? in
0) GO=true
;;
1) GO=true;exit
;;
2) if [[ -e "$DIRECTORY""Sapo_""$NAME"/$ERROR_WAV ]];then celluloid "$DIRECTORY""Sapo_""$NAME"/$ERROR_WAV & else notify-send "There is no file ""$DIRECTORY""Sapo_""$NAME"/"$ERROR_WAV"".";fi
;;
3) s="$(yad --entry --width="600" --text="This is the original text of the line $ERROR_TEXT_LINE.
Edit as you wish, then hit OK to render." --entry-text="$TEXT_TO_CORRECT" --window-icon=$HOME/git/sapo/sapo.png --title="Line $ERROR_TEXT_LINE - $NAME")";tts --text "$s" --out_path "$DIRECTORY""Sapo_""$NAME"/$ERROR_WAV
;;
4)sox -V3 "$DIRECTORY""Sapo_""$NAME"/$ERROR_WAV "$DIRECTORY""Sapo_""$NAME"/temp.wav silence 1 0.50 0.1% 1 0.5 0.1%;sox "$DIRECTORY""Sapo_""$NAME"/temp.wav "$DIRECTORY""Sapo_""$NAME"/$ERROR_WAV pad 0 0.5;rm "$DIRECTORY""Sapo_""$NAME"/temp.wav
;;
5)s="$(yad --entry --width="600" --text="Split the printed text roughly in half with the pipe symbol (|), so that it can be rendered in two batches: " --entry-text="$TEXT_TO_CORRECT" --window-icon=$HOME/git/sapo/sapo.png --title="Line $ERROR_TEXT_LINE - $NAME")";s1="$(echo $s|sed 's/|.*$//')";s2="$(echo $s|sed 's/^.*|//')"; echo $s1;echo $s2 ; tts --text "$s1" --out_path "$DIRECTORY""Sapo_""$NAME"/1temp.wav; tts --text "$s2" --out_path "$DIRECTORY""Sapo_""$NAME"/2temp.wav;sox "$DIRECTORY""Sapo_""$NAME"/1temp.wav "$DIRECTORY""Sapo_""$NAME"/2temp.wav "$DIRECTORY""Sapo_""$NAME"/$ERROR_WAV ; rm "$DIRECTORY""Sapo_""$NAME"/1temp.wav "$DIRECTORY""Sapo_""$NAME"/2temp.wav
;;
6) if [[ -e "$DIRECTORY""Sapo_""$NAME"/$ERROR_WAV ]];then rm "$DIRECTORY""Sapo_""$NAME"/$ERROR_WAV;notify-send "$DIRECTORY""Sapo_""$NAME"/"$ERROR_WAV"" has been deleted."; else notify-send "There is no file ""$DIRECTORY""Sapo_""$NAME"/"$ERROR_WAV"". Already deleted?";fi
;;
7)audacity "$DIRECTORY""Sapo_""$NAME"/$ERROR_WAV
;;
esac
done
((ERROR_LINE++))
done
sox "$DIRECTORY""Sapo_""$NAME"/*.wav "$DIRECTORY""Sapo_""$NAME"/"$NAME".wav
yad --image "$HOME/git/sapo/sapo.png" --height=40 --width=400 --title="${NAME} - Sapo" --text="Reading of ""$NAME"" is complete!" --window-icon=$HOME/git/sapo/sapo.png