This commit is contained in:
恍兮惚兮 2024-05-19 07:14:35 +08:00
parent ee183936b7
commit 11f370042f
29 changed files with 410 additions and 151 deletions

6
.gitmodules vendored
View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -789,8 +789,6 @@
"截图后进行OCR": "التعرف الضوئي على الحروف", "截图后进行OCR": "التعرف الضوئي على الحروف",
"优先级": "الأولوية", "优先级": "الأولوية",
"编码": "ترميز", "编码": "ترميز",
"安装录音驱动": "تثبيت برنامج تشغيل التسجيل",
"录音": "تسجيل صوتي",
"自动TTS": "التلقائي تحويل النص إلى كلام", "自动TTS": "التلقائي تحويل النص إلى كلام",
"使用webview显示": "عرض باستخدام WebView" "使用webview显示": "عرض باستخدام WebView"
} }

View File

@ -789,8 +789,6 @@
"截图后进行OCR": "截圖後進行OCR", "截图后进行OCR": "截圖後進行OCR",
"优先级": "優先順序", "优先级": "優先順序",
"编码": "編碼", "编码": "編碼",
"安装录音驱动": "安裝錄音驅動",
"录音": "錄音",
"自动TTS": "自動TTS", "自动TTS": "自動TTS",
"使用webview显示": "使用webview顯示" "使用webview显示": "使用webview顯示"
} }

View File

@ -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"
} }

View File

@ -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"
} }

View File

@ -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"
} }

View File

@ -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"
} }

View File

@ -789,8 +789,6 @@
"截图后进行OCR": "スクリーンショット後にOCR", "截图后进行OCR": "スクリーンショット後にOCR",
"优先级": "優先度", "优先级": "優先度",
"编码": "エンコード", "编码": "エンコード",
"安装录音驱动": "録音ドライブのインストール",
"录音": "レコーディング",
"自动TTS": "自動TTS", "自动TTS": "自動TTS",
"使用webview显示": "webview表示の使用" "使用webview显示": "webview表示の使用"
} }

View File

@ -789,8 +789,6 @@
"截图后进行OCR": "캡처해서 OCR 진행하도록 하겠습니다.", "截图后进行OCR": "캡처해서 OCR 진행하도록 하겠습니다.",
"优先级": "우선 순위", "优先级": "우선 순위",
"编码": "인코딩", "编码": "인코딩",
"安装录音驱动": "녹음 드라이브 설치",
"录音": "녹음",
"自动TTS": "자동 TTS", "自动TTS": "자동 TTS",
"使用webview显示": "웹뷰를 사용하여 표시" "使用webview显示": "웹뷰를 사용하여 표시"
} }

View File

@ -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"
} }

View File

@ -789,8 +789,6 @@
"截图后进行OCR": "Снимок экрана после OCR", "截图后进行OCR": "Снимок экрана после OCR",
"优先级": "Приоритеты", "优先级": "Приоритеты",
"编码": "Код", "编码": "Код",
"安装录音驱动": "Установка привода звукозаписи",
"录音": "Запись",
"自动TTS": "Автоматический TTS", "自动TTS": "Автоматический TTS",
"使用webview显示": "Использовать webview" "使用webview显示": "Использовать webview"
} }

View File

@ -789,8 +789,6 @@
"截图后进行OCR": "ทำ OCR หลังจากจับภาพหน้าจอ", "截图后进行OCR": "ทำ OCR หลังจากจับภาพหน้าจอ",
"优先级": "ลำดับความสำคัญ", "优先级": "ลำดับความสำคัญ",
"编码": "การเข้ารหัส", "编码": "การเข้ารหัส",
"安装录音驱动": "ติดตั้งไดรฟ์บันทึก",
"录音": "การบันทึกเสียง",
"自动TTS": "TTS อัตโนมัติ", "自动TTS": "TTS อัตโนมัติ",
"使用webview显示": "ใช้ webview เพื่อแสดงผล" "使用webview显示": "ใช้ webview เพื่อแสดงผล"
} }

View File

@ -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"
} }

View File

@ -789,8 +789,6 @@
"截图后进行OCR": "Виконати OCR після роботи знімків екрана", "截图后进行OCR": "Виконати OCR після роботи знімків екрана",
"优先级": "пріоритет", "优先级": "пріоритет",
"编码": "кодування", "编码": "кодування",
"安装录音驱动": "Встановити драйвер запису",
"录音": "стрічку",
"自动TTS": "Автоматичний TTS", "自动TTS": "Автоматичний TTS",
"使用webview显示": "Показувати за допомогою веб- перегляду" "使用webview显示": "Показувати за допомогою веб- перегляду"
} }

View File

@ -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ị"
} }

View File

@ -789,8 +789,6 @@
"截图后进行OCR": "", "截图后进行OCR": "",
"优先级": "", "优先级": "",
"编码": "", "编码": "",
"安装录音驱动": "",
"录音": "",
"自动TTS": "", "自动TTS": "",
"使用webview显示": "" "使用webview显示": ""
} }

View File

@ -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)

View File

@ -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")

@ -0,0 +1 @@
Subproject commit 4a5b74bef029b3592c54b6048650ee5f972c1a48

1
plugins/libs/tinymp3 Submodule

@ -0,0 +1 @@
Subproject commit 9781d63bf7d057457b25b5e77492bcf2cfa109c5

View File

@ -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()

View 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;
}

View File

@ -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")

View File

@ -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")

View 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;
}