Last active
January 17, 2018 15:21
-
-
Save wtnb75/9a77010255eab651fed765fb490f7aa3 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
か | 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