Skip to content

Instantly share code, notes, and snippets.

@wtnb75
Last active January 17, 2018 15:21
Show Gist options
  • Save wtnb75/9a77010255eab651fed765fb490f7aa3 to your computer and use it in GitHub Desktop.
Save wtnb75/9a77010255eab651fed765fb490f7aa3 to your computer and use it in GitHub Desktop.
import os
import sys
import tempfile
import subprocess
import csv
class singer:
VOICE = "Kyoko"
pitchmap = {
'c': 0,
'c+': 1,
'd-': 1,
'd': 2,
'd+': 3,
'e-': 3,
'e': 4,
'f': 5,
'f+': 6,
'g-': 6,
'g': 7,
'g+': 8,
'a-': 8,
'a': 9,
'a+': 10,
'b-': 10,
'b': 11,
}
def __init__(self):
pass
def getpitch(self, afile):
wav = tempfile.NamedTemporaryFile(suffix=".wav")
res = subprocess.run(["sox", afile, wav.name])
assert res.returncode == 0
res = subprocess.run(["reaper", "-i", wav.name], stdout=subprocess.PIPE)
assert res.returncode == 0
for i in res.stdout.decode("utf-8").split():
if i.startswith("P:"):
return float(i.split(":")[1])
assert False
def say(self, word, levelname, outfn=None):
if levelname in self.pitchmap:
level = self.pitchmap[levelname]
else:
level = int(levelname)
fname = tempfile.NamedTemporaryFile(suffix=".aiff")
res1 = subprocess.run(["say", "-v", self.VOICE, "-o", fname.name, word])
assert res1.returncode == 0
pitch = self.getpitch(fname.name)
pitchdiff = int((level * 100) - pitch)
print("pitch", pitch, level, pitchdiff)
if outfn:
res2 = subprocess.run(["sox", "-q", fname.name,
"-t", "aiff", outfn, "pitch", str(pitchdiff)])
else:
res2 = subprocess.run(["play", "-q", fname.name,
"pitch", str(pitchdiff)])
assert res2.returncode == 0
del fname
def sing(self, seq, outfn=None):
if outfn:
n = 0
tmpd = tempfile.TemporaryDirectory()
for word, level in seq:
self.say(word, level, os.path.join(tmpd.name, "%d.aiff" % (n)))
n += 1
arg = ["sox", "-q"]
arg.extend([os.path.join(tmpd.name, "%d.aiff" % (i)) for i in range(n)])
arg.append(outfn)
res = subprocess.run(arg)
else:
for word, level in seq:
self.say(word, level)
if __name__ == "__main__":
s = singer()
rd = csv.reader(sys.stdin)
s.sing(rd, "out.aiff")
c
d
e
f
e
d
c
e
f
g
a
g
f
e
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment