From 11f370042f47acc34c41bb3ff2f31249a3da9e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=81=8D=E5=85=AE=E6=83=9A=E5=85=AE?= <101191390+HIllya51@users.noreply.github.com> Date: Sun, 19 May 2024 07:14:35 +0800 Subject: [PATCH] mem --- .gitmodules | 6 + LunaTranslator/LunaTranslator/gui/showword.py | 109 ++------ .../LunaTranslator/myutils/utils.py | 51 ++-- .../LunaTranslator/winsharedutils.py | 20 +- .../files/defaultconfig/config.json | 1 - LunaTranslator/files/lang/ar.json | 2 - LunaTranslator/files/lang/cht.json | 2 - LunaTranslator/files/lang/en.json | 2 - LunaTranslator/files/lang/es.json | 2 - LunaTranslator/files/lang/fr.json | 2 - LunaTranslator/files/lang/it.json | 2 - LunaTranslator/files/lang/ja.json | 2 - LunaTranslator/files/lang/ko.json | 2 - LunaTranslator/files/lang/pl.json | 2 - LunaTranslator/files/lang/ru.json | 2 - LunaTranslator/files/lang/th.json | 2 - LunaTranslator/files/lang/tr.json | 2 - LunaTranslator/files/lang/uk.json | 2 - LunaTranslator/files/lang/vi.json | 2 - LunaTranslator/files/lang/zh.json | 2 - plugins/CMakeLists.txt | 2 +- plugins/libs/libs.cmake | 3 + plugins/libs/miniaudio | 1 + plugins/libs/tinymp3 | 1 + plugins/shareddllproxy/CMakeLists.txt | 7 +- plugins/shareddllproxy/mp3.cpp | 248 ++++++++++++++++++ plugins/shareddllproxy/shareddllproxy.cpp | 9 +- plugins/winsharedutils/CMakeLists.txt | 2 +- plugins/winsharedutils/audio.cpp | 71 +++++ 29 files changed, 410 insertions(+), 151 deletions(-) create mode 160000 plugins/libs/miniaudio create mode 160000 plugins/libs/tinymp3 create mode 100644 plugins/shareddllproxy/mp3.cpp create mode 100644 plugins/winsharedutils/audio.cpp diff --git a/.gitmodules b/.gitmodules index 193102c4..54120b54 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,9 @@ [submodule "plugins/libs/wil"] path = plugins/libs/wil 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 diff --git a/LunaTranslator/LunaTranslator/gui/showword.py b/LunaTranslator/LunaTranslator/gui/showword.py index 976083e5..d52a4cae 100644 --- a/LunaTranslator/LunaTranslator/gui/showword.py +++ b/LunaTranslator/LunaTranslator/gui/showword.py @@ -16,9 +16,9 @@ from PyQt5.QtWidgets import ( ) from PyQt5.QtGui import QPixmap, QImage from traceback import print_exc -import requests, json, subprocess, time -from PyQt5.QtCore import pyqtSignal, Qt, QUrl -import qtawesome, functools, os, base64 +import requests, json, time +from PyQt5.QtCore import pyqtSignal, Qt +import qtawesome, functools, os, base64, winsharedutils import gobject, uuid, windows, platform from myutils.config import globalconfig, _TR, static_data import myutils.ankiconnect as anki @@ -33,38 +33,12 @@ from gui.usefulwidget import ( getcolorbutton, tabadd_lazy, ) -from myutils.subproc import subproc_w, autoproc - +from myutils.subproc import subproc_w from myutils.wrapper import threader from myutils.ocrutil import imageCut, ocr_run 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: def __init__(self): os.makedirs("./cache/tts", exist_ok=True) @@ -72,26 +46,37 @@ class loopbackrecorder: os.path.join("./cache/tts", str(time.time()) + ".wav") ) try: - if platform.architecture()[0] == "64bit": - _6432 = "64" - elif platform.architecture()[0] == "32bit": - _6432 = "32" self.waitsignal = str(time.time()) - self.engine = autoproc( - subproc_w( - './files/plugins/shareddllproxy{}.exe recordaudio "{}" "{}"'.format( - _6432, self.file, self.waitsignal - ), - name="recordaudio", - ) + self.engine = subproc_w( + './files/plugins/shareddllproxy32.exe recordaudio "{}" "{}"'.format( + self.file, self.waitsignal + ), ) except: print_exc() - def end(self): + @threader + def end(self, callback): windows.SetEvent( 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): @@ -390,49 +375,13 @@ class AnkiWindow(QWidget): getsimpleswitch(globalconfig["ankiconnect"], "autoruntts"), ) - layout.addWidget(QLabel()) - layout.addRow(_TR("录音"), QLabel()) - lb = QLabel() - lb.setOpenExternalLinks(True) - lb.setText( - 'virtual-audio-capturer' - ) - 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 def startorendrecord(self, target: QLineEdit, idx): if idx == 1: - if len(globalconfig["ffmpeg"]) and os.path.exists(globalconfig["ffmpeg"]): - self.recorder = ffmpeg_virtual_audio_capturer() - else: - self.recorder = loopbackrecorder() + self.recorder = loopbackrecorder() else: - self.recorder.end() - target.setText(self.recorder.file) + self.recorder.end(callback=target.setText) def createaddtab(self): layout = QVBoxLayout() diff --git a/LunaTranslator/LunaTranslator/myutils/utils.py b/LunaTranslator/LunaTranslator/myutils/utils.py index 9a72980f..05123be0 100644 --- a/LunaTranslator/LunaTranslator/myutils/utils.py +++ b/LunaTranslator/LunaTranslator/myutils/utils.py @@ -20,8 +20,9 @@ from myutils.config import ( savehook_new_data, getdefaultsavehook, ) +from ctypes import c_float, pointer, c_void_p import threading -import re, heapq +import re, heapq, winsharedutils from myutils.vndb import searchfordata, getvidbytitle from myutils.wrapper import tryprint @@ -260,48 +261,36 @@ class wavmp3player: if task is None: continue 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"]: 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): + def _playsoundWin(self, binary, volume): try: - - windows.mciSendString(("stop lunatranslator_mci_{}".format(self.i))) - windows.mciSendString(("close lunatranslator_mci_{}".format(self.i))) - self.i += 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 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))) + winsharedutils.PlayAudioInMem_Stop(self.lastfile[0], self.lastfile[1]) + self.lastfile = decoder, device + durationms = duration.value * 1000 except: durationms = 0 diff --git a/LunaTranslator/LunaTranslator/winsharedutils.py b/LunaTranslator/LunaTranslator/winsharedutils.py index c5a7b9f5..8a7e5c67 100644 --- a/LunaTranslator/LunaTranslator/winsharedutils.py +++ b/LunaTranslator/LunaTranslator/winsharedutils.py @@ -16,6 +16,7 @@ from ctypes import ( create_string_buffer, c_size_t, windll, + c_float, c_char, ) 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.argtypes = c_void_p, c_wchar_p 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: @@ -333,3 +337,17 @@ startmaglistener = utilsdll.startmaglistener startmaglistener.restype = HANDLE endmaglistener = utilsdll.endmaglistener 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 diff --git a/LunaTranslator/files/defaultconfig/config.json b/LunaTranslator/files/defaultconfig/config.json index 924965cc..94fa9535 100644 --- a/LunaTranslator/files/defaultconfig/config.json +++ b/LunaTranslator/files/defaultconfig/config.json @@ -54,7 +54,6 @@ "changecharset": false, "changecharset_charset": 2 }, - "ffmpeg": "", "requestinterval": 1, "keepontop": true, "buttonsize": 20, diff --git a/LunaTranslator/files/lang/ar.json b/LunaTranslator/files/lang/ar.json index 85116dbf..f8753b01 100644 --- a/LunaTranslator/files/lang/ar.json +++ b/LunaTranslator/files/lang/ar.json @@ -789,8 +789,6 @@ "截图后进行OCR": "التعرف الضوئي على الحروف", "优先级": "الأولوية", "编码": "ترميز", - "安装录音驱动": "تثبيت برنامج تشغيل التسجيل", - "录音": "تسجيل صوتي", "自动TTS": "التلقائي تحويل النص إلى كلام", "使用webview显示": "عرض باستخدام WebView" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/cht.json b/LunaTranslator/files/lang/cht.json index e233d2c7..9468500d 100644 --- a/LunaTranslator/files/lang/cht.json +++ b/LunaTranslator/files/lang/cht.json @@ -789,8 +789,6 @@ "截图后进行OCR": "截圖後進行OCR", "优先级": "優先順序", "编码": "編碼", - "安装录音驱动": "安裝錄音驅動", - "录音": "錄音", "自动TTS": "自動TTS", "使用webview显示": "使用webview顯示" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/en.json b/LunaTranslator/files/lang/en.json index 36b73a40..7d7a9664 100644 --- a/LunaTranslator/files/lang/en.json +++ b/LunaTranslator/files/lang/en.json @@ -789,8 +789,6 @@ "截图后进行OCR": "Perform OCR after taking screenshots", "优先级": "priority", "编码": "coding", - "安装录音驱动": "Install recording driver", - "录音": "tape", "自动TTS": "Automatic TTS", "使用webview显示": "Display using webview" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/es.json b/LunaTranslator/files/lang/es.json index 9a72c073..5641b665 100644 --- a/LunaTranslator/files/lang/es.json +++ b/LunaTranslator/files/lang/es.json @@ -789,8 +789,6 @@ "截图后进行OCR": "OCR después de la captura de pantalla", "优先级": "Prioridad", "编码": "Codificación", - "安装录音驱动": "Instalación de la unidad de grabación", - "录音": "Grabación", "自动TTS": "TTS automático", "使用webview显示": "Mostrar con Webview" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/fr.json b/LunaTranslator/files/lang/fr.json index 2d439931..f73e8b7f 100644 --- a/LunaTranslator/files/lang/fr.json +++ b/LunaTranslator/files/lang/fr.json @@ -789,8 +789,6 @@ "截图后进行OCR": "OCR après capture d'écran", "优先级": "Priorité", "编码": "Codage", - "安装录音驱动": "Installer le driver d'enregistrement", - "录音": "Enregistrement sonore", "自动TTS": "Tts automatique", "使用webview显示": "Afficher avec webview" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/it.json b/LunaTranslator/files/lang/it.json index 2b1caaff..32a25380 100644 --- a/LunaTranslator/files/lang/it.json +++ b/LunaTranslator/files/lang/it.json @@ -789,8 +789,6 @@ "截图后进行OCR": "Esegui OCR dopo aver scattato screenshot", "优先级": "priorità", "编码": "codifica", - "安装录音驱动": "Installa il driver di registrazione", - "录音": "nastro", "自动TTS": "TTS automatico", "使用webview显示": "Visualizzazione tramite webview" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/ja.json b/LunaTranslator/files/lang/ja.json index a9a183b4..17c10e63 100644 --- a/LunaTranslator/files/lang/ja.json +++ b/LunaTranslator/files/lang/ja.json @@ -789,8 +789,6 @@ "截图后进行OCR": "スクリーンショット後にOCR", "优先级": "優先度", "编码": "エンコード", - "安装录音驱动": "録音ドライブのインストール", - "录音": "レコーディング", "自动TTS": "自動TTS", "使用webview显示": "webview表示の使用" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/ko.json b/LunaTranslator/files/lang/ko.json index bdd6ef33..cbcb888f 100644 --- a/LunaTranslator/files/lang/ko.json +++ b/LunaTranslator/files/lang/ko.json @@ -789,8 +789,6 @@ "截图后进行OCR": "캡처해서 OCR 진행하도록 하겠습니다.", "优先级": "우선 순위", "编码": "인코딩", - "安装录音驱动": "녹음 드라이브 설치", - "录音": "녹음", "自动TTS": "자동 TTS", "使用webview显示": "웹뷰를 사용하여 표시" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/pl.json b/LunaTranslator/files/lang/pl.json index 951a1b3b..a528170d 100644 --- a/LunaTranslator/files/lang/pl.json +++ b/LunaTranslator/files/lang/pl.json @@ -789,8 +789,6 @@ "截图后进行OCR": "Wykonanie OCR po wykonaniu zrzutów ekranu", "优先级": "priorytet", "编码": "kodowanie", - "安装录音驱动": "Zainstaluj sterownik nagrywania", - "录音": "taśma", "自动TTS": "Automatyczny TTS", "使用webview显示": "Wyświetlanie przy użyciu widoku internetowego" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/ru.json b/LunaTranslator/files/lang/ru.json index 936dd5ba..3568101d 100644 --- a/LunaTranslator/files/lang/ru.json +++ b/LunaTranslator/files/lang/ru.json @@ -789,8 +789,6 @@ "截图后进行OCR": "Снимок экрана после OCR", "优先级": "Приоритеты", "编码": "Код", - "安装录音驱动": "Установка привода звукозаписи", - "录音": "Запись", "自动TTS": "Автоматический TTS", "使用webview显示": "Использовать webview" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/th.json b/LunaTranslator/files/lang/th.json index 904cbd17..4000b2d8 100644 --- a/LunaTranslator/files/lang/th.json +++ b/LunaTranslator/files/lang/th.json @@ -789,8 +789,6 @@ "截图后进行OCR": "ทำ OCR หลังจากจับภาพหน้าจอ", "优先级": "ลำดับความสำคัญ", "编码": "การเข้ารหัส", - "安装录音驱动": "ติดตั้งไดรฟ์บันทึก", - "录音": "การบันทึกเสียง", "自动TTS": "TTS อัตโนมัติ", "使用webview显示": "ใช้ webview เพื่อแสดงผล" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/tr.json b/LunaTranslator/files/lang/tr.json index c5d6f216..c92af5d8 100644 --- a/LunaTranslator/files/lang/tr.json +++ b/LunaTranslator/files/lang/tr.json @@ -789,8 +789,6 @@ "截图后进行OCR": "Ekran fotoğraflarını aldıktan sonra OCR yap", "优先级": "Prioritet", "编码": "coding", - "安装录音驱动": "Kayıt sürücüsünü kur", - "录音": "kaset", "自动TTS": "Otomatik TTS", "使用webview显示": "Web görüntüsünü kullanarak göster" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/uk.json b/LunaTranslator/files/lang/uk.json index d40a9ae8..27275c79 100644 --- a/LunaTranslator/files/lang/uk.json +++ b/LunaTranslator/files/lang/uk.json @@ -789,8 +789,6 @@ "截图后进行OCR": "Виконати OCR після роботи знімків екрана", "优先级": "пріоритет", "编码": "кодування", - "安装录音驱动": "Встановити драйвер запису", - "录音": "стрічку", "自动TTS": "Автоматичний TTS", "使用webview显示": "Показувати за допомогою веб- перегляду" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/vi.json b/LunaTranslator/files/lang/vi.json index a4dca34d..8622a8e1 100644 --- a/LunaTranslator/files/lang/vi.json +++ b/LunaTranslator/files/lang/vi.json @@ -789,8 +789,6 @@ "截图后进行OCR": "OCR sau khi chụp ảnh màn hình", "优先级": "Ưu tiên", "编码": "Mã hóa", - "安装录音驱动": "Cài đặt Recording Drive", - "录音": "Ghi âm", "自动TTS": "Tự động TTS", "使用webview显示": "Sử dụng WebView để hiển thị" } \ No newline at end of file diff --git a/LunaTranslator/files/lang/zh.json b/LunaTranslator/files/lang/zh.json index a281f896..0c90a7cc 100644 --- a/LunaTranslator/files/lang/zh.json +++ b/LunaTranslator/files/lang/zh.json @@ -789,8 +789,6 @@ "截图后进行OCR": "", "优先级": "", "编码": "", - "安装录音驱动": "", - "录音": "", "自动TTS": "", "使用webview显示": "" } \ No newline at end of file diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index faf9f693..d91db755 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -29,7 +29,7 @@ include(generate_product_version) set(VERSION_MAJOR 2) set(VERSION_MINOR 51) -set(VERSION_PATCH 7) +set(VERSION_PATCH 8) add_library(pch pch.cpp) target_precompile_headers(pch PUBLIC pch.h) diff --git a/plugins/libs/libs.cmake b/plugins/libs/libs.cmake index 14974665..9ce4c0d0 100644 --- a/plugins/libs/libs.cmake +++ b/plugins/libs/libs.cmake @@ -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}/wil/include) +include_directories(${CMAKE_CURRENT_LIST_DIR}/miniaudio) +include_directories(${CMAKE_CURRENT_LIST_DIR}/tinymp3) + if(${CMAKE_SIZEOF_VOID_P} EQUAL 4) set(LTLPlatform "Win32") diff --git a/plugins/libs/miniaudio b/plugins/libs/miniaudio new file mode 160000 index 00000000..4a5b74be --- /dev/null +++ b/plugins/libs/miniaudio @@ -0,0 +1 @@ +Subproject commit 4a5b74bef029b3592c54b6048650ee5f972c1a48 diff --git a/plugins/libs/tinymp3 b/plugins/libs/tinymp3 new file mode 160000 index 00000000..9781d63b --- /dev/null +++ b/plugins/libs/tinymp3 @@ -0,0 +1 @@ +Subproject commit 9781d63bf7d057457b25b5e77492bcf2cfa109c5 diff --git a/plugins/shareddllproxy/CMakeLists.txt b/plugins/shareddllproxy/CMakeLists.txt index c0ced5ba..d9ffed6b 100644 --- a/plugins/shareddllproxy/CMakeLists.txt +++ b/plugins/shareddllproxy/CMakeLists.txt @@ -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) if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) target_link_libraries(shareddllproxy Mfplat mfuuid ${Detours}) set_target_properties(shareddllproxy PROPERTIES OUTPUT_NAME "shareddllproxy64") else() + add_library(tinymp3 ../libs/tinymp3/shine_mp3.c) 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(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") endif() diff --git a/plugins/shareddllproxy/mp3.cpp b/plugins/shareddllproxy/mp3.cpp new file mode 100644 index 00000000..8962ecc4 --- /dev/null +++ b/plugins/shareddllproxy/mp3.cpp @@ -0,0 +1,248 @@ + +#include +#include +#include +#include +#include +#include + +#define DR_WAV_IMPLEMENTATION + +#include + +#define DR_MP3_IMPLEMENTATION + +#include + +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] \n\n"); + printf("Use \"-\" for standard input or output.\n\n"); + printf("Options:\n"); + printf(" -h this help message\n"); + printf(" -b 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; +} diff --git a/plugins/shareddllproxy/shareddllproxy.cpp b/plugins/shareddllproxy/shareddllproxy.cpp index 65bbadb1..72052060 100644 --- a/plugins/shareddllproxy/shareddllproxy.cpp +++ b/plugins/shareddllproxy/shareddllproxy.cpp @@ -1,11 +1,12 @@ #pragma comment(linker, "/subsystem:windows /entry:wmainCRTStartup") -int recordaudio(int argc, wchar_t *argv[]); int dllinjectwmain(int argc, wchar_t *argv[]); int ntleaswmain(int argc, wchar_t *wargv[]); int updatewmain(int argc, wchar_t *wargv[]); bool checkisapatch(); #ifndef _WIN64 +int recordaudio(int argc, wchar_t *argv[]); +int mainmp3(int argc, wchar_t *argv[]); int LRwmain(int argc, wchar_t *argv[]); int jbjwmain(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); if (argv0 == L"update") return updatewmain(argc - 1, argv + 1); - if (argv0 == L"recordaudio") - return recordaudio(argc - 1, argv + 1); #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") return LRwmain(argc - 1, argv + 1); else if (argv0 == L"le") diff --git a/plugins/winsharedutils/CMakeLists.txt b/plugins/winsharedutils/CMakeLists.txt index 53941200..e158075a 100644 --- a/plugins/winsharedutils/CMakeLists.txt +++ b/plugins/winsharedutils/CMakeLists.txt @@ -11,7 +11,7 @@ generate_product_version( 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) if(${CMAKE_SIZEOF_VOID_P} EQUAL 8) set_target_properties(winsharedutils PROPERTIES OUTPUT_NAME "winsharedutils64") diff --git a/plugins/winsharedutils/audio.cpp b/plugins/winsharedutils/audio.cpp new file mode 100644 index 00000000..28808c80 --- /dev/null +++ b/plugins/winsharedutils/audio.cpp @@ -0,0 +1,71 @@ + +#define MINIAUDIO_IMPLEMENTATION +#include + +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; +}