This commit is contained in:
恍兮惚兮 2024-07-01 23:17:31 +08:00
parent c0064dcc84
commit 688dd4868c
24 changed files with 235 additions and 126 deletions

View File

@ -45,6 +45,7 @@ import winsharedutils
from winsharedutils import collect_running_pids
from myutils.post import POSTSOLVE
from myutils.utils import nowisdark
from myutils.audioplayer import audioplayer
class commonstylebase(QWidget):
@ -83,6 +84,7 @@ class MAINUI:
self.edittextui_sync = True
self.sqlsavegameinfo = None
self.notifyonce = set()
self.audioplayer = audioplayer()
@property
def textsource(self):
@ -473,7 +475,7 @@ class MAINUI:
self.reader_usevoice = use
self.reader = aclass(
use, self.settin_ui.voicelistsignal, self.settin_ui.mp3playsignal
use, self.settin_ui.voicelistsignal, self.audioplayer.play
)
def selectprocess(self, selectedp, title):

View File

@ -2,7 +2,6 @@ from qtsymbols import *
import functools
import qtawesome
from myutils.config import globalconfig, _TR, _TRL
from myutils.utils import wavmp3player
from gui.usefulwidget import closeashidewindow, makesubtab_lazy
from gui.setting_textinput import setTabOne_lazy
from gui.setting_translate import setTabTwo_lazy, checkconnected
@ -66,7 +65,6 @@ class TabWidget(QWidget):
class Setting(closeashidewindow):
voicelistsignal = pyqtSignal(list, int)
mp3playsignal = pyqtSignal(bytes, int, bool)
versiontextsignal = pyqtSignal(str)
progresssignal = pyqtSignal(str, int)
opensolvetextsig = pyqtSignal()
@ -75,8 +73,7 @@ class Setting(closeashidewindow):
def __init__(self, parent):
super(Setting, self).__init__(parent, globalconfig["setting_geo_2"])
self.setWindowIcon(qtawesome.icon("fa.gear"))
self.mp3player = wavmp3player()
self.mp3playsignal.connect(self.mp3player.mp3playfunction)
self.opensolvetextsig.connect(self.opensolvetextfun)
self.showandsolvesig.connect(functools.partial(delaysetcomparetext, self))
self.voicelistsignal.connect(functools.partial(showvoicelist, self))

View File

