2

OK, so, I have this non-functional shell script, which I am rewriting piece by piece in python, except I am getting an "unexpected "|" error" from the shell (see below):

#/bin/sh
LINES=`cat $@ | wc -l`

for i in `seq 1 $lines`; do

head -n $i $@ | tail -n 1 | text2wave -o temp.wav
sox "otherstuff.wav" "temp.wav" "silence.wav" "output.wav"
mv output.wav otherstuff.wav
rm -rf temp.wav

done

Which isn't really feasible in practice. But if I know the number of lines in a file, I can run it on a particular file to TTS the entire file and insert 10 seconds of silence between each line, because I don't have to say

LINES=`cat $@ | wc -l`

In the interest of flow control, and a way of incorporating the line count into a script I can use everywhere, am going to use Python to do this job. So far I have this fragment, also non-functional:

import linecache, os

for i in range(linelength):
    lineone = linecache.getline(filename, i)
    os.system("echo " + lineone + "|" + "festival --tts")

which gives this error in the IPython interpreter:

d 68.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
d 67.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
c 52.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
c 42.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
c 71.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
c 51.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
c 19.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
c 18.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
b 16.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
b 15.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
b 1.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
d 16.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
d 14.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
a 96.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
a 95.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
a 35.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
a 25.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
d 74.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
d 83.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
a 9.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
d 9.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
b 97.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
b 99.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
b 76.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
b 77.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
d 89.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
d 99.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
b 94.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
d 54.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
d 66.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
c 81.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512
c 61.
sh: 2: Syntax error: "|" unexpected
Out[60]: 512

and which replicates

for i in `seq 1 $lines`; do

head -n $i $@ | tail -n 1 | text2wave -o temp.wav

but is handier for testing everything, because it simply reads it out (festival and text2wave are part of the same package, one reads things out and the other writes files)...

now, the number of lines being already retrieved and stored in linelength (I didn't have a problem getting python to do that):

If it were simply

for i in range(linelength):
    lineone = linecache.getline(filename, i)
    os.system("echo somestuffnotaline | festival --tts")

then festival would say "somEhstuffnotaLINE", but I would not be as happy as I would if it would say, "c 62" -- "d 74" -- etc, those being the contents of each line in the files I am processing.

ixtmixilix
  • 13,230

2 Answers2

3

Your question is long and rambling and I don't know what you expect for an answer. Going by your title, I think your focus is on this fragment of Python code:

lineone = linecache.getline(filename, i)
os.system("echo " + lineone + "|" + "festival --tts")

Your problem is that lineone is the whole line, including the final newline. You need to, as they say in Perl land, chomp it.

lineone = linecache.getline(filename, i).rstrip('\n')
os.system("echo " + lineone + "|" + "festival --tts")

Your first shell script looks awfully complicated and slow for what it does. Why are you computing the number of lines, then retrieving the lines by number in order? You could simply read the input one line at a time, like you do in Python.

while IFS= read -r line; do
  echo "$line" | text2wave -o temp.wav
  sox "otherstuff.wav" "temp.wav" "silence.wav" "output.wav"
  mv output.wav otherstuff.wav
  rm temp.wav
done

You should be able to simplify this further by using raw audio files, that do not contain a header and so can be concatenated:

while IFS= read -r line; do
  echo "$line" | text2wave -otype raw >>otherstuff.raw
  cat silence.raw >>otherstuff.raw
done
sox … otherstuff.raw otherstuff.wav

You'll need to tell sox what parameters (such as sampling depth) the raw audio file is encoded in.

0

I'd suggest using the popen() call instead of system() and to write the lines to the input stream.

import linecache, os
p = os.popen("festival --tts", "w")
for i in range(linelength):
    lineone = linecache.getline(filename, i)
    p.write(lineone+'\n')
p.close()

Take advantage that festival can take multiple lines of text as input.

Arcege
  • 22,536