mirror of
https://github.com/HIllya51/LunaTranslator.git
synced 2024-12-29 00:24:13 +08:00
update
This commit is contained in:
parent
220e6e3051
commit
eb2bcd360f
@ -79,7 +79,7 @@ class TabWidget(QWidget):
|
|||||||
|
|
||||||
class Settin(closeashidewindow):
|
class Settin(closeashidewindow):
|
||||||
voicelistsignal = pyqtSignal(list, int)
|
voicelistsignal = pyqtSignal(list, int)
|
||||||
mp3playsignal = pyqtSignal(str, int, bool)
|
mp3playsignal = pyqtSignal(bytes, int, bool)
|
||||||
versiontextsignal = pyqtSignal(str)
|
versiontextsignal = pyqtSignal(str)
|
||||||
progresssignal = pyqtSignal(str, int)
|
progresssignal = pyqtSignal(str, int)
|
||||||
fontbigsmallsignal = pyqtSignal(int)
|
fontbigsmallsignal = pyqtSignal(int)
|
||||||
|
@ -37,6 +37,7 @@ def getttsgrid(self):
|
|||||||
continue
|
continue
|
||||||
if "args" in globalconfig["reader"][name]:
|
if "args" in globalconfig["reader"][name]:
|
||||||
items = autoinitdialog_items(globalconfig["reader"][name])
|
items = autoinitdialog_items(globalconfig["reader"][name])
|
||||||
|
items[-1]["callback"] = gobject.baseobject.startreader
|
||||||
_3 = getcolorbutton(
|
_3 = getcolorbutton(
|
||||||
globalconfig,
|
globalconfig,
|
||||||
"",
|
"",
|
||||||
|
@ -12,7 +12,7 @@ from PyQt5.QtWidgets import (
|
|||||||
QTabWidget,
|
QTabWidget,
|
||||||
QFileDialog,
|
QFileDialog,
|
||||||
QTabBar,
|
QTabBar,
|
||||||
QLabel
|
QLabel,
|
||||||
)
|
)
|
||||||
from PyQt5.QtGui import QPixmap, QImage
|
from PyQt5.QtGui import QPixmap, QImage
|
||||||
from traceback import print_exc
|
from traceback import print_exc
|
||||||
@ -31,7 +31,7 @@ from gui.usefulwidget import (
|
|||||||
getlineedit,
|
getlineedit,
|
||||||
getsimpleswitch,
|
getsimpleswitch,
|
||||||
getcolorbutton,
|
getcolorbutton,
|
||||||
tabadd_lazy
|
tabadd_lazy,
|
||||||
)
|
)
|
||||||
from myutils.wrapper import threader
|
from myutils.wrapper import threader
|
||||||
from myutils.ocrutil import imageCut, ocr_run
|
from myutils.ocrutil import imageCut, ocr_run
|
||||||
@ -54,6 +54,7 @@ class ffmpeg_virtual_audio_capturer:
|
|||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
print_exc()
|
print_exc()
|
||||||
|
|
||||||
def end(self):
|
def end(self):
|
||||||
try:
|
try:
|
||||||
self.engine.stdin.write(b"q")
|
self.engine.stdin.write(b"q")
|
||||||
@ -94,16 +95,24 @@ class AnkiWindow(QWidget):
|
|||||||
__ocrsettext = pyqtSignal(str)
|
__ocrsettext = pyqtSignal(str)
|
||||||
refreshhtml = pyqtSignal()
|
refreshhtml = pyqtSignal()
|
||||||
|
|
||||||
|
def callbacktts(self, edit, data):
|
||||||
|
fname = "./cache/tts/" + str(uuid.uuid4()) + ".mp3"
|
||||||
|
os.makedirs("./cache/tts", exist_ok=True)
|
||||||
|
with open(fname, "wb") as ff:
|
||||||
|
ff.write(data)
|
||||||
|
edit.setText(os.path.abspath(fname))
|
||||||
|
|
||||||
def langdu(self):
|
def langdu(self):
|
||||||
if gobject.baseobject.reader:
|
if gobject.baseobject.reader:
|
||||||
gobject.baseobject.reader.ttscallback(
|
gobject.baseobject.reader.ttscallback(
|
||||||
self.currentword, self.audiopath.setText
|
self.currentword, functools.partial(self.callbacktts, self.audiopath)
|
||||||
)
|
)
|
||||||
|
|
||||||
def langdu2(self):
|
def langdu2(self):
|
||||||
if gobject.baseobject.reader:
|
if gobject.baseobject.reader:
|
||||||
gobject.baseobject.reader.ttscallback(
|
gobject.baseobject.reader.ttscallback(
|
||||||
self.example.toPlainText(), self.audiopath_sentence.setText
|
self.example.toPlainText(),
|
||||||
|
functools.partial(self.callbacktts, self.audiopath_sentence),
|
||||||
)
|
)
|
||||||
|
|
||||||
@threader
|
@threader
|
||||||
|
@ -115,8 +115,8 @@ class BorderedLabel(ShadowLabel):
|
|||||||
self._type = _type
|
self._type = _type
|
||||||
|
|
||||||
def move(self, point: QPoint):
|
def move(self, point: QPoint):
|
||||||
point.setX(point.x() - self.m_fontOutLineWidth)
|
point.setX(int(point.x() - self.m_fontOutLineWidth))
|
||||||
point.setY(point.y() - self.m_fontOutLineWidth)
|
point.setY(int(point.y() - self.m_fontOutLineWidth))
|
||||||
super().move(point)
|
super().move(point)
|
||||||
|
|
||||||
def adjustSize(self):
|
def adjustSize(self):
|
||||||
@ -124,8 +124,8 @@ class BorderedLabel(ShadowLabel):
|
|||||||
text = self._m_text
|
text = self._m_text
|
||||||
font_m = QFontMetrics(font)
|
font_m = QFontMetrics(font)
|
||||||
self.resize(
|
self.resize(
|
||||||
font_m.width(text) + 2 * self.m_fontOutLineWidth,
|
int(font_m.width(text) + 2 * self.m_fontOutLineWidth),
|
||||||
font_m.height() + 2 * self.m_fontOutLineWidth,
|
int(font_m.height() + 2 * self.m_fontOutLineWidth),
|
||||||
)
|
)
|
||||||
|
|
||||||
def paintEvent(self, event):
|
def paintEvent(self, event):
|
||||||
|
@ -11,6 +11,9 @@ import time
|
|||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QApplication,
|
QApplication,
|
||||||
)
|
)
|
||||||
|
from PyQt5.QtCore import QIODevice, QBuffer
|
||||||
|
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
|
||||||
|
|
||||||
from traceback import print_exc
|
from traceback import print_exc
|
||||||
from myutils.config import (
|
from myutils.config import (
|
||||||
globalconfig,
|
globalconfig,
|
||||||
@ -235,75 +238,38 @@ def argsort(l):
|
|||||||
|
|
||||||
|
|
||||||
class wavmp3player:
|
class wavmp3player:
|
||||||
|
def changepos(self, pos):
|
||||||
|
if pos != 0 and pos == self.player.duration():
|
||||||
|
if self.next:
|
||||||
|
content, volume = self.next
|
||||||
|
self.next = None
|
||||||
|
self.realplay(content, volume)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.i = 0
|
self.player = QMediaPlayer()
|
||||||
self.lastfile = None
|
self.player.positionChanged.connect(self.changepos)
|
||||||
self.tasks = None
|
self.next = None
|
||||||
self.lock = threading.Lock()
|
|
||||||
self.lock.acquire()
|
|
||||||
threading.Thread(target=self.dotasks).start()
|
|
||||||
|
|
||||||
def mp3playfunction(self, path, volume, force):
|
def realplay(self, content, volume):
|
||||||
try:
|
self.player.stop()
|
||||||
self.tasks = (path, volume, force)
|
self.keepbuffer = []
|
||||||
self.lock.release()
|
buffer = QBuffer()
|
||||||
except:
|
buffer.open(QIODevice.ReadWrite)
|
||||||
pass
|
self.player.setMedia(QMediaContent(), buffer)
|
||||||
|
self.player.setVolume(volume)
|
||||||
|
buffer.write(content)
|
||||||
|
self.keepbuffer = [buffer]
|
||||||
|
self.player.play()
|
||||||
|
|
||||||
def dotasks(self):
|
def mp3playfunction(self, content, volume, force):
|
||||||
durationms = 0
|
if (
|
||||||
try:
|
globalconfig["ttsnointerrupt"]
|
||||||
while True:
|
and self.player.position() < self.player.duration()
|
||||||
self.lock.acquire()
|
and not force
|
||||||
task = self.tasks
|
):
|
||||||
self.tasks = None
|
self.next = [content, volume]
|
||||||
if task is None:
|
else:
|
||||||
continue
|
self.realplay(content, volume)
|
||||||
path, volume, force = task
|
|
||||||
|
|
||||||
if os.path.exists(path) == False:
|
|
||||||
continue
|
|
||||||
durationms = self._playsoundWin(path, volume)
|
|
||||||
|
|
||||||
if durationms and globalconfig["ttsnointerrupt"]:
|
|
||||||
while durationms > 0:
|
|
||||||
durationms -= 100
|
|
||||||
time.sleep(0.1)
|
|
||||||
if self.tasks and self.tasks[-1]:
|
|
||||||
break
|
|
||||||
# time.sleep(durationms / 1000)
|
|
||||||
except:
|
|
||||||
print_exc()
|
|
||||||
|
|
||||||
def _playsoundWin(self, sound, volume):
|
|
||||||
try:
|
|
||||||
|
|
||||||
windows.mciSendString(("stop lunatranslator_mci_{}".format(self.i)))
|
|
||||||
windows.mciSendString(("close lunatranslator_mci_{}".format(self.i)))
|
|
||||||
self.i += 1
|
|
||||||
if self.lastfile:
|
|
||||||
os.remove(self.lastfile)
|
|
||||||
self.lastfile = sound
|
|
||||||
windows.mciSendString(
|
|
||||||
'open "{}" type mpegvideo alias lunatranslator_mci_{}'.format(
|
|
||||||
sound, self.i
|
|
||||||
)
|
|
||||||
)
|
|
||||||
durationms = int(
|
|
||||||
windows.mciSendString(
|
|
||||||
"status lunatranslator_mci_{} length".format(self.i)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
windows.mciSendString(
|
|
||||||
"setaudio lunatranslator_mci_{} volume to {}".format(
|
|
||||||
self.i, volume * 10
|
|
||||||
)
|
|
||||||
)
|
|
||||||
windows.mciSendString(("play lunatranslator_mci_{}".format(self.i)))
|
|
||||||
except:
|
|
||||||
durationms = 0
|
|
||||||
|
|
||||||
return durationms
|
|
||||||
|
|
||||||
|
|
||||||
def selectdebugfile(path):
|
def selectdebugfile(path):
|
||||||
|
@ -84,4 +84,8 @@ class TTS(TTSbase):
|
|||||||
windows.WriteFile(self.hPipe, bytes(buf))
|
windows.WriteFile(self.hPipe, bytes(buf))
|
||||||
fname = windows.ReadFile(self.hPipe, 1024).decode("utf-16-le")
|
fname = windows.ReadFile(self.hPipe, 1024).decode("utf-16-le")
|
||||||
if os.path.exists(fname):
|
if os.path.exists(fname):
|
||||||
return fname
|
with open("./cache/tts/" + fname + ".wav", "rb") as ff:
|
||||||
|
data = ff.read()
|
||||||
|
os.remove("./cache/tts/" + fname + ".wav")
|
||||||
|
return data
|
||||||
|
return None
|
||||||
|
@ -3,6 +3,7 @@ import threading, os, functools
|
|||||||
from myutils.wrapper import threader
|
from myutils.wrapper import threader
|
||||||
from traceback import print_exc
|
from traceback import print_exc
|
||||||
|
|
||||||
|
|
||||||
class TTSbase:
|
class TTSbase:
|
||||||
def init(self):
|
def init(self):
|
||||||
pass
|
pass
|
||||||
@ -60,11 +61,12 @@ class TTSbase:
|
|||||||
threading.Thread(target=_).start()
|
threading.Thread(target=_).start()
|
||||||
|
|
||||||
def read(self, content, force=False):
|
def read(self, content, force=False):
|
||||||
def _(force, fname):
|
volume = self.publicconfig["volume"]
|
||||||
volume = self.publicconfig["volume"]
|
|
||||||
self.mp3playsignal.emit(fname, volume, force)
|
|
||||||
|
|
||||||
self.ttscallback(content, functools.partial(_, force))
|
def _(force, volume, data):
|
||||||
|
self.mp3playsignal.emit(data, volume, force)
|
||||||
|
|
||||||
|
self.ttscallback(content, functools.partial(_, force, volume))
|
||||||
|
|
||||||
@threader
|
@threader
|
||||||
def ttscallback(self, content, callback):
|
def ttscallback(self, content, callback):
|
||||||
@ -74,14 +76,13 @@ class TTSbase:
|
|||||||
return
|
return
|
||||||
if len(self.voicelist) == 0:
|
if len(self.voicelist) == 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
rate = self.publicconfig["rate"]
|
rate = self.publicconfig["rate"]
|
||||||
voice = self.privateconfig["voice"]
|
voice = self.privateconfig["voice"]
|
||||||
voice_index = self.voicelist.index(voice)
|
voice_index = self.voicelist.index(voice)
|
||||||
try:
|
try:
|
||||||
fname = self.speak(content, rate, voice, voice_index)
|
data = self.speak(content, rate, voice, voice_index)
|
||||||
if fname:
|
if data and len(data):
|
||||||
callback(os.path.abspath(fname))
|
callback(data)
|
||||||
except:
|
except:
|
||||||
print_exc()
|
print_exc()
|
||||||
return
|
return
|
||||||
|
@ -193,8 +193,4 @@ def transferMsTTSData(rate, content, voice):
|
|||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
ws.close()
|
ws.close()
|
||||||
os.makedirs("./cache/tts/", exist_ok=True)
|
return audio_stream
|
||||||
outputPath = "./cache/tts/" + str(time.time()) + ".mp3"
|
|
||||||
with open(outputPath, "wb") as audio_out:
|
|
||||||
audio_out.write(audio_stream)
|
|
||||||
return outputPath
|
|
||||||
|
@ -325,6 +325,7 @@ import re
|
|||||||
|
|
||||||
_ALL_PUNC_OR_SPACE = re.compile("^[{}]*$".format(re.escape(punc + ws)))
|
_ALL_PUNC_OR_SPACE = re.compile("^[{}]*$".format(re.escape(punc + ws)))
|
||||||
|
|
||||||
|
|
||||||
def _minimize(the_string, delim, max_size):
|
def _minimize(the_string, delim, max_size):
|
||||||
if the_string.startswith(delim):
|
if the_string.startswith(delim):
|
||||||
the_string = the_string[len(delim) :]
|
the_string = the_string[len(delim) :]
|
||||||
@ -543,11 +544,11 @@ class gTTS:
|
|||||||
"'fp' is not a file-like object or it does not take bytes: %s" % str(e)
|
"'fp' is not a file-like object or it does not take bytes: %s" % str(e)
|
||||||
)
|
)
|
||||||
|
|
||||||
def save(self, savefile):
|
def save(self):
|
||||||
with open(str(savefile), "wb") as f:
|
bs = b""
|
||||||
self.write_to_fp(f)
|
for idx, decoded in enumerate(self.stream()):
|
||||||
f.flush()
|
bs += decoded
|
||||||
log.debug("Saved to %s", savefile)
|
return bs
|
||||||
|
|
||||||
|
|
||||||
class gTTSError(Exception):
|
class gTTSError(Exception):
|
||||||
@ -605,8 +606,4 @@ class TTS(TTSbase):
|
|||||||
|
|
||||||
def speak(self, content, rate, voice, voiceidx):
|
def speak(self, content, rate, voice, voiceidx):
|
||||||
tts = gTTS(content, lang=getlangsrc())
|
tts = gTTS(content, lang=getlangsrc())
|
||||||
fname = str(time.time())
|
return tts.save()
|
||||||
os.makedirs("./cache/tts/", exist_ok=True)
|
|
||||||
|
|
||||||
tts.save("./cache/tts/" + fname + ".mp3")
|
|
||||||
return "./cache/tts/" + fname + ".mp3"
|
|
||||||
|
@ -45,10 +45,6 @@ class TTS(TTSbase):
|
|||||||
json=json_data,
|
json=json_data,
|
||||||
proxies={"http": None, "https": None},
|
proxies={"http": None, "https": None},
|
||||||
)
|
)
|
||||||
fname = str(time.time())
|
|
||||||
b64 = base64.b64decode(response.json()["audio"]["data"])
|
b64 = base64.b64decode(response.json()["audio"]["data"])
|
||||||
os.makedirs("./cache/tts/", exist_ok=True)
|
|
||||||
with open("./cache/tts/" + fname + ".mp3", "wb") as ff:
|
|
||||||
ff.write(b64)
|
|
||||||
|
|
||||||
return "./cache/tts/" + fname + ".mp3"
|
return b64
|
||||||
|
@ -30,9 +30,5 @@ class TTS(TTSbase):
|
|||||||
response = requests.get(
|
response = requests.get(
|
||||||
f"http://127.0.0.1:{self.config['Port']}/voice/{model}?text={encoded_content}&id={idx}&lang=auto&prompt_lang=auto&format=wav&preset={self.config['preset']}"
|
f"http://127.0.0.1:{self.config['Port']}/voice/{model}?text={encoded_content}&id={idx}&lang=auto&prompt_lang=auto&format=wav&preset={self.config['preset']}"
|
||||||
).content
|
).content
|
||||||
fname = str(time.time())
|
|
||||||
os.makedirs("./cache/tts/", exist_ok=True)
|
|
||||||
with open("./cache/tts/" + fname + ".wav", "wb") as ff:
|
|
||||||
ff.write(response)
|
|
||||||
|
|
||||||
return "./cache/tts/" + fname + ".wav"
|
return response
|
||||||
|
@ -2,19 +2,18 @@ import time
|
|||||||
import os
|
import os
|
||||||
import windows
|
import windows
|
||||||
from tts.basettsclass import TTSbase
|
from tts.basettsclass import TTSbase
|
||||||
|
from ctypes import cast, POINTER, c_char, c_int32
|
||||||
from myutils.subproc import subproc_w, autoproc
|
from myutils.subproc import subproc_w, autoproc
|
||||||
|
import threading
|
||||||
|
|
||||||
|
|
||||||
class TTS(TTSbase):
|
class TTS(TTSbase):
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
self.path = ""
|
self.status = None
|
||||||
self.voice = ""
|
|
||||||
self.rate = ""
|
|
||||||
|
|
||||||
self.voicelist = self.getvoicelist()
|
self.voicelist = self.getvoicelist()
|
||||||
self.checkpath()
|
threading.Thread(target=self.checkpath).start()
|
||||||
|
|
||||||
def getvoicelist(self):
|
def getvoicelist(self):
|
||||||
voicelist = []
|
voicelist = []
|
||||||
@ -26,7 +25,7 @@ class TTS(TTSbase):
|
|||||||
if "_" in _:
|
if "_" in _:
|
||||||
_l = _.split("_")
|
_l = _.split("_")
|
||||||
if len(_l) >= 2:
|
if len(_l) >= 2:
|
||||||
if _l[-1] == "44":
|
if _l[-1] == "44" or _l[-1] == "22":
|
||||||
voicelist.append(_)
|
voicelist.append(_)
|
||||||
return voicelist
|
return voicelist
|
||||||
|
|
||||||
@ -63,25 +62,19 @@ class TTS(TTSbase):
|
|||||||
if os.path.exists(self.config["path"]) == False:
|
if os.path.exists(self.config["path"]) == False:
|
||||||
return False
|
return False
|
||||||
if (
|
if (
|
||||||
self.config["path"] != self.path
|
self.config["path"],
|
||||||
or self.privateconfig["voice"] != self.voice
|
self.privateconfig["voice"],
|
||||||
or self.publicconfig["rate"] != self.rate
|
self.publicconfig["rate"],
|
||||||
):
|
) != self.status:
|
||||||
self.path = self.config["path"]
|
dllpath = os.path.join(self.config["path"], "aitalked.dll")
|
||||||
self.rate = self.publicconfig["rate"]
|
|
||||||
self.voice = self.privateconfig["voice"]
|
|
||||||
fname = str(time.time())
|
|
||||||
os.makedirs("./cache/tts/", exist_ok=True)
|
|
||||||
savepath = os.path.join(os.getcwd(), "cache/tts", fname + ".wav")
|
|
||||||
dllpath = os.path.join(self.path, "aitalked.dll")
|
|
||||||
##dllpath=r'C:\Users\wcy\Downloads\zunko\aitalked.dll'
|
##dllpath=r'C:\Users\wcy\Downloads\zunko\aitalked.dll'
|
||||||
exepath = os.path.join(os.getcwd(), "files/plugins/shareddllproxy32.exe")
|
exepath = os.path.join(os.getcwd(), "files/plugins/shareddllproxy32.exe")
|
||||||
self.savepath = savepath
|
|
||||||
|
|
||||||
t = time.time()
|
t = time.time()
|
||||||
t = str(t)
|
t = str(t)
|
||||||
pipename = "\\\\.\\Pipe\\voiceroid2_" + t
|
pipename = "\\\\.\\Pipe\\voiceroid2_" + t
|
||||||
waitsignal = "voiceroid2waitload_" + t
|
waitsignal = "voiceroid2waitload_" + t
|
||||||
|
mapname = "voiceroid2filemap" + t
|
||||||
|
|
||||||
def linear_map(x):
|
def linear_map(x):
|
||||||
if x >= 0:
|
if x >= 0:
|
||||||
@ -90,22 +83,29 @@ class TTS(TTSbase):
|
|||||||
x = 0.05 * x + 1.0
|
x = 0.05 * x + 1.0
|
||||||
return x
|
return x
|
||||||
|
|
||||||
|
"".endswith
|
||||||
|
if self.privateconfig["voice"].endswith("_44"):
|
||||||
|
_1 = 44100
|
||||||
|
_2 = linear_map(self.publicconfig["rate"])
|
||||||
|
elif self.privateconfig["voice"].endswith("_22"):
|
||||||
|
_1 = 22050
|
||||||
|
_2 = 0
|
||||||
self.engine = autoproc(
|
self.engine = autoproc(
|
||||||
subproc_w(
|
subproc_w(
|
||||||
'"{}" voiceroid2 "{}" "{}" {} 44100 {} "{}" {} {}'.format(
|
'"{}" voiceroid2 "{}" "{}" {} {} {} {} {} {}'.format(
|
||||||
exepath,
|
exepath,
|
||||||
self.config["path"],
|
self.config["path"],
|
||||||
dllpath,
|
dllpath,
|
||||||
self.privateconfig["voice"],
|
self.privateconfig["voice"],
|
||||||
linear_map(self.publicconfig["rate"]),
|
_1,
|
||||||
savepath,
|
_2,
|
||||||
pipename,
|
pipename,
|
||||||
waitsignal,
|
waitsignal,
|
||||||
|
mapname,
|
||||||
),
|
),
|
||||||
name="voicevoid2",
|
name="voicevoid2",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
windows.WaitForSingleObject(
|
windows.WaitForSingleObject(
|
||||||
windows.AutoHandle(windows.CreateEvent(False, False, waitsignal)),
|
windows.AutoHandle(windows.CreateEvent(False, False, waitsignal)),
|
||||||
windows.INFINITE,
|
windows.INFINITE,
|
||||||
@ -122,20 +122,35 @@ class TTS(TTSbase):
|
|||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
self.mappedFile2 = windows.AutoHandle(
|
||||||
|
windows.OpenFileMapping(
|
||||||
|
windows.FILE_MAP_READ | windows.FILE_MAP_WRITE, False, mapname
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.mem = windows.MapViewOfFile(
|
||||||
|
self.mappedFile2,
|
||||||
|
windows.FILE_MAP_READ | windows.FILE_MAP_WRITE,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1024 * 1024 * 10,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.status = (
|
||||||
|
self.config["path"],
|
||||||
|
self.privateconfig["voice"],
|
||||||
|
self.publicconfig["rate"],
|
||||||
|
)
|
||||||
|
|
||||||
def speak(self, content, rate, voice, voice_idx):
|
def speak(self, content, rate, voice, voice_idx):
|
||||||
self.checkpath()
|
self.checkpath()
|
||||||
# def _():
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
content.encode("shift-jis")
|
code1 = content.encode("shift-jis")
|
||||||
except:
|
except:
|
||||||
return
|
return
|
||||||
code1 = content.encode("shift-jis")
|
|
||||||
# print(code1)
|
|
||||||
windows.WriteFile(self.hPipe, code1)
|
windows.WriteFile(self.hPipe, code1)
|
||||||
|
|
||||||
fname = windows.ReadFile(self.hPipe, 1024).decode("utf8")
|
size = c_int32.from_buffer_copy(windows.ReadFile(self.hPipe, 4)).value
|
||||||
if os.path.exists(fname):
|
if size == 0:
|
||||||
return fname
|
return None
|
||||||
|
return cast(self.mem, POINTER(c_char))[:size]
|
||||||
|
@ -1,130 +0,0 @@
|
|||||||
import time
|
|
||||||
import os
|
|
||||||
import windows
|
|
||||||
from tts.basettsclass import TTSbase
|
|
||||||
|
|
||||||
from myutils.subproc import subproc_w, autoproc
|
|
||||||
|
|
||||||
|
|
||||||
class TTS(TTSbase):
|
|
||||||
|
|
||||||
def init(self):
|
|
||||||
self.path = ""
|
|
||||||
self.voice = ""
|
|
||||||
self.rate = ""
|
|
||||||
|
|
||||||
self.voicelist = self.getvoicelist()
|
|
||||||
def voiceshowmap(self, voice):
|
|
||||||
name = voice.split("_")[0]
|
|
||||||
jpname = {
|
|
||||||
"yukari": "結月ゆかり",
|
|
||||||
"akari": "紲星あかり",
|
|
||||||
"kiritan": "東北きりたん",
|
|
||||||
"itako": "東北イタコ",
|
|
||||||
"zunko": "東北ずん子",
|
|
||||||
"yuzuru": "伊織弓鶴",
|
|
||||||
"tsuina": "ついなちゃん",
|
|
||||||
"akane": "琴葉茜",
|
|
||||||
"aoi": "琴葉葵",
|
|
||||||
"kou": "水奈瀬コウ",
|
|
||||||
"sora": "桜乃そら",
|
|
||||||
"tamiyasu": "民安ともえ",
|
|
||||||
"ai": "月読アイ",
|
|
||||||
"shouta": "月読ショウタ",
|
|
||||||
"seika": "京町セイカ",
|
|
||||||
"una": "音街ウナ",
|
|
||||||
"yoshidakun": "鷹の爪吉田",
|
|
||||||
"galaco": "ギャラ子",
|
|
||||||
}
|
|
||||||
vv = jpname[name]
|
|
||||||
if "west" in voice:
|
|
||||||
vv += "(関西弁)"
|
|
||||||
return vv
|
|
||||||
|
|
||||||
def getvoicelist(self):
|
|
||||||
voicelist = []
|
|
||||||
if os.path.exists(self.config["path"]) == False:
|
|
||||||
return []
|
|
||||||
l = os.listdir(os.path.join(self.config["path"], "Voice"))
|
|
||||||
|
|
||||||
for _ in l:
|
|
||||||
if "_" in _:
|
|
||||||
_l = _.split("_")
|
|
||||||
if len(_l) >= 2:
|
|
||||||
if _l[-1] == "22":
|
|
||||||
voicelist.append(_)
|
|
||||||
return voicelist
|
|
||||||
|
|
||||||
def checkpath(self):
|
|
||||||
if self.config["path"] == "":
|
|
||||||
return False
|
|
||||||
if os.path.exists(self.config["path"]) == False:
|
|
||||||
return False
|
|
||||||
if (
|
|
||||||
self.config["path"] != self.path
|
|
||||||
or self.privateconfig["voice"] != self.voice
|
|
||||||
or self.publicconfig["rate"] != self.rate
|
|
||||||
):
|
|
||||||
self.path = self.config["path"]
|
|
||||||
self.rate = self.publicconfig["rate"]
|
|
||||||
self.voice = self.privateconfig["voice"]
|
|
||||||
fname = str(time.time())
|
|
||||||
os.makedirs("./cache/tts/", exist_ok=True)
|
|
||||||
savepath = os.path.join(os.getcwd(), "cache/tts", fname + ".wav")
|
|
||||||
dllpath = os.path.join(self.path, "aitalked.dll")
|
|
||||||
|
|
||||||
exepath = os.path.join(os.getcwd(), "files/plugins/shareddllproxy32.exe")
|
|
||||||
self.savepath = savepath
|
|
||||||
|
|
||||||
t = time.time()
|
|
||||||
t = str(t)
|
|
||||||
pipename = "\\\\.\\Pipe\\voiceroid2_" + t
|
|
||||||
waitsignal = "voiceroid2waitload_" + t
|
|
||||||
# 速率不可调
|
|
||||||
self.engine = autoproc(
|
|
||||||
subproc_w(
|
|
||||||
'"{}" voiceroid2 "{}" "{}" {} 22050 0 "{}" {} {}'.format(
|
|
||||||
exepath,
|
|
||||||
self.config["path"],
|
|
||||||
dllpath,
|
|
||||||
self.privateconfig["voice"],
|
|
||||||
savepath,
|
|
||||||
pipename,
|
|
||||||
waitsignal,
|
|
||||||
),
|
|
||||||
name="voicevoid2",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
windows.WaitForSingleObject(
|
|
||||||
windows.AutoHandle(windows.CreateEvent(False, False, waitsignal)),
|
|
||||||
windows.INFINITE,
|
|
||||||
)
|
|
||||||
windows.WaitNamedPipe(pipename, windows.NMPWAIT_WAIT_FOREVER)
|
|
||||||
self.hPipe = windows.AutoHandle(
|
|
||||||
windows.CreateFile(
|
|
||||||
pipename,
|
|
||||||
windows.GENERIC_READ | windows.GENERIC_WRITE,
|
|
||||||
0,
|
|
||||||
None,
|
|
||||||
windows.OPEN_EXISTING,
|
|
||||||
windows.FILE_ATTRIBUTE_NORMAL,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def speak(self, content, rate, voice, voice_idx):
|
|
||||||
self.checkpath()
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
content.encode("shift-jis")
|
|
||||||
except:
|
|
||||||
return
|
|
||||||
code1 = content.encode("shift-jis")
|
|
||||||
# print(code1)
|
|
||||||
windows.WriteFile(self.hPipe, code1)
|
|
||||||
|
|
||||||
fname = windows.ReadFile(self.hPipe, 1024).decode("utf8")
|
|
||||||
if os.path.exists(fname):
|
|
||||||
return fname
|
|
@ -100,7 +100,4 @@ class TTS(TTSbase):
|
|||||||
headers=headers,
|
headers=headers,
|
||||||
data=json.dumps(response.json()),
|
data=json.dumps(response.json()),
|
||||||
)
|
)
|
||||||
os.makedirs("./cache/tts/", exist_ok=True)
|
return response.content
|
||||||
with open("./cache/tts/" + fname + ".wav", "wb") as ff:
|
|
||||||
ff.write(response.content)
|
|
||||||
return "./cache/tts/" + fname + ".wav"
|
|
@ -40,4 +40,7 @@ class TTS(TTSbase):
|
|||||||
winsharedutils.SAPI_Speak(
|
winsharedutils.SAPI_Speak(
|
||||||
content, version, voice_idx, rate, 100, "./cache/tts/" + fname + ".wav"
|
content, version, voice_idx, rate, 100, "./cache/tts/" + fname + ".wav"
|
||||||
)
|
)
|
||||||
return "./cache/tts/" + fname + ".wav"
|
with open("./cache/tts/" + fname + ".wav", "rb") as ff:
|
||||||
|
data = ff.read()
|
||||||
|
os.remove("./cache/tts/" + fname + ".wav")
|
||||||
|
return data
|
||||||
|
@ -38,9 +38,4 @@ class TTS(TTSbase):
|
|||||||
headers=headers,
|
headers=headers,
|
||||||
proxies={"http": None, "https": None},
|
proxies={"http": None, "https": None},
|
||||||
).content
|
).content
|
||||||
fname = str(time.time())
|
return response
|
||||||
os.makedirs("./cache/tts/", exist_ok=True)
|
|
||||||
with open("./cache/tts/" + fname + ".mp3", "wb") as ff:
|
|
||||||
ff.write(response)
|
|
||||||
|
|
||||||
return "./cache/tts/" + fname + ".mp3"
|
|
||||||
|
@ -970,3 +970,25 @@ _LoadLibraryW.argtypes = (LPCWSTR,)
|
|||||||
|
|
||||||
def loadlibrary(path):
|
def loadlibrary(path):
|
||||||
_LoadLibraryW(path)
|
_LoadLibraryW(path)
|
||||||
|
|
||||||
|
|
||||||
|
SECTION_MAP_WRITE = 0x0002
|
||||||
|
SECTION_MAP_READ = 0x0004
|
||||||
|
FILE_MAP_WRITE = SECTION_MAP_WRITE
|
||||||
|
FILE_MAP_READ = SECTION_MAP_READ
|
||||||
|
_OpenFileMapping = _kernel32.OpenFileMappingW
|
||||||
|
_OpenFileMapping.argtypes = DWORD, BOOL, LPCWSTR
|
||||||
|
_OpenFileMapping.restype = HANDLE
|
||||||
|
|
||||||
|
|
||||||
|
def OpenFileMapping(acc, inher, name):
|
||||||
|
return _OpenFileMapping(acc, inher, name)
|
||||||
|
|
||||||
|
|
||||||
|
_MapViewOfFile = _kernel32.MapViewOfFile
|
||||||
|
_MapViewOfFile.argtypes = HANDLE, DWORD, DWORD, DWORD, c_size_t
|
||||||
|
_MapViewOfFile.restype = c_void_p
|
||||||
|
|
||||||
|
|
||||||
|
def MapViewOfFile(hfmap, acc, high, low, size):
|
||||||
|
return _MapViewOfFile(hfmap, acc, high, low, size)
|
||||||
|
@ -656,22 +656,7 @@
|
|||||||
"voiceroid2": {
|
"voiceroid2": {
|
||||||
"use": false,
|
"use": false,
|
||||||
"voice": "",
|
"voice": "",
|
||||||
"name": "VoiceRoid2",
|
"name": "VoiceRoid2/VoiceRoid+",
|
||||||
"args": {
|
|
||||||
"path": ""
|
|
||||||
},
|
|
||||||
"argstype": {
|
|
||||||
"path": {
|
|
||||||
"type": "file",
|
|
||||||
"name": "路径",
|
|
||||||
"dir": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"voiceroidplus": {
|
|
||||||
"use": false,
|
|
||||||
"voice": "",
|
|
||||||
"name": "VoiceRoid+",
|
|
||||||
"args": {
|
"args": {
|
||||||
"path": ""
|
"path": ""
|
||||||
},
|
},
|
||||||
|
@ -182,6 +182,21 @@ copycheck(
|
|||||||
os.path.join(py37Path, "Lib/site-packages/PyQt5/Qt5/bin/Qt5Gui.dll"),
|
os.path.join(py37Path, "Lib/site-packages/PyQt5/Qt5/bin/Qt5Gui.dll"),
|
||||||
os.path.join(runtime, "PyQt5/Qt5/bin"),
|
os.path.join(runtime, "PyQt5/Qt5/bin"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
###
|
||||||
|
copycheck(
|
||||||
|
os.path.join(py37Path, "Lib/site-packages/PyQt5/Qt5/bin/Qt5Multimedia.dll"),
|
||||||
|
os.path.join(runtime, "PyQt5/Qt5/bin"),
|
||||||
|
)
|
||||||
|
copycheck(
|
||||||
|
os.path.join(py37Path, "Lib/site-packages/PyQt5/Qt5/bin/Qt5Network.dll"),
|
||||||
|
os.path.join(runtime, "PyQt5/Qt5/bin"),
|
||||||
|
)
|
||||||
|
copycheck(
|
||||||
|
os.path.join(py37Path, "Lib/site-packages/PyQt5/QtNetwork.pyd"),
|
||||||
|
os.path.join(runtime, "PyQt5"),
|
||||||
|
)
|
||||||
|
###
|
||||||
copycheck(
|
copycheck(
|
||||||
os.path.join(py37Path, "Lib/site-packages/PyQt5/Qt5/bin/Qt5Widgets.dll"),
|
os.path.join(py37Path, "Lib/site-packages/PyQt5/Qt5/bin/Qt5Widgets.dll"),
|
||||||
os.path.join(runtime, "PyQt5/Qt5/bin"),
|
os.path.join(runtime, "PyQt5/Qt5/bin"),
|
||||||
@ -191,6 +206,10 @@ copycheck(
|
|||||||
os.path.join(py37Path, "Lib/site-packages/PyQt5/Qt5/plugins/imageformats"),
|
os.path.join(py37Path, "Lib/site-packages/PyQt5/Qt5/plugins/imageformats"),
|
||||||
os.path.join(runtime, "PyQt5/Qt5/plugins"),
|
os.path.join(runtime, "PyQt5/Qt5/plugins"),
|
||||||
)
|
)
|
||||||
|
copycheck(
|
||||||
|
os.path.join(py37Path, "Lib/site-packages/PyQt5/Qt5/plugins/mediaservice"),
|
||||||
|
os.path.join(runtime, "PyQt5/Qt5/plugins"),
|
||||||
|
)
|
||||||
copycheck(
|
copycheck(
|
||||||
os.path.join(
|
os.path.join(
|
||||||
py37Path, "Lib/site-packages/PyQt5/Qt5/plugins/platforms/qoffscreen.dll"
|
py37Path, "Lib/site-packages/PyQt5/Qt5/plugins/platforms/qoffscreen.dll"
|
||||||
|
@ -29,7 +29,7 @@ include(generate_product_version)
|
|||||||
|
|
||||||
set(VERSION_MAJOR 2)
|
set(VERSION_MAJOR 2)
|
||||||
set(VERSION_MINOR 51)
|
set(VERSION_MINOR 51)
|
||||||
set(VERSION_PATCH 3)
|
set(VERSION_PATCH 4)
|
||||||
|
|
||||||
add_library(pch pch.cpp)
|
add_library(pch pch.cpp)
|
||||||
target_precompile_headers(pch PUBLIC pch.h)
|
target_precompile_headers(pch PUBLIC pch.h)
|
||||||
|
@ -7,42 +7,33 @@ using ebyroid::Ebyroid;
|
|||||||
|
|
||||||
int voiceroid2wmain(int argc, wchar_t *wargv[])
|
int voiceroid2wmain(int argc, wchar_t *wargv[])
|
||||||
{
|
{
|
||||||
UINT codepage = GetACP();
|
|
||||||
|
|
||||||
char **argv = new char *[argc];
|
char **argv = new char *[argc];
|
||||||
for (int i = 0; i < argc; i++)
|
for (int i = 0; i < argc; i++)
|
||||||
{
|
{
|
||||||
int length = WideCharToMultiByte(codepage, 0, wargv[i], -1, NULL, 0, NULL, NULL);
|
int length = WideCharToMultiByte(CP_ACP, 0, wargv[i], -1, NULL, 0, NULL, NULL);
|
||||||
argv[i] = new char[length];
|
argv[i] = new char[length];
|
||||||
WideCharToMultiByte(codepage, 0, wargv[i], -1, argv[i], length, NULL, NULL);
|
WideCharToMultiByte(CP_ACP, 0, wargv[i], -1, argv[i], length, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
HANDLE hPipe = CreateNamedPipeA(argv[6], PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 65535, 65535, NMPWAIT_WAIT_FOREVER, 0);
|
||||||
HANDLE hPipe = CreateNamedPipeA(argv[7], PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 65535, 65535, NMPWAIT_WAIT_FOREVER, 0);
|
|
||||||
|
|
||||||
Ebyroid *ebyroid;
|
Ebyroid *ebyroid;
|
||||||
|
|
||||||
printf("argc %d \n", argc);
|
|
||||||
for (int i = 0; i < argc; i++)
|
|
||||||
{
|
|
||||||
printf("%d %s\n", i, argv[i]);
|
|
||||||
}
|
|
||||||
ebyroid = Ebyroid::Create((const char *)argv[1], //"C:\\dataH\\Yukari2",
|
ebyroid = Ebyroid::Create((const char *)argv[1], //"C:\\dataH\\Yukari2",
|
||||||
(const char *)argv[2],
|
(const char *)argv[2],
|
||||||
(const char *)argv[3], //"yukari_emo_44",
|
(const char *)argv[3], //"yukari_emo_44",
|
||||||
2,
|
2,
|
||||||
atof((const char *)argv[5])); // 1); //0.1-2,0.5-4
|
atof((const char *)argv[5])); // 1); //0.1-2,0.5-4
|
||||||
|
|
||||||
SetEvent(CreateEventA(&allAccess, FALSE, FALSE, argv[8]));
|
auto handle = CreateFileMappingA(INVALID_HANDLE_VALUE, &allAccess, PAGE_EXECUTE_READWRITE, 0, 1024 * 1024 * 10, argv[8]);
|
||||||
if (ConnectNamedPipe(hPipe, NULL) != NULL)
|
|
||||||
{
|
auto mapview = (char *)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0, 1024 * 1024 * 10);
|
||||||
DWORD len = 0;
|
memset(mapview, 0, 1024 * 1024 * 10);
|
||||||
}
|
SetEvent(CreateEventA(&allAccess, FALSE, FALSE, argv[7]));
|
||||||
|
ConnectNamedPipe(hPipe, NULL);
|
||||||
int freq1 = atoi(argv[4]);
|
int freq1 = atoi(argv[4]);
|
||||||
printf("pipe connected");
|
|
||||||
int II = 0;
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
II += 1;
|
|
||||||
unsigned char *out;
|
unsigned char *out;
|
||||||
size_t output_size;
|
size_t output_size;
|
||||||
int16_t *out2;
|
int16_t *out2;
|
||||||
@ -52,34 +43,43 @@ int voiceroid2wmain(int argc, wchar_t *wargv[])
|
|||||||
if (!ReadFile(hPipe, input_j, 4096, &_, NULL))
|
if (!ReadFile(hPipe, input_j, 4096, &_, NULL))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
printf("%s\n", input_j);
|
|
||||||
// int result = ebyroid->Hiragana((const unsigned char*)UnicodeToShift_jis(input), &out, &output_size);
|
// int result = ebyroid->Hiragana((const unsigned char*)UnicodeToShift_jis(input), &out, &output_size);
|
||||||
int result = ebyroid->Hiragana((const unsigned char *)input_j, &out, &output_size);
|
int result = ebyroid->Hiragana((const unsigned char *)input_j, &out, &output_size);
|
||||||
|
|
||||||
printf("%s\n", out);
|
|
||||||
result = ebyroid->Speech(out, &out2, &output_size);
|
result = ebyroid->Speech(out, &out2, &output_size);
|
||||||
char newname[1024] = {0};
|
|
||||||
sprintf(newname, "%s%d.wav", argv[6], II);
|
|
||||||
FILE *F = fopen(newname, "wb");
|
|
||||||
|
|
||||||
int fsize = output_size + 44;
|
int fsize = output_size + 44;
|
||||||
fseek(F, 0, SEEK_SET);
|
if (fsize > 1024 * 1024 * 10)
|
||||||
fwrite("RIFF", 1, 4, F);
|
{
|
||||||
fwrite(&fsize, 4, 1, F);
|
fsize = 0;
|
||||||
fwrite("WAVEfmt ", 1, 8, F);
|
}
|
||||||
fwrite("\x10\x00\x00\x00\x01\x00\x01\x00", 1, 8, F);
|
else
|
||||||
int freq = freq1;
|
{
|
||||||
fwrite(&freq, 4, 1, F);
|
|
||||||
freq = freq * 2;
|
int ptr = 0;
|
||||||
fwrite(&freq, 4, 1, F);
|
memcpy(mapview, "RIFF", 4);
|
||||||
fwrite("\x02\x00\x10\x00", 1, 4, F);
|
ptr += 4;
|
||||||
fwrite("data", 1, 4, F);
|
memcpy(mapview + ptr, &fsize, 4);
|
||||||
int sz = fsize - 44;
|
ptr += 4;
|
||||||
fwrite(&sz, 4, 1, F);
|
memcpy(mapview + ptr, "WAVEfmt ", 8);
|
||||||
printf("%d \n", ftell(F));
|
ptr += 8;
|
||||||
fwrite((char *)out2, 1, output_size, F);
|
memcpy(mapview + ptr, "\x10\x00\x00\x00\x01\x00\x01\x00", 8);
|
||||||
fclose(F);
|
ptr += 8;
|
||||||
WriteFile(hPipe, newname, strlen(newname), &_, NULL);
|
int freq = freq1;
|
||||||
|
memcpy(mapview + ptr, &freq, 4);
|
||||||
|
ptr += 4;
|
||||||
|
freq = freq * 2;
|
||||||
|
memcpy(mapview + ptr, &freq, 4);
|
||||||
|
ptr += 4;
|
||||||
|
memcpy(mapview + ptr, "\x02\x00\x10\x00", 4);
|
||||||
|
ptr += 4;
|
||||||
|
memcpy(mapview + ptr, "data", 4);
|
||||||
|
ptr += 4;
|
||||||
|
memcpy(mapview + ptr, &output_size, 4);
|
||||||
|
ptr += 4;
|
||||||
|
memcpy(mapview + ptr, out2, output_size);
|
||||||
|
}
|
||||||
|
WriteFile(hPipe, &fsize, 4, &_, NULL);
|
||||||
|
|
||||||
free(out);
|
free(out);
|
||||||
free(out2);
|
free(out2);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user