@ -1,7 +1,7 @@
from qtsymbols import *
import os, functools
import gobject
from myutils.config import globalconfig, _TRL
from myutils.config import globalconfig, _TRL, static_data
from gui.inputdialog import autoinitdialog_items, noundictconfigdialog1, autoinitdialog
from gui.usefulwidget import (
D_getsimplecombobox,
@ -127,14 +127,35 @@ def setTab5lz(self):
grid=[
[
"选择声音",
(functools.partial(createvoicecombo, self), 4),
functools.partial(createvoicecombo, self),
],
[
"语速:(-10~10)",
"语速_(-10~10)",
D_getspinbox(-10, 10, globalconfig["ttscommon"], "rate"),
],
],
),
0,
"group",
)
],
[
(
dict(
title="音频播放",
type="grid",
grid=[
[
"音量:(0~100)",
"引擎",
D_getsimplecombobox(
static_data["audioengine_vis"],
globalconfig,
"audioengine",
internallist=static_data["audioengine"],
),
],
[
"音量_(0~100)",
D_getspinbox(0, 100, globalconfig["ttscommon"], "volume"),
],
],
@ -185,7 +206,7 @@ def setTab5lz(self):
"语音修正",
D_getsimpleswitch(globalconfig["ttscommon"], "tts_repair"),
D_getIconButton(
callback=lambda : noundictconfigdialog1(
callback=lambda: noundictconfigdialog1(
self,
globalconfig["ttscommon"]["tts_repair_regex"],
"语音修正",

View File

@ -0,0 +1,131 @@
import windows
import os, time
import gobject, uuid
from traceback import print_exc
from myutils.config import globalconfig, static_data
import threading
import winsharedutils
from ctypes import c_float, pointer, c_void_p
# miniaudio似乎有的时候会莫名崩溃但我没遇到过。没办法只好恢复之前的mci了
# 但miniaudio的好处是不需要写硬盘可以直接在内存里播放mci必须写到文件里才能播放
class player_miniaudio:
def stop(self, context):
winsharedutils.PlayAudioInMem_Stop(context[0], context[1])
def play(self, binary, volume):
duration = c_float()
device = c_void_p()
decoder = c_void_p()
succ = winsharedutils.PlayAudioInMem(
binary,
len(binary),
volume / 100,
pointer(decoder),
pointer(device),
pointer(duration),
)
if succ != 0:
return 0
context = decoder, device
durationms = duration.value * 1000
return durationms, context
class player_mci:
def stop(self, context):
i, lastfile = context
windows.mciSendString(("stop lunatranslator_mci_{}".format(i)))
windows.mciSendString(("close lunatranslator_mci_{}".format(i)))
os.remove(lastfile)
def play(self, binary, volume):
tgt = gobject.gettempdir(f"tts/{time.time()}.wav")
with open(tgt, "wb") as ff:
ff.write(binary)
i = str(uuid.uuid4())
context = (i, tgt)
windows.mciSendString(
'open "{}" type mpegvideo alias lunatranslator_mci_{}'.format(tgt, i)
)
durationms = int(
windows.mciSendString("status lunatranslator_mci_{} length".format(i))
)
windows.mciSendString(
"setaudio lunatranslator_mci_{} volume to {}".format(i, volume * 10)
)
windows.mciSendString(("play lunatranslator_mci_{}".format(i)))
return durationms, context
class audioplayer:
def __init__(self):
self.i = 0
self.lastfile = None
self.tasks = None
self.lock = threading.Lock()
self.lock.acquire()
self.lastplayer = None
self.lastengine = None
self.lastcontext = None
threading.Thread(target=self.__dotasks).start()
def play(self, binary, volume, force):
try:
self.tasks = (binary, volume, force)
self.lock.release()
except:
pass
def __maybeinitengine(self):
using = globalconfig["audioengine"]
supports = static_data["audioengine"]
if using not in supports:
using = supports[0]
if using == self.lastengine:
return
self.lastplayer = {"mci": player_mci, "miniaudio": player_miniaudio}.get(
using
)()
self.lastengine = using
def __maybestoplast(self):
if self.lastplayer and self.lastcontext:
try:
self.lastplayer.stop(self.lastcontext)
except:
print_exc()
self.lastcontext = None
def __playthis(self, binary, volume):
try:
durationms, self.lastcontext = self.lastplayer.play(binary, volume)
except:
durationms = 0
self.lastcontext = None
return durationms
def __dotasks(self):
durationms = 0
try:
while True:
self.lock.acquire()
task = self.tasks
self.tasks = None
if task is None:
continue
binary, volume, force = task
self.__maybestoplast()
self.__maybeinitengine()
durationms = self.__playthis(binary, volume)
if durationms and globalconfig["ttsnointerrupt"]:
while durationms > 0:
durationms -= 100
time.sleep(0.1)
if self.tasks and self.tasks[-1]:
break
except:
print_exc()

View File

@ -1,12 +1,9 @@
import windows
import os, time
import codecs, hashlib
import os, time
import socket, gobject, uuid
import ctypes, importlib
import time
import ctypes.wintypes
import time
from qtsymbols import *
from traceback import print_exc
from myutils.config import (
@ -18,7 +15,6 @@ from myutils.config import (
findgameuidofpath,
getdefaultsavehook,
)
from ctypes import c_float, pointer, c_void_p
import threading
import re, heapq, winsharedutils
from myutils.wrapper import tryprint
@ -303,68 +299,6 @@ def argsort(l):
return ll
class wavmp3player:
def __init__(self):
self.i = 0
self.lastfile = None
self.tasks = None
self.lock = threading.Lock()
self.lock.acquire()
threading.Thread(target=self.dotasks).start()
def mp3playfunction(self, binary, volume, force):
try:
self.tasks = (binary, volume, force)
self.lock.release()
except:
pass
def dotasks(self):
durationms = 0
try:
while True:
self.lock.acquire()
task = self.tasks
self.tasks = None
if task is None:
continue
binary, volume, force = task
durationms = self._playsoundWin(binary, volume)
if durationms and globalconfig["ttsnointerrupt"]:
while durationms > 0:
durationms -= 100
time.sleep(0.1)
if self.tasks and self.tasks[-1]:
break
except:
print_exc()
def _playsoundWin(self, binary, volume):
try:
if self.lastfile:
winsharedutils.PlayAudioInMem_Stop(self.lastfile[0], self.lastfile[1])
duration = c_float()
device = c_void_p()
decoder = c_void_p()
succ = winsharedutils.PlayAudioInMem(
binary,
len(binary),
volume / 100,
pointer(decoder),
pointer(device),
pointer(duration),
)
if succ != 0:
return 0
self.lastfile = decoder, device
durationms = duration.value * 1000
except:
durationms = 0
return durationms
def selectdebugfile(path: str, ismypost=False):
if ismypost:
path = f"./userconfig/posts/{path}.py"

View File

@ -40,10 +40,10 @@ class TTSbase:
########################
def __init__(self, typename, showlistsignal, mp3playsignal) -> None:
def __init__(self, typename, showlistsignal, playaudiofunction) -> None:
self.typename = typename
self.showlistsignal = showlistsignal
self.mp3playsignal = mp3playsignal
self.playaudiofunction = playaudiofunction
self.loadok = False
def _():
@ -71,7 +71,7 @@ class TTSbase:
volume = self.publicconfig["volume"]
def _(force, volume, data):
self.mp3playsignal.emit(data, volume, force)
self.playaudiofunction(data, volume, force)
self.ttscallback(content, functools.partial(_, force, volume))

View File

@ -331,6 +331,7 @@
"buttonsize2": 18,
"language_setted_2.4.5": false,
"postprocess_rank": [],
"audioengine": "mci",
"transoptimi": {
"noundict": false,
"transerrorfix": false,

View File

@ -1755,5 +1755,13 @@
"miaobian0",
"miaobian1"
]
}
},
"audioengine": [
"mci",
"miniaudio"
],
"audioengine_vis": [
"Windows MCI",
"miniaudio"
]
}

View File

@ -154,7 +154,6 @@
"结束地址(hex)": "نهاية العنوان ( عرافة )",
"日语(CP932,SHIFT-JIS)": "اليابانية ( cp932 shift-jis , )",
"显示朗读按钮": "عرض زر القراءة",
"语速:(-10~10)": "سرعة الكلام : ( - 10-10 )",
"北欧": "نورد",
"到进程": "في عملية",
"显示/隐藏范围框": "إظهار / إخفاء مربع مجموعة",
@ -201,7 +200,6 @@
"Moji辞书": "معجم موجي",
"显示错误信息": "عرض رسالة خطأ",
"水奈瀬コウ": "شوي ناي",
"音量:(0~100)": "حجم : ( 0 ~ 100 )",
"Unicode范围": "يونيكود مجموعة",
"繁体中文(BIG5)": "الصينية التقليدية ( big5 ) .",
"编辑专有名词": "تحرير الأسماء الصحيحة",
@ -811,5 +809,8 @@
"修改列表名称": "تعديل اسم القائمة",
"滚动到最后": "انتقل إلى آخر",
"创建列表": "إنشاء قائمة",
"限制每行字数": "الحد من عدد الكلمات في السطر"
"限制每行字数": "الحد من عدد الكلمات في السطر",
"音频播放": "تشغيل الصوت",
"语速": "سرعة الكلام",
"音量": "حجم"
}

View File

@ -107,8 +107,6 @@
"语音设置": "語音設定",
"火山TTS": "火山TTS",
"选择声音": "選擇聲音",
"语速:(-10~10)": "語速:(-10~10",
"音量:(0~100)": "音量0~100",
"自动朗读": "自動朗讀",
"翻译优化": "翻譯優化",
"文本预处理": "文字預處理",
@ -811,5 +809,8 @@
"修改列表名称": "修改清單名稱",
"滚动到最后": "滾動到最後",
"创建列表": "創建清單",
"限制每行字数": "限制每行字數"
"限制每行字数": "限制每行字數",
"音频播放": "音訊播放",
"语速": "語速",
"音量": "音量"
}

View File

@ -17,7 +17,6 @@
"显示原文": "Show Original Text",
"去除重复字符(若为1则自动分析去重)": "Filter duplicate characters (Set 1 for Auto-Removal)",
"居中显示": "Center Display",
"语速:(-10~10)": "TTS Speed (-10~10):",
"百度api": "Baidu API",
"预翻译": "Pre-translation",
"专有名词翻译设置(游戏ID 0表示全局)": "Proper Noun Translation Settings (Game ID 0 means global)",
@ -94,7 +93,6 @@
"灵格斯词典": "Lingoes Dictionary",
"游戏窗口移动时同步移动": "Mone in Sync with Game Window",
"语音设置": "TTS Settings",
"音量:(0~100)": "Volume: (0~100)",
"光标缩放系数": "Cursor Scale Factor",
"前景窗口截屏": "Foreground Window Screenshot",
"3D游戏模式": "3D Game Mode",
@ -811,5 +809,8 @@
"滚动到最后": "Scroll to End",
"指定模块": "Specify modules",
"创建列表": "Create List",
"限制每行字数": "Limit the number of words per line"
"限制每行字数": "Limit the number of words per line",
"音频播放": "Audio playback",
"语速": "Speech speed",
"音量": "volume"
}

View File

@ -107,8 +107,6 @@
"语音设置": "Configuración de voz",
"火山TTS": "Volcán TTS",
"选择声音": "Seleccionar sonido",
"语速:(-10~10)": "Velocidad del habla: (- 10 a 10)",
"音量:(0~100)": "Volumen: (0 a 100)",
"自动朗读": "Lectura automática en voz alta",
"翻译优化": "Optimización de la traducción",
"文本预处理": "Preprocesamiento de texto",
@ -811,5 +809,8 @@
"修改列表名称": "Modificar el nombre de la lista",
"滚动到最后": "Rodar hasta el final",
"创建列表": "Crear lista",
"限制每行字数": "Limitar el número de palabras por línea"
"限制每行字数": "Limitar el número de palabras por línea",
"音频播放": "Reproducción de audio",
"语速": "Velocidad del habla",
"音量": "Volumen"
}

