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"]
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

View File

@ -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
self.engine = subproc_w(
'./files/plugins/shareddllproxy32.exe recordaudio "{}" "{}"'.format(
self.file, self.waitsignal
),
name="recordaudio",
)
)
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(
'<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
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()
else:
self.recorder.end()
target.setText(self.recorder.file)
self.recorder.end(callback=target.setText)
def createaddtab(self):
layout = QVBoxLayout()

View File

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

View File

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

View File

@ -54,7 +54,6 @@
"changecharset": false,
"changecharset_charset": 2
},
"ffmpeg": "",
"requestinterval": 1,
"keepontop": true,
"buttonsize": 20,

View File

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

View File

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

View File

@ -789,8 +789,6 @@
"截图后进行OCR": "Perform OCR after taking screenshots",
"优先级": "priority",
"编码": "coding",
"安装录音驱动": "Install recording driver",
"录音": "tape",
"自动TTS": "Automatic TTS",
"使用webview显示": "Display using webview"
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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}/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")

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

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

View File

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

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