mirror of
https://github.com/HIllya51/LunaTranslator.git
synced 2024-12-27 15:44:12 +08:00
mem
This commit is contained in:
parent
ee183936b7
commit
11f370042f
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -1,3 +1,9 @@
|
|||||||
[submodule "plugins/libs/wil"]
|
[submodule "plugins/libs/wil"]
|
||||||
path = plugins/libs/wil
|
path = plugins/libs/wil
|
||||||
url = https://github.com/microsoft/wil.git
|
url = https://github.com/microsoft/wil.git
|
||||||
|
[submodule "plugins/libs/tinymp3"]
|
||||||
|
path = plugins/libs/tinymp3
|
||||||
|
url = https://github.com/HIllya51/tinymp3
|
||||||
|
[submodule "plugins/libs/miniaudio"]
|
||||||
|
path = plugins/libs/miniaudio
|
||||||
|
url = https://github.com/HIllya51/miniaudio
|
||||||
|
@ -16,9 +16,9 @@ from PyQt5.QtWidgets import (
|
|||||||
)
|
)
|
||||||
from PyQt5.QtGui import QPixmap, QImage
|
from PyQt5.QtGui import QPixmap, QImage
|
||||||
from traceback import print_exc
|
from traceback import print_exc
|
||||||
import requests, json, subprocess, time
|
import requests, json, time
|
||||||
from PyQt5.QtCore import pyqtSignal, Qt, QUrl
|
from PyQt5.QtCore import pyqtSignal, Qt
|
||||||
import qtawesome, functools, os, base64
|
import qtawesome, functools, os, base64, winsharedutils
|
||||||
import gobject, uuid, windows, platform
|
import gobject, uuid, windows, platform
|
||||||
from myutils.config import globalconfig, _TR, static_data
|
from myutils.config import globalconfig, _TR, static_data
|
||||||
import myutils.ankiconnect as anki
|
import myutils.ankiconnect as anki
|
||||||
@ -33,38 +33,12 @@ from gui.usefulwidget import (
|
|||||||
getcolorbutton,
|
getcolorbutton,
|
||||||
tabadd_lazy,
|
tabadd_lazy,
|
||||||
)
|
)
|
||||||
from myutils.subproc import subproc_w, autoproc
|
from myutils.subproc import subproc_w
|
||||||
|
|
||||||
from myutils.wrapper import threader
|
from myutils.wrapper import threader
|
||||||
from myutils.ocrutil import imageCut, ocr_run
|
from myutils.ocrutil import imageCut, ocr_run
|
||||||
from gui.rangeselect import rangeselct_function
|
from gui.rangeselect import rangeselct_function
|
||||||
|
|
||||||
|
|
||||||
class ffmpeg_virtual_audio_capturer:
|
|
||||||
def __init__(self):
|
|
||||||
os.makedirs("./cache/tts", exist_ok=True)
|
|
||||||
self.file = os.path.abspath(
|
|
||||||
os.path.join("./cache/tts", str(time.time()) + ".mp3")
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
self.engine = subprocess.Popen(
|
|
||||||
os.path.join(
|
|
||||||
globalconfig["ffmpeg"],
|
|
||||||
f'ffmpeg.exe -f dshow -i audio="virtual-audio-capturer" "{self.file}"',
|
|
||||||
),
|
|
||||||
stdin=subprocess.PIPE,
|
|
||||||
)
|
|
||||||
except:
|
|
||||||
print_exc()
|
|
||||||
|
|
||||||
def end(self):
|
|
||||||
try:
|
|
||||||
self.engine.stdin.write(b"q")
|
|
||||||
self.engine.stdin.flush()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class loopbackrecorder:
|
class loopbackrecorder:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
os.makedirs("./cache/tts", exist_ok=True)
|
os.makedirs("./cache/tts", exist_ok=True)
|
||||||
@ -72,26 +46,37 @@ class loopbackrecorder:
|
|||||||
os.path.join("./cache/tts", str(time.time()) + ".wav")
|
os.path.join("./cache/tts", str(time.time()) + ".wav")
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
if platform.architecture()[0] == "64bit":
|
|
||||||
_6432 = "64"
|
|
||||||
elif platform.architecture()[0] == "32bit":
|
|
||||||
_6432 = "32"
|
|
||||||
self.waitsignal = str(time.time())
|
self.waitsignal = str(time.time())
|
||||||
self.engine = autoproc(
|
self.engine = subproc_w(
|
||||||
subproc_w(
|
'./files/plugins/shareddllproxy32.exe recordaudio "{}" "{}"'.format(
|
||||||
'./files/plugins/shareddllproxy{}.exe recordaudio "{}" "{}"'.format(
|
self.file, self.waitsignal
|
||||||
_6432, self.file, self.waitsignal
|
),
|
||||||
),
|
|
||||||
name="recordaudio",
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
print_exc()
|
print_exc()
|
||||||
|
|
||||||
def end(self):
|
@threader
|
||||||
|
def end(self, callback):
|
||||||
windows.SetEvent(
|
windows.SetEvent(
|
||||||
windows.AutoHandle(windows.CreateEvent(False, False, self.waitsignal))
|
windows.AutoHandle(windows.CreateEvent(False, False, self.waitsignal))
|
||||||
)
|
)
|
||||||
|
self.engine.wait()
|
||||||
|
filewav = self.file
|
||||||
|
if os.path.exists(filewav) == False:
|
||||||
|
callback("")
|
||||||
|
return
|
||||||
|
filemp3 = filewav.replace(".wav", ".mp3")
|
||||||
|
subproc_w(
|
||||||
|
'./files/plugins/shareddllproxy32.exe mainmp3 "{}" "{}"'.format(
|
||||||
|
filewav, filemp3
|
||||||
|
),
|
||||||
|
run=True,
|
||||||
|
)
|
||||||
|
if os.path.exists(filemp3):
|
||||||
|
os.remove(filewav)
|
||||||
|
callback(filemp3)
|
||||||
|
else:
|
||||||
|
callback(filewav)
|
||||||
|
|
||||||
|
|
||||||
class statusbutton(QPushButton):
|
class statusbutton(QPushButton):
|
||||||
@ -390,49 +375,13 @@ class AnkiWindow(QWidget):
|
|||||||
getsimpleswitch(globalconfig["ankiconnect"], "autoruntts"),
|
getsimpleswitch(globalconfig["ankiconnect"], "autoruntts"),
|
||||||
)
|
)
|
||||||
|
|
||||||
layout.addWidget(QLabel())
|
|
||||||
layout.addRow(_TR("录音"), QLabel())
|
|
||||||
lb = QLabel()
|
|
||||||
lb.setOpenExternalLinks(True)
|
|
||||||
lb.setText(
|
|
||||||
'<a href="https://github.com/HIllya51/RESOURCES/releases/download/softwares/virtual-audio.zip">virtual-audio-capturer</a>'
|
|
||||||
)
|
|
||||||
layout.addRow(_TR("安装录音驱动"), lb)
|
|
||||||
ffmpegpath = getlineedit(globalconfig, "ffmpeg", readonly=True)
|
|
||||||
|
|
||||||
def selectpath():
|
|
||||||
f = QFileDialog.getExistingDirectory()
|
|
||||||
if f != "":
|
|
||||||
ffmpegpath.setText(f)
|
|
||||||
|
|
||||||
layout.addRow(
|
|
||||||
_TR("ffmpeg"),
|
|
||||||
getboxlayout(
|
|
||||||
[
|
|
||||||
ffmpegpath,
|
|
||||||
getcolorbutton(
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
selectpath,
|
|
||||||
icon="fa.gear",
|
|
||||||
constcolor="#FF69B4",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
makewidget=True,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
return wid
|
return wid
|
||||||
|
|
||||||
def startorendrecord(self, target: QLineEdit, idx):
|
def startorendrecord(self, target: QLineEdit, idx):
|
||||||
if idx == 1:
|
if idx == 1:
|
||||||
if len(globalconfig["ffmpeg"]) and os.path.exists(globalconfig["ffmpeg"]):
|
self.recorder = loopbackrecorder()
|
||||||
self.recorder = ffmpeg_virtual_audio_capturer()
|
|
||||||
else:
|
|
||||||
self.recorder = loopbackrecorder()
|
|
||||||
else:
|
else:
|
||||||
self.recorder.end()
|
self.recorder.end(callback=target.setText)
|
||||||
target.setText(self.recorder.file)
|
|
||||||
|
|
||||||
def createaddtab(self):
|
def createaddtab(self):
|
||||||
layout = QVBoxLayout()
|
layout = QVBoxLayout()
|
||||||
|
@ -20,8 +20,9 @@ from myutils.config import (
|
|||||||
savehook_new_data,
|
savehook_new_data,
|
||||||
getdefaultsavehook,
|
getdefaultsavehook,
|
||||||
)
|
)
|
||||||
|
from ctypes import c_float, pointer, c_void_p
|
||||||
import threading
|
import threading
|
||||||
import re, heapq
|
import re, heapq, winsharedutils
|
||||||
from myutils.vndb import searchfordata, getvidbytitle
|
from myutils.vndb import searchfordata, getvidbytitle
|
||||||
from myutils.wrapper import tryprint
|
from myutils.wrapper import tryprint
|
||||||
|
|
||||||
@ -260,48 +261,36 @@ class wavmp3player:
|
|||||||
if task is None:
|
if task is None:
|
||||||
continue
|
continue
|
||||||
binary, volume, force = task
|
binary, volume, force = task
|
||||||
os.makedirs("./cache/tts", exist_ok=True)
|
durationms = self._playsoundWin(binary, volume)
|
||||||
|
|
||||||
tgt = os.path.abspath("./cache/tts/" + str(time.time()) + ".wav")
|
|
||||||
with open(tgt, "wb") as ff:
|
|
||||||
ff.write(binary)
|
|
||||||
durationms = self._playsoundWin(tgt, volume)
|
|
||||||
self.lastfile = tgt
|
|
||||||
if durationms and globalconfig["ttsnointerrupt"]:
|
if durationms and globalconfig["ttsnointerrupt"]:
|
||||||
while durationms > 0:
|
while durationms > 0:
|
||||||
durationms -= 100
|
durationms -= 100
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
if self.tasks and self.tasks[-1]:
|
if self.tasks and self.tasks[-1]:
|
||||||
break
|
break
|
||||||
# time.sleep(durationms / 1000)
|
|
||||||
except:
|
except:
|
||||||
print_exc()
|
print_exc()
|
||||||
|
|
||||||
def _playsoundWin(self, sound, volume):
|
def _playsoundWin(self, binary, volume):
|
||||||
try:
|
try:
|
||||||
|
duration = c_float()
|
||||||
windows.mciSendString(("stop lunatranslator_mci_{}".format(self.i)))
|
device = c_void_p()
|
||||||
windows.mciSendString(("close lunatranslator_mci_{}".format(self.i)))
|
decoder = c_void_p()
|
||||||
self.i += 1
|
succ = winsharedutils.PlayAudioInMem(
|
||||||
|
binary,
|
||||||
|
len(binary),
|
||||||
|
volume / 100,
|
||||||
|
pointer(decoder),
|
||||||
|
pointer(device),
|
||||||
|
pointer(duration),
|
||||||
|
)
|
||||||
|
if succ != 0:
|
||||||
|
return 0
|
||||||
if self.lastfile:
|
if self.lastfile:
|
||||||
os.remove(self.lastfile)
|
winsharedutils.PlayAudioInMem_Stop(self.lastfile[0], self.lastfile[1])
|
||||||
self.lastfile = sound
|
self.lastfile = decoder, device
|
||||||
windows.mciSendString(
|
durationms = duration.value * 1000
|
||||||
'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:
|
except:
|
||||||
durationms = 0
|
durationms = 0
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ from ctypes import (
|
|||||||
create_string_buffer,
|
create_string_buffer,
|
||||||
c_size_t,
|
c_size_t,
|
||||||
windll,
|
windll,
|
||||||
|
c_float,
|
||||||
c_char,
|
c_char,
|
||||||
)
|
)
|
||||||
from ctypes.wintypes import WORD, HANDLE, HWND, LONG, DWORD
|
from ctypes.wintypes import WORD, HANDLE, HWND, LONG, DWORD
|
||||||
@ -186,7 +187,10 @@ html_release.argtypes = (c_void_p,)
|
|||||||
html_get_current_url = utilsdll.html_get_current_url
|
html_get_current_url = utilsdll.html_get_current_url
|
||||||
html_get_current_url.argtypes = c_void_p, c_wchar_p
|
html_get_current_url.argtypes = c_void_p, c_wchar_p
|
||||||
html_set_html = utilsdll.html_set_html
|
html_set_html = utilsdll.html_set_html
|
||||||
html_set_html.argtypes = c_void_p, c_wchar_p,
|
html_set_html.argtypes = (
|
||||||
|
c_void_p,
|
||||||
|
c_wchar_p,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class HTMLBrowser:
|
class HTMLBrowser:
|
||||||
@ -333,3 +337,17 @@ startmaglistener = utilsdll.startmaglistener
|
|||||||
startmaglistener.restype = HANDLE
|
startmaglistener.restype = HANDLE
|
||||||
endmaglistener = utilsdll.endmaglistener
|
endmaglistener = utilsdll.endmaglistener
|
||||||
endmaglistener.argtypes = (HANDLE,)
|
endmaglistener.argtypes = (HANDLE,)
|
||||||
|
|
||||||
|
PlayAudioInMem = utilsdll.PlayAudioInMem
|
||||||
|
PlayAudioInMem.argtypes = (
|
||||||
|
c_void_p,
|
||||||
|
c_size_t,
|
||||||
|
c_float,
|
||||||
|
c_void_p,
|
||||||
|
c_void_p,
|
||||||
|
POINTER(c_float),
|
||||||
|
)
|
||||||
|
PlayAudioInMem.restype = c_int
|
||||||
|
|
||||||
|
PlayAudioInMem_Stop = utilsdll.PlayAudioInMem_Stop
|
||||||
|
PlayAudioInMem_Stop.argtypes = c_void_p, c_void_p
|
||||||
|
@ -54,7 +54,6 @@
|
|||||||
"changecharset": false,
|
"changecharset": false,
|
||||||
"changecharset_charset": 2
|
"changecharset_charset": 2
|
||||||
},
|
},
|
||||||
"ffmpeg": "",
|
|
||||||
"requestinterval": 1,
|
"requestinterval": 1,
|
||||||
"keepontop": true,
|
"keepontop": true,
|
||||||
"buttonsize": 20,
|
"buttonsize": 20,
|
||||||
|
@ -789,8 +789,6 @@
|
|||||||
"截图后进行OCR": "التعرف الضوئي على الحروف",
|
"截图后进行OCR": "التعرف الضوئي على الحروف",
|
||||||
"优先级": "الأولوية",
|
"优先级": "الأولوية",
|
||||||
"编码": "ترميز",
|
"编码": "ترميز",
|
||||||
"安装录音驱动": "تثبيت برنامج تشغيل التسجيل",
|
|
||||||
"录音": "تسجيل صوتي",
|
|
||||||
"自动TTS": "التلقائي تحويل النص إلى كلام",
|
"自动TTS": "التلقائي تحويل النص إلى كلام",
|
||||||
"使用webview显示": "عرض باستخدام WebView"
|
"使用webview显示": "عرض باستخدام WebView"
|
||||||
}
|
}
|
@ -789,8 +789,6 @@
|
|||||||
"截图后进行OCR": "截圖後進行OCR",
|
"截图后进行OCR": "截圖後進行OCR",
|
||||||
"优先级": "優先順序",
|
"优先级": "優先順序",
|
||||||
"编码": "編碼",
|
"编码": "編碼",
|
||||||
"安装录音驱动": "安裝錄音驅動",
|
|
||||||
"录音": "錄音",
|
|
||||||
"自动TTS": "自動TTS",
|
"自动TTS": "自動TTS",
|
||||||
"使用webview显示": "使用webview顯示"
|
"使用webview显示": "使用webview顯示"
|
||||||
}
|
}
|
@ -789,8 +789,6 @@
|
|||||||
"截图后进行OCR": "Perform OCR after taking screenshots",
|
"截图后进行OCR": "Perform OCR after taking screenshots",
|
||||||
"优先级": "priority",
|
"优先级": "priority",
|
||||||
"编码": "coding",
|
"编码": "coding",
|
||||||
"安装录音驱动": "Install recording driver",
|
|
||||||
"录音": "tape",
|
|
||||||
"自动TTS": "Automatic TTS",
|
"自动TTS": "Automatic TTS",
|
||||||
"使用webview显示": "Display using webview"
|
"使用webview显示": "Display using webview"
|
||||||
}
|
}
|
@ -789,8 +789,6 @@
|
|||||||
"截图后进行OCR": "OCR después de la captura de pantalla",
|
"截图后进行OCR": "OCR después de la captura de pantalla",
|
||||||
"优先级": "Prioridad",
|
"优先级": "Prioridad",
|
||||||
"编码": "Codificación",
|
"编码": "Codificación",
|
||||||
"安装录音驱动": "Instalación de la unidad de grabación",
|
|
||||||
"录音": "Grabación",
|
|
||||||
"自动TTS": "TTS automático",
|
"自动TTS": "TTS automático",
|
||||||
"使用webview显示": "Mostrar con Webview"
|
"使用webview显示": "Mostrar con Webview"
|
||||||
}
|
}
|
@ -789,8 +789,6 @@
|
|||||||
"截图后进行OCR": "OCR après capture d'écran",
|
"截图后进行OCR": "OCR après capture d'écran",
|
||||||
"优先级": "Priorité",
|
"优先级": "Priorité",
|
||||||
"编码": "Codage",
|
"编码": "Codage",
|
||||||
"安装录音驱动": "Installer le driver d'enregistrement",
|
|
||||||
"录音": "Enregistrement sonore",
|
|
||||||
"自动TTS": "Tts automatique",
|
"自动TTS": "Tts automatique",
|
||||||
"使用webview显示": "Afficher avec webview"
|
"使用webview显示": "Afficher avec webview"
|
||||||
}
|
}
|
@ -789,8 +789,6 @@
|
|||||||
"截图后进行OCR": "Esegui OCR dopo aver scattato screenshot",
|
"截图后进行OCR": "Esegui OCR dopo aver scattato screenshot",
|
||||||
"优先级": "priorità",
|
"优先级": "priorità",
|
||||||
"编码": "codifica",
|
"编码": "codifica",
|
||||||
"安装录音驱动": "Installa il driver di registrazione",
|
|
||||||
"录音": "nastro",
|
|
||||||
"自动TTS": "TTS automatico",
|
"自动TTS": "TTS automatico",
|
||||||
"使用webview显示": "Visualizzazione tramite webview"
|
"使用webview显示": "Visualizzazione tramite webview"
|
||||||
}
|
}
|
@ -789,8 +789,6 @@
|
|||||||
"截图后进行OCR": "スクリーンショット後にOCR",
|
"截图后进行OCR": "スクリーンショット後にOCR",
|
||||||
"优先级": "優先度",
|
"优先级": "優先度",
|
||||||
"编码": "エンコード",
|
"编码": "エンコード",
|
||||||
"安装录音驱动": "録音ドライブのインストール",
|
|
||||||
"录音": "レコーディング",
|
|
||||||
"自动TTS": "自動TTS",
|
"自动TTS": "自動TTS",
|
||||||
"使用webview显示": "webview表示の使用"
|
"使用webview显示": "webview表示の使用"
|
||||||
}
|
}
|
@ -789,8 +789,6 @@
|
|||||||
"截图后进行OCR": "캡처해서 OCR 진행하도록 하겠습니다.",
|
"截图后进行OCR": "캡처해서 OCR 진행하도록 하겠습니다.",
|
||||||
"优先级": "우선 순위",
|
"优先级": "우선 순위",
|
||||||
"编码": "인코딩",
|
"编码": "인코딩",
|
||||||
"安装录音驱动": "녹음 드라이브 설치",
|
|
||||||
"录音": "녹음",
|
|
||||||
"自动TTS": "자동 TTS",
|
"自动TTS": "자동 TTS",
|
||||||
"使用webview显示": "웹뷰를 사용하여 표시"
|
"使用webview显示": "웹뷰를 사용하여 표시"
|
||||||
}
|
}
|
@ -789,8 +789,6 @@
|
|||||||
"截图后进行OCR": "Wykonanie OCR po wykonaniu zrzutów ekranu",
|
"截图后进行OCR": "Wykonanie OCR po wykonaniu zrzutów ekranu",
|
||||||
"优先级": "priorytet",
|
"优先级": "priorytet",
|
||||||
"编码": "kodowanie",
|
"编码": "kodowanie",
|
||||||
"安装录音驱动": "Zainstaluj sterownik nagrywania",
|
|
||||||
"录音": "taśma",
|
|
||||||
"自动TTS": "Automatyczny TTS",
|
"自动TTS": "Automatyczny TTS",
|
||||||
"使用webview显示": "Wyświetlanie przy użyciu widoku internetowego"
|
"使用webview显示": "Wyświetlanie przy użyciu widoku internetowego"
|
||||||
}
|
}
|
@ -789,8 +789,6 @@
|
|||||||
"截图后进行OCR": "Снимок экрана после OCR",
|
"截图后进行OCR": "Снимок экрана после OCR",
|
||||||
"优先级": "Приоритеты",
|
"优先级": "Приоритеты",
|
||||||
"编码": "Код",
|
"编码": "Код",
|
||||||
"安装录音驱动": "Установка привода звукозаписи",
|
|
||||||
"录音": "Запись",
|
|
||||||
"自动TTS": "Автоматический TTS",
|
"自动TTS": "Автоматический TTS",
|
||||||
"使用webview显示": "Использовать webview"
|
"使用webview显示": "Использовать webview"
|
||||||
}
|
}
|
@ -789,8 +789,6 @@
|
|||||||
"截图后进行OCR": "ทำ OCR หลังจากจับภาพหน้าจอ",
|
"截图后进行OCR": "ทำ OCR หลังจากจับภาพหน้าจอ",
|
||||||
"优先级": "ลำดับความสำคัญ",
|
"优先级": "ลำดับความสำคัญ",
|
||||||
"编码": "การเข้ารหัส",
|
"编码": "การเข้ารหัส",
|
||||||
"安装录音驱动": "ติดตั้งไดรฟ์บันทึก",
|
|
||||||
"录音": "การบันทึกเสียง",
|
|
||||||
"自动TTS": "TTS อัตโนมัติ",
|
"自动TTS": "TTS อัตโนมัติ",
|
||||||
"使用webview显示": "ใช้ webview เพื่อแสดงผล"
|
"使用webview显示": "ใช้ webview เพื่อแสดงผล"
|
||||||
}
|
}
|
@ -789,8 +789,6 @@
|
|||||||
"截图后进行OCR": "Ekran fotoğraflarını aldıktan sonra OCR yap",
|
"截图后进行OCR": "Ekran fotoğraflarını aldıktan sonra OCR yap",
|
||||||
"优先级": "Prioritet",
|
"优先级": "Prioritet",
|
||||||
"编码": "coding",
|
"编码": "coding",
|
||||||
"安装录音驱动": "Kayıt sürücüsünü kur",
|
|
||||||
"录音": "kaset",
|
|
||||||
"自动TTS": "Otomatik TTS",
|
"自动TTS": "Otomatik TTS",
|
||||||
"使用webview显示": "Web görüntüsünü kullanarak göster"
|
"使用webview显示": "Web görüntüsünü kullanarak göster"
|
||||||
}
|
}
|
@ -789,8 +789,6 @@
|
|||||||
"截图后进行OCR": "Виконати OCR після роботи знімків екрана",
|
"截图后进行OCR": "Виконати OCR після роботи знімків екрана",
|
||||||
"优先级": "пріоритет",
|
"优先级": "пріоритет",
|
||||||
"编码": "кодування",
|
"编码": "кодування",
|
||||||
"安装录音驱动": "Встановити драйвер запису",
|
|
||||||
"录音": "стрічку",
|
|
||||||
"自动TTS": "Автоматичний TTS",
|
"自动TTS": "Автоматичний TTS",
|
||||||
"使用webview显示": "Показувати за допомогою веб- перегляду"
|
"使用webview显示": "Показувати за допомогою веб- перегляду"
|
||||||
}
|
}
|
@ -789,8 +789,6 @@
|
|||||||
"截图后进行OCR": "OCR sau khi chụp ảnh màn hình",
|
"截图后进行OCR": "OCR sau khi chụp ảnh màn hình",
|
||||||
"优先级": "Ưu tiên",
|
"优先级": "Ưu tiên",
|
||||||
"编码": "Mã hóa",
|
"编码": "Mã hóa",
|
||||||
"安装录音驱动": "Cài đặt Recording Drive",
|
|
||||||
"录音": "Ghi âm",
|
|
||||||
"自动TTS": "Tự động TTS",
|
"自动TTS": "Tự động TTS",
|
||||||
"使用webview显示": "Sử dụng WebView để hiển thị"
|
"使用webview显示": "Sử dụng WebView để hiển thị"
|
||||||
}
|
}
|
@ -789,8 +789,6 @@
|
|||||||
"截图后进行OCR": "",
|
"截图后进行OCR": "",
|
||||||
"优先级": "",
|
"优先级": "",
|
||||||
"编码": "",
|
"编码": "",
|
||||||
"安装录音驱动": "",
|
|
||||||
"录音": "",
|
|
||||||
"自动TTS": "",
|
"自动TTS": "",
|
||||||
"使用webview显示": ""
|
"使用webview显示": ""
|
||||||
}
|
}
|
@ -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 7)
|
set(VERSION_PATCH 8)
|
||||||
|
|
||||||
add_library(pch pch.cpp)
|
add_library(pch pch.cpp)
|
||||||
target_precompile_headers(pch PUBLIC pch.h)
|
target_precompile_headers(pch PUBLIC pch.h)
|
||||||
|
@ -8,6 +8,9 @@ include_directories(${CMAKE_CURRENT_LIST_DIR})
|
|||||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/Detours-4.0.1/include)
|
include_directories(${CMAKE_CURRENT_LIST_DIR}/Detours-4.0.1/include)
|
||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/wil/include)
|
include_directories(${CMAKE_CURRENT_LIST_DIR}/wil/include)
|
||||||
|
include_directories(${CMAKE_CURRENT_LIST_DIR}/miniaudio)
|
||||||
|
include_directories(${CMAKE_CURRENT_LIST_DIR}/tinymp3)
|
||||||
|
|
||||||
|
|
||||||
if(${CMAKE_SIZEOF_VOID_P} EQUAL 4)
|
if(${CMAKE_SIZEOF_VOID_P} EQUAL 4)
|
||||||
set(LTLPlatform "Win32")
|
set(LTLPlatform "Win32")
|
||||||
|
1
plugins/libs/miniaudio
Submodule
1
plugins/libs/miniaudio
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 4a5b74bef029b3592c54b6048650ee5f972c1a48
|
1
plugins/libs/tinymp3
Submodule
1
plugins/libs/tinymp3
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 9781d63bf7d057457b25b5e77492bcf2cfa109c5
|
@ -12,17 +12,18 @@ generate_product_version(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
add_executable(shareddllproxy applicationloopbackaudio/LoopbackCapture.cpp applicationloopbackaudio/runer.cpp shareddllproxy.cpp dllinject.cpp ntleas.cpp aspatch.cpp update.cpp ${versioninfo})
|
add_executable(shareddllproxy shareddllproxy.cpp dllinject.cpp ntleas.cpp aspatch.cpp update.cpp ${versioninfo})
|
||||||
target_precompile_headers(shareddllproxy REUSE_FROM pch)
|
target_precompile_headers(shareddllproxy REUSE_FROM pch)
|
||||||
if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
|
if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
|
||||||
|
|
||||||
target_link_libraries(shareddllproxy Mfplat mfuuid ${Detours})
|
target_link_libraries(shareddllproxy Mfplat mfuuid ${Detours})
|
||||||
set_target_properties(shareddllproxy PROPERTIES OUTPUT_NAME "shareddllproxy64")
|
set_target_properties(shareddllproxy PROPERTIES OUTPUT_NAME "shareddllproxy64")
|
||||||
else()
|
else()
|
||||||
|
add_library(tinymp3 ../libs/tinymp3/shine_mp3.c)
|
||||||
add_subdirectory(voiceroid2)
|
add_subdirectory(voiceroid2)
|
||||||
add_library(x86lib dreye.cpp jbj7.cpp kingsoft.cpp le.cpp neospeech.cpp ../implsapi.cpp LR.cpp)
|
add_library(x86lib dreye.cpp jbj7.cpp kingsoft.cpp le.cpp neospeech.cpp ../implsapi.cpp LR.cpp applicationloopbackaudio/runer.cpp applicationloopbackaudio/LoopbackCapture.cpp mp3.cpp)
|
||||||
target_precompile_headers(voiceroid2 REUSE_FROM pch)
|
target_precompile_headers(voiceroid2 REUSE_FROM pch)
|
||||||
target_precompile_headers(x86lib REUSE_FROM pch)
|
target_precompile_headers(x86lib REUSE_FROM pch)
|
||||||
target_link_libraries(shareddllproxy Mfplat mfuuid x86lib voiceroid2 ${Detours})
|
target_link_libraries(shareddllproxy Mfplat mfuuid x86lib tinymp3 voiceroid2 ${Detours})
|
||||||
set_target_properties(shareddllproxy PROPERTIES OUTPUT_NAME "shareddllproxy32")
|
set_target_properties(shareddllproxy PROPERTIES OUTPUT_NAME "shareddllproxy32")
|
||||||
endif()
|
endif()
|
||||||
|
248
plugins/shareddllproxy/mp3.cpp
Normal file
248
plugins/shareddllproxy/mp3.cpp
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <timing.h>
|
||||||
|
#include <shine_mp3.h>
|
||||||
|
|
||||||
|
#define DR_WAV_IMPLEMENTATION
|
||||||
|
|
||||||
|
#include <dr_wav.h>
|
||||||
|
|
||||||
|
#define DR_MP3_IMPLEMENTATION
|
||||||
|
|
||||||
|
#include <dr_mp3.h>
|
||||||
|
|
||||||
|
void error(char *s);
|
||||||
|
|
||||||
|
|
||||||
|
int16_t *wavRead_int16(char *filename, uint32_t *sampleRate, uint32_t *channels, uint64_t *totalSampleCount) {
|
||||||
|
int16_t *buffer = drwav_open_file_and_read_pcm_frames_s16(filename, channels, sampleRate, totalSampleCount, NULL);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
drmp3_config pConfig;
|
||||||
|
buffer = drmp3_open_file_and_read_pcm_frames_s16(filename, &pConfig, totalSampleCount, NULL);
|
||||||
|
if (buffer != NULL) {
|
||||||
|
*channels = pConfig.channels;
|
||||||
|
*sampleRate = pConfig.sampleRate;
|
||||||
|
*totalSampleCount *= *channels;
|
||||||
|
} else {
|
||||||
|
printf("read file [%s] error.\n", filename);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*totalSampleCount *= *channels;
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Some global vars. */
|
||||||
|
char *infname, *outfname;
|
||||||
|
FILE *outfile;
|
||||||
|
int quiet = 0;
|
||||||
|
int stereo = STEREO;
|
||||||
|
int force_mono = 0;
|
||||||
|
|
||||||
|
/* Write out the MP3 file */
|
||||||
|
int write_mp3(long bytes, void *buffer, void *config) {
|
||||||
|
return fwrite(buffer, sizeof(unsigned char), bytes, outfile) / sizeof(unsigned char);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Output error message and exit */
|
||||||
|
void error(char *s) {
|
||||||
|
fprintf(stderr, "Error: %s\n", s);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_usage() {
|
||||||
|
printf("Audio Processing\n");
|
||||||
|
printf("mp3 encoder && decoder\n");
|
||||||
|
printf("blog: http://cpuimage.cnblogs.com/\n");
|
||||||
|
printf("Usage: tinymp3 [options] <infile> <outfile>\n\n");
|
||||||
|
printf("Use \"-\" for standard input or output.\n\n");
|
||||||
|
printf("Options:\n");
|
||||||
|
printf(" -h this help message\n");
|
||||||
|
printf(" -b <bitrate> set the bitrate [8-320], default 64 kbit\n");
|
||||||
|
printf(" -m force encoder to operate in mono\n");
|
||||||
|
printf(" -c set copyright flag, default off\n");
|
||||||
|
printf(" -j encode in joint stereo (stereo data only)\n");
|
||||||
|
printf(" -d encode in dual-channel (stereo data only)\n");
|
||||||
|
printf(" -q quiet mode\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use these default settings, can be overridden */
|
||||||
|
static void set_defaults(shine_config_t *config) {
|
||||||
|
shine_set_config_mpeg_defaults(&config->mpeg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse command line arguments */
|
||||||
|
static int parse_command(int argc, char **argv, shine_config_t *config) {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (argc < 3) return 0;
|
||||||
|
|
||||||
|
while (argv[++i][0] == '-' && argv[i][1] != '\000' && argv[i][1] != ' ')
|
||||||
|
switch (argv[i][1]) {
|
||||||
|
case 'b':
|
||||||
|
config->mpeg.bitr = atoi(argv[++i]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
force_mono = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'j':
|
||||||
|
stereo = JOINT_STEREO;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
stereo = DUAL_CHANNEL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
config->mpeg.copyright = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'q':
|
||||||
|
quiet = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
quiet = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
default :
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc - i != 2) return 0;
|
||||||
|
infname = argv[i++];
|
||||||
|
outfname = argv[i];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print some info about what we're going to encode */
|
||||||
|
static void check_config(shine_config_t *config) {
|
||||||
|
static char *version_names[4] = {"2.5", "reserved", "II", "I"};
|
||||||
|
static char *mode_names[4] = {"stereo", "joint-stereo", "dual-channel", "mono"};
|
||||||
|
static char *demp_names[4] = {"none", "50/15us", "", "CITT"};
|
||||||
|
|
||||||
|
printf("MPEG-%s layer III, %s Psychoacoustic Model: Shine\n",
|
||||||
|
version_names[shine_check_config(config->wave.samplerate, config->mpeg.bitr)],
|
||||||
|
mode_names[config->mpeg.mode]);
|
||||||
|
printf("Bitrate: %d kbps ", config->mpeg.bitr);
|
||||||
|
printf("De-emphasis: %s %s %s\n",
|
||||||
|
demp_names[config->mpeg.emph],
|
||||||
|
((config->mpeg.original) ? "Original" : ""),
|
||||||
|
((config->mpeg.copyright) ? "(C)" : ""));
|
||||||
|
printf("Encoding \"%s\" to \"%s\"\n", infname, outfname);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mainmp3(int argc, wchar_t *wargv[]) {
|
||||||
|
char **argv = new char *[argc];
|
||||||
|
for (int i = 0; i < argc; i++)
|
||||||
|
{
|
||||||
|
int length = WideCharToMultiByte(CP_ACP, 0, wargv[i], -1, NULL, 0, NULL, NULL);
|
||||||
|
argv[i] = new char[length];
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, wargv[i], -1, argv[i], length, NULL, NULL);
|
||||||
|
}
|
||||||
|
shine_config_t config;
|
||||||
|
shine_t s;
|
||||||
|
int written;
|
||||||
|
unsigned char *data;
|
||||||
|
/* Set the default MPEG encoding paramters - basically init the struct */
|
||||||
|
set_defaults(&config);
|
||||||
|
|
||||||
|
if (!parse_command(argc, argv, &config)) {
|
||||||
|
print_usage();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
quiet = quiet || !strcmp(outfname, "-");
|
||||||
|
|
||||||
|
if (!quiet) {
|
||||||
|
printf("Audio Processing\n");
|
||||||
|
printf("mp3 encoder && decoder\n");
|
||||||
|
printf("blog:http://cpuimage.cnblogs.com/\n");
|
||||||
|
}
|
||||||
|
uint32_t sampleRate = 0;
|
||||||
|
uint64_t totalSampleCount = 0;
|
||||||
|
uint32_t channels = 0;
|
||||||
|
int16_t *data_in = wavRead_int16(infname, &sampleRate, &channels, &totalSampleCount);
|
||||||
|
if (data_in == NULL)
|
||||||
|
return -1;
|
||||||
|
double startTime = now();
|
||||||
|
config.wave.samplerate = sampleRate;
|
||||||
|
config.wave.channels = (decltype(config.wave.channels))channels;
|
||||||
|
|
||||||
|
if (force_mono)
|
||||||
|
config.wave.channels = (decltype(config.wave.channels))1;
|
||||||
|
|
||||||
|
/* See if samplerate and bitrate are valid */
|
||||||
|
if (shine_check_config(config.wave.samplerate, config.mpeg.bitr) < 0)
|
||||||
|
error("Unsupported samplerate/bitrate configuration.");
|
||||||
|
|
||||||
|
/* open the output file */
|
||||||
|
if (!strcmp(outfname, "-"))
|
||||||
|
outfile = stdout;
|
||||||
|
else
|
||||||
|
outfile = fopen(outfname, "wb");
|
||||||
|
if (!outfile) {
|
||||||
|
fprintf(stderr, "Could not create \"%s\".\n", outfname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set to stereo mode if wave data is stereo, mono otherwise. */
|
||||||
|
if (config.wave.channels > 1)
|
||||||
|
config.mpeg.mode = (decltype(config.mpeg.mode))stereo;
|
||||||
|
else
|
||||||
|
config.mpeg.mode = MONO;
|
||||||
|
|
||||||
|
/* Initiate encoder */
|
||||||
|
s = shine_initialise(&config);
|
||||||
|
|
||||||
|
// assert(s != NULL);
|
||||||
|
/* Print some info about the file about to be created (optional) */
|
||||||
|
if (!quiet) check_config(&config);
|
||||||
|
|
||||||
|
int samples_per_pass = shine_samples_per_pass(s) * channels;
|
||||||
|
|
||||||
|
/* All the magic happens here */
|
||||||
|
size_t count = totalSampleCount / samples_per_pass;
|
||||||
|
int16_t *buffer = data_in;
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
data = shine_encode_buffer_interleaved(s, buffer, &written);
|
||||||
|
if (write_mp3(written, data, &config) != written) {
|
||||||
|
fprintf(stderr, "mp3 encoder && decoder: write error\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
buffer += samples_per_pass;
|
||||||
|
}
|
||||||
|
size_t last = totalSampleCount % samples_per_pass;
|
||||||
|
if (last != 0) {
|
||||||
|
int16_t *cache = (int16_t *) calloc(samples_per_pass, sizeof(int16_t));
|
||||||
|
if (cache != NULL) {
|
||||||
|
memcpy(cache, buffer, last * sizeof(int16_t));
|
||||||
|
data = shine_encode_buffer_interleaved(s, cache, &written);
|
||||||
|
free(cache);
|
||||||
|
if (write_mp3(written, data, &config) != written) {
|
||||||
|
fprintf(stderr, "mp3 encoder && decoder: write error\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Flush and write remaining data. */
|
||||||
|
data = shine_flush(s, &written);
|
||||||
|
write_mp3(written, data, &config);
|
||||||
|
/* Close encoder. */
|
||||||
|
shine_close(s);
|
||||||
|
/* Close the MP3 file */
|
||||||
|
fclose(outfile);
|
||||||
|
free(data_in);
|
||||||
|
double time_interval = calcElapsed(startTime, now());
|
||||||
|
if (!quiet)
|
||||||
|
printf("time interval: %d ms\n ", (int) (time_interval * 1000));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -1,11 +1,12 @@
|
|||||||
#pragma comment(linker, "/subsystem:windows /entry:wmainCRTStartup")
|
#pragma comment(linker, "/subsystem:windows /entry:wmainCRTStartup")
|
||||||
int recordaudio(int argc, wchar_t *argv[]);
|
|
||||||
|
|
||||||
int dllinjectwmain(int argc, wchar_t *argv[]);
|
int dllinjectwmain(int argc, wchar_t *argv[]);
|
||||||
int ntleaswmain(int argc, wchar_t *wargv[]);
|
int ntleaswmain(int argc, wchar_t *wargv[]);
|
||||||
int updatewmain(int argc, wchar_t *wargv[]);
|
int updatewmain(int argc, wchar_t *wargv[]);
|
||||||
bool checkisapatch();
|
bool checkisapatch();
|
||||||
#ifndef _WIN64
|
#ifndef _WIN64
|
||||||
|
int recordaudio(int argc, wchar_t *argv[]);
|
||||||
|
int mainmp3(int argc, wchar_t *argv[]);
|
||||||
int LRwmain(int argc, wchar_t *argv[]);
|
int LRwmain(int argc, wchar_t *argv[]);
|
||||||
int jbjwmain(int argc, wchar_t *argv[]);
|
int jbjwmain(int argc, wchar_t *argv[]);
|
||||||
int dreyewmain(int argc, wchar_t *argv[]);
|
int dreyewmain(int argc, wchar_t *argv[]);
|
||||||
@ -65,9 +66,11 @@ int wmain(int argc, wchar_t *argv[])
|
|||||||
return listprocessmodule(argc - 1, argv + 1);
|
return listprocessmodule(argc - 1, argv + 1);
|
||||||
if (argv0 == L"update")
|
if (argv0 == L"update")
|
||||||
return updatewmain(argc - 1, argv + 1);
|
return updatewmain(argc - 1, argv + 1);
|
||||||
if (argv0 == L"recordaudio")
|
|
||||||
return recordaudio(argc - 1, argv + 1);
|
|
||||||
#ifndef _WIN64
|
#ifndef _WIN64
|
||||||
|
else if (argv0 == L"recordaudio")
|
||||||
|
return recordaudio(argc - 1, argv + 1);
|
||||||
|
else if (argv0 == L"mainmp3")
|
||||||
|
return mainmp3(argc - 1, argv + 1);
|
||||||
else if (argv0 == L"LR")
|
else if (argv0 == L"LR")
|
||||||
return LRwmain(argc - 1, argv + 1);
|
return LRwmain(argc - 1, argv + 1);
|
||||||
else if (argv0 == L"le")
|
else if (argv0 == L"le")
|
||||||
|
@ -11,7 +11,7 @@ generate_product_version(
|
|||||||
VERSION_PATCH ${VERSION_PATCH}
|
VERSION_PATCH ${VERSION_PATCH}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(winsharedutils MODULE ../implsapi.cpp hwnd.cpp darklistener.cpp theme.cpp version.cpp otsu.cpp cinterface.cpp clipboard.cpp lnk.cpp dllmain.cpp levenshtein.cpp muteprocess.cpp sapi_dll.cpp simplemecab.cpp SimpleBrowser.cpp MWebBrowser.cpp icon.cpp maglistener.cpp ${versioninfo})
|
add_library(winsharedutils MODULE audio.cpp ../implsapi.cpp hwnd.cpp darklistener.cpp theme.cpp version.cpp otsu.cpp cinterface.cpp clipboard.cpp lnk.cpp dllmain.cpp levenshtein.cpp muteprocess.cpp sapi_dll.cpp simplemecab.cpp SimpleBrowser.cpp MWebBrowser.cpp icon.cpp maglistener.cpp ${versioninfo})
|
||||||
target_precompile_headers(winsharedutils REUSE_FROM pch)
|
target_precompile_headers(winsharedutils REUSE_FROM pch)
|
||||||
if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
|
if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
|
||||||
set_target_properties(winsharedutils PROPERTIES OUTPUT_NAME "winsharedutils64")
|
set_target_properties(winsharedutils PROPERTIES OUTPUT_NAME "winsharedutils64")
|
||||||
|
71
plugins/winsharedutils/audio.cpp
Normal file
71
plugins/winsharedutils/audio.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
|
||||||
|
#define MINIAUDIO_IMPLEMENTATION
|
||||||
|
#include <miniaudio.h>
|
||||||
|
|
||||||
|
void data_callback(ma_device *pDevice, void *pOutput, const void *pInput, ma_uint32 frameCount)
|
||||||
|
{
|
||||||
|
ma_decoder *pDecoder = (ma_decoder *)pDevice->pUserData;
|
||||||
|
if (pDecoder == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ma_decoder_read_pcm_frames(pDecoder, pOutput, frameCount, NULL);
|
||||||
|
|
||||||
|
(void)pInput;
|
||||||
|
}
|
||||||
|
extern "C" __declspec(dllexport) void PlayAudioInMem_Stop(ma_decoder *decoder, ma_device *device)
|
||||||
|
{
|
||||||
|
ma_device_stop(device);
|
||||||
|
ma_device_uninit(device);
|
||||||
|
ma_decoder_uninit(decoder);
|
||||||
|
delete decoder;
|
||||||
|
delete device;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" __declspec(dllexport) int PlayAudioInMem(void *ptr, size_t len, float volume, ma_decoder **decoderet, ma_device **deviceret, float *duration)
|
||||||
|
{
|
||||||
|
ma_result result;
|
||||||
|
ma_decoder *decoder = new ma_decoder;
|
||||||
|
ma_device_config deviceConfig;
|
||||||
|
ma_device *device = new ma_device;
|
||||||
|
ZeroMemory(device, sizeof(ma_device));
|
||||||
|
ZeroMemory(decoder, sizeof(ma_decoder));
|
||||||
|
result = ma_decoder_init_memory(ptr, len, NULL, decoder);
|
||||||
|
if (result != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
delete decoder;
|
||||||
|
delete device;
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||||
|
deviceConfig.playback.format = decoder->outputFormat;
|
||||||
|
deviceConfig.playback.channels = decoder->outputChannels;
|
||||||
|
deviceConfig.sampleRate = decoder->outputSampleRate;
|
||||||
|
deviceConfig.dataCallback = data_callback;
|
||||||
|
deviceConfig.pUserData = decoder;
|
||||||
|
|
||||||
|
if (ma_device_init(NULL, &deviceConfig, device) != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
ma_decoder_uninit(decoder);
|
||||||
|
delete decoder;
|
||||||
|
delete device;
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
ma_device_set_master_volume(device, volume);
|
||||||
|
if (ma_device_start(device) != MA_SUCCESS)
|
||||||
|
{
|
||||||
|
ma_device_uninit(device);
|
||||||
|
ma_decoder_uninit(decoder);
|
||||||
|
delete decoder;
|
||||||
|
delete device;
|
||||||
|
return -4;
|
||||||
|
}
|
||||||
|
|
||||||
|
*decoderet = decoder;
|
||||||
|
*deviceret = device;
|
||||||
|
ma_uint64 frames;
|
||||||
|
ma_decoder_get_length_in_pcm_frames(decoder, &frames);
|
||||||
|
*duration = 1.0f * frames / (decoder->outputSampleRate);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user