View File

@ -107,8 +107,6 @@
"语音设置": "Paramètres vocaux",
"火山TTS": "Volcan tts",
"选择声音": "Sélectionner le son",
"语速:(-10~10)": "Vitesse de la parole: (- 10 ~ 10)",
"音量:(0~100)": "Volume: (0 ~ 100)",
"自动朗读": "Lecture automatique",
"翻译优化": "Optimisation de la traduction",
"文本预处理": "Prétraitement de texte",
@ -811,5 +809,8 @@
"修改列表名称": "Modifier le nom de la Liste",
"滚动到最后": "Rouler jusqu'à la fin",
"创建列表": "Créer une liste",
"限制每行字数": "Limiter le nombre de mots par ligne"
"限制每行字数": "Limiter le nombre de mots par ligne",
"音频播放": "Lecture audio",
"语速": "Vitesse de la parole",
"音量": "Volume"
}

View File

@ -101,8 +101,6 @@
"语音设置": "Impostazioni vocali",
"火山TTS": "Vulcano TTS",
"选择声音": "Seleziona suono",
"语速:(-10~10)": "Velocità vocale: (-10-10)",
"音量:(0~100)": "Volume: (0-100)",
"自动朗读": "Lettura automatica",
"翻译优化": "Ottimizzazione della traduzione",
"文本预处理": "Preelaborazione del testo",
@ -811,5 +809,8 @@
"修改列表名称": "Modifica nome elenco",
"滚动到最后": "Scorri fino alla fine",
"创建列表": "Crea elenco",
"限制每行字数": "Limitare il numero di parole per riga"
"限制每行字数": "Limitare il numero di parole per riga",
"音频播放": "Riproduzione audio",
"语速": "Velocità vocale",
"音量": "volume"
}

View File

@ -107,8 +107,6 @@
"语音设置": "音声設定",
"火山TTS": "火山TTS",
"选择声音": "サウンドの選択",
"语速:(-10~10)": "語速:(-1010",
"音量:(0~100)": "音量0100",
"自动朗读": "自動読み上げ",
"翻译优化": "翻訳の最適化",
"文本预处理": "テキスト前処理",
@ -811,5 +809,8 @@
"修改列表名称": "リスト名の変更",
"滚动到最后": "最後までスクロール",
"创建列表": "リストの作成",
"限制每行字数": "1行あたりの文字数を制限する"
"限制每行字数": "1行あたりの文字数を制限する",
"音频播放": "オーディオ再生",
"语速": "早口",
"音量": "音量"
}

View File

@ -107,8 +107,6 @@
"语音设置": "음성 설정",
"火山TTS": "화산 TTS",
"选择声音": "사운드 선택",
"语速:(-10~10)": "언어 속도: (-10~10)",
"音量:(0~100)": "음량: (0~100)",
"自动朗读": "자동 발음",
"翻译优化": "번역 최적화",
"文本预处理": "텍스트 사전 처리",
@ -811,5 +809,8 @@
"修改列表名称": "목록 이름 수정",
"滚动到最后": "끝까지 스크롤",
"创建列表": "목록 만들기",
"限制每行字数": "행당 단어 수 제한"
"限制每行字数": "행당 단어 수 제한",
"音频播放": "오디오 재생",
"语速": "말속도",
"音量": "볼륨"
}

View File

@ -107,8 +107,6 @@
"语音设置": "Ustawienia głosu",
"火山TTS": "Wulkan TTS",
"选择声音": "Wybierz dźwięk",
"语速:(-10~10)": "Prędkość mowy: (-10-10)",
"音量:(0~100)": "Objętość: (0-100)",
"自动朗读": "Automatyczny odczyt",
"翻译优化": "Optymalizacja tłumaczeń",
"文本预处理": "Wstępne przetwarzanie tekstu",
@ -811,5 +809,8 @@
"修改列表名称": "Zmień nazwę listy",
"滚动到最后": "Przewiń do końca",
"创建列表": "Utwórz listę",
"限制每行字数": "Ograniczenie liczby słów na wiersz"
"限制每行字数": "Ograniczenie liczby słów na wiersz",
"音频播放": "Odtwarzanie dźwięku",
"语速": "Szybkość mowy",
"音量": "objętość"
}

View File

@ -107,8 +107,6 @@
"语音设置": "Настройка звука",
"火山TTS": "Вулканический TTS",
"选择声音": "Выберите голос",
"语速:(-10~10)": "Скорость: (- 10 ~ 10)",
"音量:(0~100)": "Громкость: (0 ~ 100)",
"自动朗读": "Автоматическое чтение",
"翻译优化": "Оптимизация перевода",
"文本预处理": "Предварительная обработка текста",
@ -811,5 +809,8 @@
"修改列表名称": "Изменить имя списка",
"滚动到最后": "Прокрутить до конца",
"创建列表": "Создать список",
"限制每行字数": "Ограничение количества слов в строке"
"限制每行字数": "Ограничение количества слов в строке",
"音频播放": "Звуковое воспроизведение",
"语速": "Скорость речи",
"音量": "Громкость"
}

View File

@ -103,7 +103,6 @@
"接尾辞": "ข้อความท้าย",
"通用": "วัตถุประสงค์ทั่วไป",
"设置刷新延迟": "ตั้งค่าความล่าช้าในการรีเฟรช",
"音量:(0~100)": "ระดับเสียง: (0 ~ 100)",
"将汉字转换成繁体/日式汉字": "แปลงคันจิเป็นตัวอักษรจีนแบบดั้งเดิม/ญี่ปุ่น",
"失败": "ล้มเหลว",
"token设置": "การตั้งค่า token",
@ -128,7 +127,6 @@
"显示原文": "แสดงข้อความต้นฉบับ",
"不切换": "ไม่มีการสลับ",
"自动更新": "อัปเดตอัตโนมัติ",
"语速:(-10~10)": "ความเร็วในการพูด: (-10 ~ 10)",
"缩放时模拟独占全屏": "จำลองการแสดงผลแบบเต็มหน้าจอเมื่อซูม",
"专有名词翻译设置按钮": "ปุ่มตั้งค่าการแปลคำนามที่เป็นกรรมสิทธิ์",
"越南语": "เวียดนาม",
@ -811,5 +809,8 @@
"修改列表名称": "แก้ไขชื่อรายการ",
"滚动到最后": "เลื่อนไปจนสุด",
"创建列表": "สร้างรายการ",
"限制每行字数": "จำกัดจำนวนคำต่อบรรทัด"
"限制每行字数": "จำกัดจำนวนคำต่อบรรทัด",
"音频播放": "เล่นเสียง",
"语速": "ความเร็วการพูด",
"音量": "ระดับเสียง"
}

View File

@ -107,8 +107,6 @@
"语音设置": "Ses ayarları",
"火山TTS": "Volcano TTS",
"选择声音": "Sesi seç",
"语速:(-10~10)": "Konuşma hızı: (- 10~10)",
"音量:(0~100)": "Ses: (0~100)",
"自动朗读": "Otomatik okuma",
"翻译优化": "Çeviri iyileştirmesi",
"文本预处理": "Metin ön işleme",
@ -811,5 +809,8 @@
"修改列表名称": "Liste ismini değiştir",
"滚动到最后": "Sonuna doğru yürüt",
"创建列表": "Liste oluştur",
"限制每行字数": "Sırada kelimelerin sayısını sınırla"
"限制每行字数": "Sırada kelimelerin sayısını sınırla",
"音频播放": "Ses çalması",
"语速": "Konuşma hızı",
"音量": "volume"
}

View File

@ -101,8 +101,6 @@
"语音设置": "Параметри голосу",
"火山TTS": "Волкановий TTS",
"选择声音": "Виберіть звук",
"语速:(-10~10)": "Швидкість мовлення: (- 10- 10)",
"音量:(0~100)": "Volume: (0-100)",
"自动朗读": "Автоматичне читання",
"翻译优化": "Оптимізація перекладу",
"文本预处理": "Перепроцес тексту",
@ -811,5 +809,8 @@
"修改列表名称": "Змінити назву списку",
"滚动到最后": "Пересунутися до кінця",
"创建列表": "Створити список",
"限制每行字数": "Обмежити кількість слів на рядок"
"限制每行字数": "Обмежити кількість слів на рядок",
"音频播放": "Відтворення звуку",
"语速": "Швидкість мовлення",
"音量": "гучність"
}

View File

@ -107,8 +107,6 @@
"语音设置": "Thiết lập giọng nói",
"火山TTS": "Núi lửa TTS",
"选择声音": "Chọn âm thanh",
"语速:(-10~10)": "Tốc độ nói: (-10~10)",
"音量:(0~100)": "Âm lượng: (0~100)",
"自动朗读": "Tự động đọc",
"翻译优化": "Tối ưu hóa dịch",
"文本预处理": "Tiền xử lý văn bản",
@ -811,5 +809,8 @@
"修改列表名称": "Thay đổi tên danh sách",
"滚动到最后": "Cuộn đến cuối",
"创建列表": "Tạo danh sách",
"限制每行字数": "Giới hạn số lượng từ trên mỗi dòng"
"限制每行字数": "Giới hạn số lượng từ trên mỗi dòng",
"音频播放": "Phát lại âm thanh",
"语速": "Tốc độ nói",
"音量": "Âm lượng"
}

View File

@ -103,7 +103,6 @@
"接尾辞": "",
"通用": "",
"设置刷新延迟": "",
"音量:(0~100)": "",
"将汉字转换成繁体/日式汉字": "",
"失败": "",
"token设置": "",
@ -128,7 +127,6 @@
"显示原文": "",
"不切换": "",
"自动更新": "",
"语速:(-10~10)": "",
"缩放时模拟独占全屏": "",
"专有名词翻译设置按钮": "",
"越南语": "",
@ -811,5 +809,8 @@
"以当前md5复制选中行": "",
"修改列表名称": "",
"滚动到最后": "",
"限制每行字数": ""
"限制每行字数": "",
"音频播放": "",
"语速": "",
"音量": ""
}

View File

@ -28,7 +28,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/version)
include(generate_product_version)
set(VERSION_MAJOR 5)
set(VERSION_MINOR 6)
set(VERSION_MINOR 7)
set(VERSION_PATCH 0)
add_library(pch pch.cpp)